运行 来自 LaunchAgent plist 的后台文件?

Run file in background from LaunchAgent plist?

我有这个代码:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>updater.Keychain.plist.sh</string>
    <key>ProgramArguments</key>
    <array>
        <string>bash</string>
        <string>-c</string>
        <string>/Users/qwe/Music/meta.sh</string>
        <string>/Users/qwe/Music/seta.sh</string>

    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

问题是 "meta.sh" 是一个永无止境的脚本,它每 5 秒检查一次是否有特定的事情发生,因此 "seta.sh" 永远不会 运行。在终端中执行此操作时,我可以简单地使用 & 符号在后台创建文件 运行,但我尝试在文件名末尾使用 &amp;,但它并没有真正起作用。有人可以帮我吗?谢谢!!

chepner 对当前问题的评论是正确的:您将脚本名称传递给 bash 是错误的。在 -c 选项之后,bash 需要一个包含要执行的命令的参数(可选地后跟要传递给它的参数,以 [=13=] 开头)。如果要执行多个命令,则需要将它们组合成一个复合命令,如 /Users/qwe/Music/meta.sh & /Users/qwe/Music/seta.sh.

但我认为您也错误地使用了 launchd。 Launchd 的真正目的是启动进程,然后监视它们;这要求他们留在前台。从 under launchd 中脱颖而出的事情往往会混淆它,从而导致奇怪的问题。例如,考虑我上面给出的命令字符串。它 运行 在后台 meta.sh,在前台 seta.sh。你说 meta.sh 是一个漫长的 运行ning 过程,但我假设 seta.sh 只是完成它的工作并退出?如果是这样,launchd 将看到 seta.sh(前台进程)已经退出,认为任何子进程(meta.sh)都是剩余的孤儿,它应该 "clean them up",即杀死它们。糟糕,meta.sh不再是长-运行ning.

如果你真的只想启动 meta.sh 和 seta.sh,最好为它们创建两个单独的启动项(即两个 .plist 文件)。

如果出于某种原因需要 运行 它们在一起,最好的方法可能是本质上创建一个小脚本,运行 将它们 然后等待既要退出 ,又要将 "script" 传递给 bash 作为 -c 选项的参数。请注意,这意味着整个 "script" 必须位于 ProgramArguments 数组中的单个 string 中:

<key>ProgramArguments</key>
<array>
    <string>bash</string>
    <string>-c</string>
    <string>/Users/qwe/Music/meta.sh &amp; /Users/qwe/Music/seta.sh; wait</string>
</array>

另一种可能性是将 AbandonProcessGroup 键添加到 .plist,而不是让 "script" 等待后台进程完成:

<key>ProgramArguments</key>
<array>
    <string>bash</string>
    <string>-c</string>
    <string>/Users/qwe/Music/meta.sh &amp; /Users/qwe/Music/seta.sh</string>
</array>
<key>AbandonProcessGroup</key>
<true/>

...但这有一个缺点,即 launchd 没有意识到还有一个后台进程遗留下来,在某些情况下它可能会再次尝试 运行 作业,导致两个(或更多)后台进程...