我有一个自定义的 launchd 作业设置,在目录更改时运行。它已经运行了相当长一段时间,直到最近(2011 年 7 月 28 日)它一直运行良好。然而,我刚刚意识到,该作业不再由路径修改触发。
这是我的启动 plist(/Library/LaunchDaemons/com.mydomain.myscript.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>com.mydomain.myscript</string>
<key>LowPriorityIO</key>
<true/>
<key>Nice</key>
<integer>20</integer>
<key>Program</key>
<string>/path/to/myscript.sh</string>
<key>RunAtLoad</key>
<false/>
<key>StandardErrorPath</key>
<string>/Library/Logs/myscript.log</string>
<key>StandardOutPath</key>
<string>/Library/Logs/myscript.log</string>
<key>ThrottleInterval</key>
<integer>60</integer>
<key>UserName</key>
<string>adminuser</string>
<key>WatchPaths</key>
<array>
<string>/Volumes/MyDisk/Watch</string>
</array>
</dict>
</plist>
我仔细检查了所有我能想到的事情:
最近监视的目录中出现了各种各样的活动(新文件),这些活动在过去总是会触发该作业:
$ ls -ld /Volumes/MyDisk/Watch
drwxrwxr-x 93 adminuser admingrp 3162 Aug 3 16:08 /Volumes/MyDisk/Watch
工作处于活动状态:
$ sudo launchctl list | grep mydomain
- 0 com.mydomain.myscript
我的脚本位于正确的位置,可执行,并且在以正确的用户身份手动运行时运行良好。日志文件显示了 launchd 上次执行我的脚本的日期:
$ cat /Library/Logs/myscript.log
<snip>
[2011-07-27 08:04:27] running...
[2011-07-27 08:06:33] running...
[2011-07-27 08:07:33] running...
[2011-07-27 20:58:15] running...
[2011-07-28 21:10:18] running...
我最近确实对机器进行了软件更新,所以我检查了那里发生了什么变化......
$ cat /Library/Logs/Software\ Update.log
<snip>
2011-06-15 08:13:31 -0400: Installed "Java for Mac OS X 10.5 Update 9" (1.0)
2011-07-29 15:39:24 -0400: Installed "Java for Mac OS X 10.5 Update 10" (1.0)
2011-07-29 15:40:55 -0400: Installed "Safari" (5.0.6)
2011-07-29 15:45:46 -0400: Installed "Security Update 2011-004" (1.0)
2011-07-29 15:47:10 -0400: Installed "iTunes" (10.4)
然而,“安全更新 2011-004”看起来非常可疑知识库文章没有提及有关 launchd 的任何内容。
有什么建议么?
系统版本:Mac OS X Server 10.5.8 (9L30)
编辑:
好的,经过一番折腾和研究,我发现了问题所在。当机器重新启动时(在这种情况下是由于软件更新),就会发生这种情况(launchd 无法监控路径更改)。在查看旋转系统日志时,我发现这个 launchd 错误在机器启动后仅几秒内就出现了:
Aug 1 07:37:12 localhost kernel[0]: Darwin Kernel Version 9.8.0: ...
<snip>
Aug 1 07:37:17 localhost com.apple.launchd[1] (com.mydomain.myscript): Path monitoring failed on "/Volumes/MyDisk/Watch": No such file or directory
这里真正的问题是 launchd 应该监视的路径存在于外部(FireWire)卷上,并且 launchd 作业是在启动时加载的前卷已挂载。我个人认为这是一个 launchd 错误,因为我认为 launchd 会将该路径视为“未修改”如果该路径不存在,并且只是在那一刻不运行该作业。相反,launchd 从此时起完全忽略了该路径,并且该作业永远处于闲置状态。
所以我现在的问题是:在告诉 launchd 监视路径之前,有什么好方法可以确保磁盘安装?
答案1
火线磁盘可能会在系统启动时出现和消失多次 - 它的本质是可移动的,不是吗?
使用一个小扩展,你应该能够适应 launchd 的工作方式,以及它启动的时间(很早,在你的磁盘到达之前)。设置第二个脚本,
- 监视 /Volumes 的变化
- 如果发生某些变化,并且脚本被触发,请检查发生了什么
- 如果不是你的磁盘:再去睡觉
- 如果出现的是您的磁盘:加载目录观察器(您的原始目录观察器)
- 如果是你的磁盘消失:卸载观察程序