5

我的应用程序在 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 - 我的用户名 -c "ls /用户/我的用户名"

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

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

它说:“没有发现加载”

4

1 回答 1

2

您最后一个命令的失败与引导命名空间有关,您试图将代理加载到错误的引导命名空间中。系统正在创建两个不同的引导命名空间,摘自Apple 文档

值得注意的是GUI 和非 GUI 每会话引导命名空间之间的区别。当用户通过 GUI 登录时,GUI 基础结构 (loginwindow和)实例化 GUI 每会话引导命名空间。WindowServer当用户通过 SSH 登录时,会创建一个非 GUI 每会话引导命名空间。虽然这些命名空间之间没有根本区别,但基于 GUI 的服务(如 Dock)仅在 GUI 每次会话引导命名空间中注册。

su命令未在launchd.

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

  • 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"
    
于 2017-03-15T08:37:09.130 回答