You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cocoa应用在macOS High Sierra 10.13.4获Root权限改系统文件出错求助

解决macOS High Sierra 10.13.4下AuthorizationExecuteWithPrivileges报错-60031及Root权限获取方案

首先,你遇到的errAuthorizationToolExecuteFailure(错误码-60031)问题,大概率和几个核心因素有关,咱们一步步拆解解决:

一、先修复当前代码的问题

你的代码里用到的AuthorizationExecuteWithPrivileges其实在macOS 10.10之后就被Apple标记为废弃API了,在High Sierra版本中它的兼容性已经很差,这是触发错误的主要原因之一。另外还有几个细节需要排查:

  1. 确认工具路径的正确性
    务必保证传入的path是绝对路径,比如"/usr/bin/touch"而不是相对路径或者仅写"touch"——系统找不到工具的准确位置就会直接抛出这个错误。你可以在调用函数前加个校验:

    if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:NO]) {
        NSLog(@"工具路径不存在: %@", path);
        return errAuthorizationInvalidTool;
    }
    
  2. 替换废弃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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:22:29