使用GUI会话为所有用户启动/停止launchd代理

Law*_*ton 11 macos daemon launchd agent launchdagent

我需要能够从根级别守护程序启动/停止每会话GUI代理.

这里,这里这里讨论类似的问题.

我希望能够做的基本上是

for num in `ps ax | grep [s]bin/launchd | cut -c 1-5`; 
do 
    if [ $num -ne 1 ]; 
    then 
        sudo launchctl bsexec $num launchctl (un)load -S Aqua /Library/LaunchAgents/com.mycompany.mydaemon.plist; 
    fi; 
done
Run Code Online (Sandbox Code Playgroud)

但这仅启动/停止一个实例,并在当前GUI会话中以root身份运行.如果我离开sudo,我就会开始

task_for_pid() (os/kern) failure
Couldn't switch to new bootstrap port: (ipc/send) invalid port right
Run Code Online (Sandbox Code Playgroud)

我已经尝试过使用bsexec的各种其他排列(包括使用load/unload命令从bsexec调用辅助脚本),但是我永远不能让实例以root身份启动,而不能在另一个GUI会话中启动.

我也试图与乱搞su - <user> ...sudo -u <user> ...,但没有运气有两种(如很多人在上面链接的文章和其他地方的讨论).

有人有什么想法吗?

编辑:我尝试使用Graham Lee下面建议的包装工具执行此操作,但是我收到以下错误:

launch_msg(): Socket is not connected
Run Code Online (Sandbox Code Playgroud)

这是我正在使用的命令行命令,包装器和脚本(501是用户ID,63093是另一个登录到系统的用户的launchd的pid):

命令行:

sudo launchctl bsexec 63093 /path/TestSetUIDAndExecuteTool 501 /path/LoadBillingDialogAgent
Run Code Online (Sandbox Code Playgroud)

包装:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  if (argc != 3) {
    NSLog(@"Tool called with improper arguments");
    return -1;
  }

  int uid = [[NSString stringWithUTF8String:argv[1]] intValue];
  // TODO: REMOVE
  NSLog(@"Setting uid to |%i|", uid);

  setuid(uid);
  // TODO: REMOVE
  char *command = (char *)argv[2];
  NSLog(@"Executing command |%s|", command);
  system(command);

  [pool drain];
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

脚本:

/bin/launchctl load -S Aqua /Library/LaunchAgents/com.company.agent.plist
Run Code Online (Sandbox Code Playgroud)

小智 6

使用launchctl bsexec是正确的,但您需要启动一个包装工具,在运行"真正的"代理可执行文件之前将UID丢弃给目标用户.哦,寻找loginwindow流程可能更好,因为那些是登录会话的领导者(尽管launchd很可能也会工作).