Launchctl минимальный рабочий пример с Python
Я хотел бы запускать скрипт на Python каждую минуту, используя launchd. Мой файл 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
Я загружаю этот список через:
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 ответа
Похоже, что внутри скрипта есть некоторая зависимость от среды - по сути, она предполагает что-то относительно среды, в которой он работает, это правильно, когда вы запускаете его вручную, а не когда запускает launchd. Не зная ничего о сценарии, трудно указать, что это может быть, но я могу предложить несколько вещей, на которые стоит обратить внимание:
sudo launchctl
не более мощная версияlaunchctl
, это делает что-то значительно другое. Вы должны выяснить, какой вы хотите, и использовать его.Когда ты бежишь
launchctl
как обычный пользователь (например,launchctl load
), он взаимодействует с вашим пользовательским экземпляром launchd, чтобы управлять агентами запуска - элементами, которые запускаются в вашем пользовательском сеансе под вашим именем пользователя.Когда ты бежишь
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.
Ваш файл.plist в ~/Library/LaunchAgents
:
<?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
Попробуй написать /tmp
который может быть написан любым пользователем. т.е. изменить /Users/turtle/Desktop/data/data.txt
в /tmp/my_data.txt
если это ваш выходной файл.