使用Python启动最小的工作示例

时间:2013-04-13 17:06:17

标签: python macos launchd

我想使用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

任何人都可以帮忙解决问题吗?

3 个答案:

答案 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