【问题标题】:How can you start a LaunchAgent for the first time without rebooting, when your code runs as a LaunchDaemon?当您的代码作为 LaunchDaemon 运行时,如何在不重新启动的情况下首次启动 LaunchAgent?
【发布时间】:2011-12-15 07:50:05
【问题描述】:

我有一个 LaunchDaemon。当它运行时,它会检查是否安装了 SIMBL。如果没有安装 SIMBL,它会使用 NSTask 在 SIMBL.pkg 上运行 /usr/sbin/installer。

SIMBL 的 postflight 脚本然后尝试运行 launchctl load 命令以立即启动 SIMBL 的 LaunchAgent:

sudo -u "$USER" -- /bin/launchctl load -F -S Aqua -D user "${LAUNCHD_PLIST}"

这失败了,因为我的 LaunchDaemon 的 NSTask 环境没有设置 $USER。

如果我让我的守护进程使用系统配置框架检测当前用户并使用 setEnvironment 将其传递给 NSTask,launchctl 就会出现错误:

Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1

我意识到,根据定义,守护进程不应该在用户会话中运行。出于同样的原因,Apple 似乎推荐 LaunchAgents 作为 LaunchDaemons 的辅助对象,以完成用户会话工作。有没有办法让这样的代理立即启动并运行?

我将所有 .plist 都放在正确的位置(它们在重新启动后开始运行,下次 launchctl 进行常规加载时)所以我的第一个想法就是告诉 launchctl 重新加载。但是all the code to do that is commented out in launchctl.c

//  { "reload",         reload_cmd,             "Reload configuration files and/or directories" },

...

 * In later versions of launchd, I hope to load everything in the first pass,
 * then do the Bonjour magic on the jobs that need it, and reload them, but for now,
 * I haven't thought through the various complexities of reloading jobs, and therefore
 * launchd doesn't have reload support right now.

【问题讨论】:

    标签: macos daemon nstask launchd


    【解决方案1】:

    哦,launchd 怎么让我发疯......

    切入正题,经过大量研究和实验,我在 10.5+ 上就是这样:

    # If possible, tell launchd to start the LaunchAgent. This will fail on 10.4.
    # $F[0] is the pid
    # $F[1] is the username
    # $F[2] is the first word of the command
    ps -ww -A -opid,user,command | \
      perl -nae 'if($F[2] =~ /\bloginwindow\b/) { system(
        qq(launchctl bsexec $F[0] su $F[1] -c "launchctl load -w <your_plist>"))
    }'
    

    我发现没有办法直接在 10.4 上实现这一点。我在 10.4 上作弊,只运行 LaunchAgent 会运行的东西,即使它有一个 GUI,而且你不应该这样做(无论如何你可以在 10.4-10.6 中;你不能在 10.7 中)。在 10.4 上,LaunchAgent 会在下次重新启动后正常工作。

    以上代码查找loginwindow 进程并使用bsexec 在这些上下文中运行命令。请记住,使用快速用户切换,可以有多个上下文。

    一些有用的链接:

    IMO,launchd 是 Apple 部署过的最糟糕的“好主意”之一。这个想法非常有用,但是 API 很糟糕。

    【讨论】:

    • 使用 OS X "El Capitan" 10.11 (15A204h) 似乎 "launchctl bsexec" 不再起作用了。是否有需要执行此步骤的原因?
    • 这是在正确的上下文中重新启动代理的部分。没有它,您不会按照 OP 的要求重新启动。我不知道 10.11 有什么方法(如果有的话)。
    • 似乎有办法在 10.11 上做到这一点:launchctl bootstrap gui/`stat -f %u` &lt;your-agent-plist-file-path&gt;。来自stackoverflow.com/questions/1106638/…
    猜你喜欢
    • 2013-12-12
    • 2011-09-07
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    相关资源
    最近更新 更多