从LaunchAgent plist在后台运行文件?

时间:2017-01-07 02:48:56

标签: bash macos plist launch

我有这段代码:

<?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>

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

1 个答案:

答案 0 :(得分:0)

chepner的评论是关于直接问题的:你传递的脚本名称是错误的。在-c选项之后,bash期望包含要执行的命令的单个参数(可选地后跟要传递给它的参数,从$0开始)。如果要执行多个命令,则需要将它们组合为单个复合命令,如/Users/qwe/Music/meta.sh & /Users/qwe/Music/seta.sh

但我认为你也使用了launchd错误。 Launchd真的打算启动流程,然后监控它们;这要求他们留在前台。在发射下背景的东西往往会混淆它,导致奇怪的问题。例如,考虑我上面给出的命令字符串。它在后台运行meta.sh,在前台运行seta.sh。你说meta.sh是一个长期运行的过程,但我认为seta.sh只是完成它的工作并退出?如果是这样,launchd将看到seta.sh(前台进程)退出,认为任何子进程(meta.sh)是剩余的孤儿,它应该“清理它们”,即杀死它们。糟糕,meta.sh不再长时间运行。

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

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

<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中,而不是让“脚本”等待后台进程完成:

<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没有意识到还有后台进程,并且在某些情况下它可能会尝试再次运行该作业,导致两个(或更多)后台进程... < / p>