【问题标题】:Launchctl minimal working example with Python使用 Python 的 Launchctl 最小工作示例
【发布时间】:2013-04-13 17:06:16
【问题描述】:

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

谁能帮忙解决问题?

【问题讨论】:

  • 有什么问题?你从来没有真正说过。
  • 更新了问题。问题是代码永远不会执行它的预期目标——将文件写入磁盘。

标签: python macos launchd


【解决方案1】:

听起来脚本内部存在一些环境依赖性——本质上,它假定它运行的环境在您手动运行时是正确的,但在 launchd 运行时却不是。在对脚本一无所知的情况下,很难指出这可能是什么,但我可以提出一些建议:

  • sudo launchctl 不是launchctl 的更强大版本,它做了一些明显不同的事情。你需要弄清楚你想要哪一个,然后使用它。

    当您以普通用户(例如 launchctl load)的身份运行 launchctl 时,它会与您的 launchd 用户实例交互以管理启动代理——在您的用户会话中以您的用户身份运行的项目。

    当您以 root 身份运行 launchctl(例如 sudo launchctl load)时,它会与 launchd 的系统实例交互以管理启动守护进程——以 root 身份在系统上下文中运行的项目。

    您必须根据此脚本的功能来决定哪个是合适的。

  • 检查 system.log(您可以使用控制台实用程序查看它,或使用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。

【讨论】:

  • 谢谢。在你的帮助下,我让它工作了。问题是一个环境变量。
【解决方案2】:

尝试写信给任何用户都可以写的/tmp。即将/Users/turtle/Desktop/data/data.txt 更改为/tmp/my_data.txt 如果这是您的输出文件。

【讨论】:

    【解决方案3】:

    ~/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()
    

    请注意,我使用来自 MacPorts 的 python,它位于 /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
    

    【讨论】:

      猜你喜欢
      • 2018-08-28
      • 1970-01-01
      • 2013-10-08
      • 2022-10-03
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      • 2018-03-30
      • 2019-05-23
      相关资源
      最近更新 更多