Cocoa应用在macOS High Sierra 10.13.4获Root权限改系统文件出错求助
首先,你遇到的errAuthorizationToolExecuteFailure(错误码-60031)问题,大概率和几个核心因素有关,咱们一步步拆解解决:
一、先修复当前代码的问题
你的代码里用到的AuthorizationExecuteWithPrivileges其实在macOS 10.10之后就被Apple标记为废弃API了,在High Sierra版本中它的兼容性已经很差,这是触发错误的主要原因之一。另外还有几个细节需要排查:
确认工具路径的正确性
务必保证传入的path是绝对路径,比如"/usr/bin/touch"而不是相对路径或者仅写"touch"——系统找不到工具的准确位置就会直接抛出这个错误。你可以在调用函数前加个校验:if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:NO]) { NSLog(@"工具路径不存在: %@", path); return errAuthorizationInvalidTool; }替换废弃API为官方推荐写法
既然AuthorizationExecuteWithPrivileges已经被淘汰,咱们换成Apple推荐的posix_spawn配合授权机制,修改后的代码如下:OSStatus LaunchPrivilegedProcess(NSString *path) { OSStatus status; AuthorizationRef authorizationRef; status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); if (status != errAuthorizationSuccess) { NSLog(@"创建初始授权失败: %d", status); return status; } AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0}; AuthorizationRights rights = {1, &right}; AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL); if (status != errAuthorizationSuccess) { NSLog(@"获取权限失败: %d", status); AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); return status; } const char *toolPath = path.UTF8String; char *const args[] = {(char *)toolPath, NULL}; posix_spawnattr_t spawnAttr; posix_spawnattr_init(&spawnAttr); status = AuthorizationApplyAuthorizationToSpawn(authorizationRef, &spawnAttr); if (status != errAuthorizationSuccess) { NSLog(@"应用授权到Spawn失败: %d", status); posix_spawnattr_destroy(&spawnAttr); AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); return status; } pid_t pid; status = posix_spawn(&pid, toolPath, NULL, &spawnAttr, args, NULL); if (status != 0) { NSLog(@"Spawn进程失败: %d", status); posix_spawnattr_destroy(&spawnAttr); AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); return status; } posix_spawnattr_destroy(&spawnAttr); AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); return errAuthorizationSuccess; }
二、其他获取Root权限修改系统文件的合规方法
如果你的需求是长期运行特权任务,或者需要更符合Apple规范的方式,推荐以下几种方案:
1. SMJobBless(Apple官方首选方案)
这是Apple认可的安装特权守护进程的标准方式,适合需要后台长期运行的特权任务。核心步骤:
- 创建符合要求的特权XPC守护进程,在其Info.plist中配置
SMJobBless相关键值 - 在主应用的Info.plist中关联对应的守护进程信息
- 调用
SMJobBless函数完成安装,用户会看到系统级的授权弹窗,授权后守护进程将以Root权限运行
这种方式完全符合Apple的沙盒与权限规则,不会被系统拦截,也无需关闭系统安全机制。
2. 临时关闭系统完整性保护(SIP,仅推荐测试场景)
如果只是临时测试修改系统文件,可以临时关闭SIP,但会降低系统安全性:
- 重启Mac,按住Command+R进入恢复模式
- 打开终端,执行
csrutil disable - 重启后即可修改系统目录,测试完成后务必执行
csrutil enable重新开启SIP
3. 使用AppleScript的do shell script(适合简单一次性任务)
在Objective-C中可以通过NSAppleScript调用带管理员权限的Shell命令,示例代码:
NSAppleScript *script = [[NSAppleScript alloc] initWithSource:@"do shell script \"touch /System/TestFile\" with administrator privileges"]; NSDictionary *errorInfo = nil; NSAppleEventDescriptor *result = [script executeAndReturnError:&errorInfo]; if (errorInfo) { NSLog(@"执行失败: %@", errorInfo); }
这种方式适合简单的一次性操作,但不适合复杂的进程调用场景。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

