自定义Mac App中sudo cp执行失败,终端运行正常的原因及解决
问题描述
在Mac上通过以下步骤创建了自定义App1.app:
- 切换到桌面并创建App1.app文件夹(替换
<your_user>为你的Mac用户名):
cd /Users/<your_user>/Desktop mkdir App1.app
- 进入该目录:
cd App1.app
- 创建脚本文件:
touch App1
- 用
vi App1编辑脚本内容:
#!/bin/sh export PASSWORD=<替换为你的root密码> # 替换为目标应用的Info.plist路径,比如WhatsApp的路径 export FILE_PATH=/Applications/WhatsApp.app/Contents/Info.plist echo "$PASSWORD" | sudo -S cp "$FILE_PATH" "${FILE_PATH}.backup" echo "$PASSWORD" | sudo -S cp "$FILE_PATH" "/Users/<your_user>/Desktop/Info_plist.backup" exit
- 保存退出后修改权限:
chown -R root:wheel .
现象:
- 双击桌面的App1.app或用
open /Users/<your_user>/Desktop/App1.app运行时,仅能成功复制桌面的备份文件,无法复制应用内的Info.plist.backup,报错:
+ export PASSWORD=<我的root密码> + PASSWORD=<我的root密码> + export FILE_PATH=/Applications/WhatsApp.app/Contents/Info.plist + FILE_PATH=/Applications/WhatsApp.app/Contents/Info.plist + echo <我的root密码> + sudo -S cp /Applications/WhatsApp.app/Contents/Info.plist /Applications/WhatsApp.app/Contents/Info.plist.backup Password:cp: /Applications/WhatsApp.app/Contents/Info.plist.backup: Operation not permitted
- 直接在终端执行
/Users/<your_user>/Desktop/App1.app/App1时,两个文件都能复制成功:
+ export PASSWORD=<我的root密码> + PASSWORD=<我的root密码> + export FILE_PATH=/Applications/WhatsApp.app/Contents/Info.plist + FILE_PATH=/Applications/WhatsApp.app/Contents/Info.plist + echo <我的root密码> + sudo -S cp /Applications/WhatsApp.app/Contents/Info.plist /Applications/WhatsApp.app/Contents/Info.plist.backup Password:+ echo <我的root密码> + sudo -S cp /Applications/WhatsApp.app/Contents/Info.plist /Users/acayon/Desktop/Info_plist.backup + exit
已尝试给App1配置与Terminal相同的权限(包括完全磁盘访问),但问题依旧。
解决方案
1. 给App1.app添加代码签名
Mac对未签名的应用会施加更严格的沙箱限制,即使手动添加权限也可能不生效。可以用自签名证书给App签名:
- 打开「钥匙串访问」→ 菜单栏「钥匙串访问」→「证书助理」→「创建证书」
- 名称填
MyDeveloperCert,证书类型选「代码签名」,勾选「让我覆盖这些默认值」,一路下一步直到完成 - 在终端执行签名命令(替换
<your_user>):
codesign -s "MyDeveloperCert" /Users/<your_user>/Desktop/App1.app
签名完成后,重新尝试运行App1.app。
2. 确保App1获得完整的「完全磁盘访问」权限
- 打开「系统设置」→「隐私与安全性」→「完全磁盘访问」
- 点击左下角锁图标解锁,点击「+」按钮,找到桌面的App1.app并添加进去
- 重启App1.app,或者重启系统确保权限生效
3. 避免硬编码密码(可选但推荐)
脚本里硬编码root密码存在安全风险,可以修改为让用户输入密码,或者配置sudo免密(需谨慎):
- 修改脚本内容:
#!/bin/sh # 替换为目标应用的Info.plist路径 export FILE_PATH=/Applications/WhatsApp.app/Contents/Info.plist sudo cp "$FILE_PATH" "${FILE_PATH}.backup" sudo cp "$FILE_PATH" "/Users/<your_user>/Desktop/Info_plist.backup" exit
这样运行时会弹出密码输入框,更安全。
4. 用Plist文件配置App权限(进阶)
如果上述方法无效,可以给App1.app添加Info.plist文件,声明需要的权限:
- 在App1.app目录下创建
Contents文件夹,再在其中创建Info.plist:
mkdir -p /Users/<your_user>/Desktop/App1.app/Contents touch /Users/<your_user>/Desktop/App1.app/Contents/Info.plist
- 编辑
Info.plist内容:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleExecutable</key> <string>App1</string> <key>CFBundleName</key> <string>App1</string> <key>CFBundleIdentifier</key> <string>com.yourname.App1</string> <key>CFBundleVersion</key> <string>1.0</string> <key>NSAppleEventsUsageDescription</key> <string>需要访问磁盘文件以完成备份操作</string> <key>NSFilePathUsageDescription</key> <string>需要访问应用目录以创建备份</string> </dict> </plist>
- 重新签名App,然后测试运行。
内容的提问来源于stack exchange,提问作者Asier Cayón Francisco
相关产品推荐
相关产品推荐

