12

我需要能够从根级守护进程启动/停止每个会话的 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

但这只会启动/停止一个实例,并在当前 GUI 会话中以 root 身份运行。如果我离开 sudo 那里开始我得到

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

我尝试过处理 bsexec 的各种其他排列(包括使用 load/unload 命令从 bsexec 调用辅助脚本),但我永远无法让实例以 root 以外的任何方式启动,也永远无法在另一个 GUI 会话中启动.

我也尝试过使用su - <user> ...and sudo -u <user> ...,但也没有运气(正如许多人在上面链接的文章和其他地方所讨论的那样)。

有人有什么想法吗?

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

launch_msg(): Socket is not connected

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

命令行:

sudo launchctl bsexec 63093 /path/TestSetUIDAndExecuteTool 501 /path/LoadBillingDialogAgent

包装:

#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;
}

脚本:

/bin/launchctl load -S Aqua /Library/LaunchAgents/com.company.agent.plist
4

4 回答 4

6

使用launchctl bsexec是正确的,但您需要启动一个包装工具,在运行“真实”代理可执行文件之前将 UID 放到目标用户。哦,寻找loginwindow进程可能会更好,因为它们是登录会话的领导者(尽管launchd也很可能工作)。

于 2009-07-09T21:55:12.720 回答
4

看起来每个用户启动的实例与从终端启动的 launchctl 不在同一个引导命名空间中运行。

通过使用 Dock.app 作为 pid 捐助者和一些 sudo 魔法:

ps aux | grep Dock.app | grep -v grep | awk '{system("sudo launchctl bsexec "$2" sudo -u "$1" launchctl load -S Aqua /Library/LaunchAgents/com.my.agent.plist")}'

可以在所有正在运行的会话中启动代理。

不整洁,但有效。

更新:不适用于 10.7。是的,代理将被启动,但正如我从测试中看到的那样,不是在正确的上下文中。

于 2011-05-28T19:06:07.417 回答
3

根据这里的讨论和这个脚本,我认为不需要包装工具。这两个 bash 脚本也可以帮助其他人。

卸载代理

#!/bin/bash
for id in `ps aux | grep -v grep | grep MyAgent | awk {'print $2'}`
do
    launchctl bsexec $id launchctl unload /Library/LaunchAgents/myAgent.plist
done

将“MyAgent”替换为您的 Launch Agent 的名称。

负载代理

#!/bin/bash
for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do

    pid=$(echo $pid_uid | cut -d, -f1)
    uid=$(echo $pid_uid | cut -d, -f2)

    launchctl bsexec "$pid" chroot -u "$uid" / launchctl load /Library/LaunchAgents/myAgent.plist
done

从根守护程序调用,这将为所有登录用户加载和卸载 myAgent.plist 中引用的启动代理。

请注意,由于 OS X El Capitan (10.11) 中的“无根”,使用 bsexec 可能不再有效,但直到 10.10,这应该没问题。

于 2015-07-21T09:00:24.833 回答
1

我有同样的问题。要解决此问题,请使用“under”launchd 的 pid,即已启动的进程的 pid。

您提交给“launchctl bsexec”的 pid 用于查找正确的引导程序。如果您使用 launchd 的 pid(来自用户上下文),那么您在 root launchd 引导程序中工作。如果你使用 pe. Finder 或用户的 Dock pid,您可以在此“每用户”引导程序中工作

于 2014-09-02T09:40:03.863 回答