我想使用launchd每分钟运行一个python脚本。我的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.turtle.script.plist</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python</string>
<string>/Users/turtle/Desktop/turtle.py</string>
<string>/Users/turtle/Desktop/data/data.txt</string>
</array>
<key>StartInterval</key>
<integer>60</integer>
</dict>
</plist>
这个plist文件看起来不错,因为我得到以下内容:
plutil -lint com.turtle.script.plist
com.turtle.script.plist: OK
当我从命令行运行脚本时,脚本可以运行:
/usr/bin/python /Users/turtle/Desktop/turtle.py /Users/turtle/Desktop/data/data.txt
我通过以下方式加载此plist:
launchctl load -w -F com.turtle.script.plist
我也试过了:
sudo launchctl load -w -F com.turtle.script.plist
我加载此作业,python脚本应该将文件写入磁盘。但是没有生成任何文件。我用以下方式检查了这份工作:
sudo launchctl list | grep com.turtle.script.plist
输出结果为:
- 1 com.turtle.script.plist
任何人都可以帮忙解决问题吗?
答案 0 :(得分:5)
听起来脚本中存在一些环境依赖性 - 本质上,它假定一些关于它运行的环境是正确的,当你手动运行它时,而不是当launchd运行它时。在不了解脚本的情况下,很难指出这可能是什么,但我可以提出一些建议:
sudo launchctl
不是launchctl
的更强大版本,它会做一些截然不同的事情。你需要弄清楚你想要哪一个,并使用它。
当您以普通用户身份运行launchctl
时(例如launchctl load
),它会与您的launchd用户实例进行交互,以管理启动代理 - 您的用户会话中以您的用户身份运行的项目
当您以root身份运行launchctl
时(例如sudo launchctl load
),它会与launchd的系统实例进行交互,以管理启动守护程序 - 在系统上下文中以root身份运行的项目。
你必须根据这个脚本的作用来决定哪个是合适的。
检查system.log(您可以使用Console实用程序查看它,或tail -f /var/log/system.log
)并查看它是否包含任何内容以指示脚本失败的原因。
在launchd .plist中添加条目以记录脚本的输出,并查看是否包含任何错误消息或其他错误指示:
<key>StandardOutPath</key>
<string>/tmp/turtle.out</string>
<key>StandardErrorPath</key>
<string>/tmp/turtle.err</string>
编辑脚本以添加调试输出可能会有所帮助,因此您可以详细了解它是如何工作的(/不工作)。
脚本是否依赖于具有特定的工作目录和/或环境变量?如果是,请将相应的WorkingDirectory
和/或EnvironmentVariables
项添加到.plist。
答案 1 :(得分:1)
尝试写入/tmp
,可以由任何用户编写。即如果这是您的输出文件,请将/Users/turtle/Desktop/data/data.txt
更改为/tmp/my_data.txt
。
答案 2 :(得分:1)
~/Library/LaunchAgents
中的.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>local.tf.check_up</string>
<key>Program</key>
<string>/Users/tf/.bin/check_up.py</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/local.tf.check_up.stderr</string>
<key>StandardOutPath</key>
<string>/tmp/local.tf.check_up.stdout</string>
<key>StartInterval</key>
<integer>60</integer>
<key>WorkingDirectory</key>
<string>/tmp/</string>
</dict>
</plist>
您的脚本/Users/tf/.bin/check_up.py
:
#!/opt/local/bin/python
f = open('/Users/tf/Desktop/test.txt', 'a')
f.write('hello again 4\n')
f.close()
请注意,我使用的是来自python
的MacPorts的/opt/local/bin/
。如果您使用不同的python解释器,请将上面的行替换为$ which python
返回的任何内容。
确保您的脚本是可执行的,并且只有您具有写访问权限:
$ chmod 755 ~/.bin/check_up.py
测试脚本:运行它并看到它按预期工作:
$ ~/.bin/check_up.py
加载LaunchAgent:
$ launchctl load ~/Library/LaunchAgents/local.tf.check_up.plist