运行 来自 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" 永远不会 运行。在终端中执行此操作时,我可以简单地使用 & 符号在后台创建文件 运行,但我尝试在文件名末尾使用 &
,但它并没有真正起作用。有人可以帮我吗?谢谢!!
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 & /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 & /Users/qwe/Music/seta.sh</string>
</array>
<key>AbandonProcessGroup</key>
<true/>
...但这有一个缺点,即 launchd 没有意识到还有一个后台进程遗留下来,在某些情况下它可能会再次尝试 运行 作业,导致两个(或更多)后台进程...
我有这个代码:
<?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" 永远不会 运行。在终端中执行此操作时,我可以简单地使用 & 符号在后台创建文件 运行,但我尝试在文件名末尾使用 &
,但它并没有真正起作用。有人可以帮我吗?谢谢!!
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 & /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 & /Users/qwe/Music/seta.sh</string>
</array>
<key>AbandonProcessGroup</key>
<true/>
...但这有一个缺点,即 launchd 没有意识到还有一个后台进程遗留下来,在某些情况下它可能会再次尝试 运行 作业,导致两个(或更多)后台进程...