在OS X中使用NSTask在特定用户下运行“launchctl”命令

时间:2014-06-09 13:25:33

标签: objective-c daemon nstask start-stop-daemon

我的应用程序是在root下启动的,我需要能够使用NSTask和launchctl卸载进程 这是我做的代码:

    NSPipe *pipe = [NSPipe pipe];

    NSTask *task = [[NSTask alloc] init];
    [task setLaunchPath: @"/bin/launchctl"];
    [task setCurrentDirectoryPath:@"/"];
    [task setStandardError:pipe];

    NSLog(@"/bin/launchctl unload %@", plistAutostartLocation);

    NSArray *arguments;
    arguments = [NSArray arrayWithObjects: enableCommand, plistAutostartLocation, nil];
    [task setArguments: arguments];

    NSFileHandle * read = [pipe fileHandleForReading];

    [task launch];
    [task waitUntilExit];

如果需要卸载进程是在" root"下启动的。如果没有失败,它会成功卸载。 问题是如何运行" launchctl"在特定用户下(例如" myusername")?

编辑: 在终端,如果我想在特定用户下运行一些命令,我​​接下来做的很好:

  

su - myusername -c" ls / Users / myusername"

但是,当我尝试运行" launchctl"在特定用户下它失败了:

  

su - myusername -c" launchctl load /Library/LaunchAgents/com.google.keystone.agent.plist"

它说:"没有找到任何东西加载"

1 个答案:

答案 0 :(得分:1)

您的上一个命令失败与引导名称空间有关,您试图在错误的引导程序命名空间中加载代理程序。系统正在创建两个不同的引导名称空间,摘自Apple documentation

  

值得注意的是 GUI和非GUI每会话之间的区别   引导名称空间。 GUI每会话引导程序命名空间是   由GUI基础架构实例化(loginwindowWindowServer)   当用户通过GUI登录时。非GUI每会话引导程序   用户通过SSH登录时创建名称空间。虽然没有   这些命名空间,基于GUI的服务之间的根本区别,   像Dock一样,只在GUI每会话引导程序中注册自己   命名空间。

su命令未在launchd使用的同一个bootsrap命名空间中启动。

有两种方法可以运行一个命令,就像你想在正确的bootstrap命名空间中运行一样:

  • 10.10及以上:使用launchctl asuser。这将运行由指定的<myusername>启动的任何命令。值得一提的是,您必须以root身份运行它,否则命令将失败。你的上一个命令应该像这样运行:

     launchctl asuser <myusername> launchctl load "/Library/LaunchAgents/com.google.keystone.agent.plist"
    
  • 10.10及以下(自10.11起,SIP阻止此方法):使用launchctl bsexec。这需要一个进程id来检索正确的命名空间,在该命名空间中运行另一个命令。此外,您必须手动更改命令的UID,如下所示:

    launctl bsexec <pid> su -u <myusername> launchctl load "/Library/LaunchAgents/com.google.keystone.agent.plist"