У меня есть пользователь dropbox, который запускает демон Dropbox, я хочу отслеживать каталоги в каталоге Dropbox на предмет новых файлов и запускать скрипт python, когда они появляются.
У меня есть скрипт Python, который, как я знаю, работает:
$ /home/dropbox/monitor.py
Trying to get lock
Got lock, waiting for Dropbox to be idle
Dropbox idle
Finding instructions
Done, releasing lock
У меня есть запись incrontab:
$ incrontab -l
/home/dropbox/Dropbox IN_CREATE /home/dropbox/monitor.py | logger
/home/dropbox/test IN_CREATE logger "$$ $@ $# $% $&"
Когда я добавляю файл в тестовый каталог, я вижу результат в /var/log/syslog
:
$ touch /home/dropbox/test/a
$ tail /var/log/syslog
...
Nov 9 10:18:27 vps incrond[1354]: (dropbox) CMD (logger "$ /home/dropbox/test a IN_CREATE 256")
Nov 9 10:18:27 vps logger: "$ /home/dropbox/test a IN_CREATE 256"
...
Однако, когда я добавляю файл в каталог Dropbox, команда не запускается:
$ touch /home/dropbox/Dropbox/a
$ tail /var/log/syslog
...
Nov 9 10:24:16 vps incrond[1354]: (dropbox) CMD (/home/dropbox/monitor.py | logger)
...
Таким образом, демон incron замечает новый файл и обнаруживает, что выполняется правильная команда, но на самом деле она никогда не выполняется. И сообщений об ошибках нет. Кажется, что incrontab можно использовать только для выполнения самых простых команд.
Это может быть вопрос, похожий на:
но я думаю, что у меня нет проблем с env, каждый путь абсолютен. Я пытался изменить .../monitor.py
к /usr/bin/python2.7 .../monitor.py
на всякий случай, но это не имело никакого значения.
Деннис Карсемейкер предложил решение, согласно которому incrontab выполнял мою команду без использования cron, и это могло быть причиной проблемы. К сожалению, я все еще не могу заставить его работать.
Сначала я удалил лишнее из incrontab:
$ incrontab -l
/home/dropbox/Dropbox IN_CREATE /home/dropbox/monitor.py
Это должно запускать только мой файл монитора и не пытаться передавать что-либо в качестве аргументов. Нет кубиков, все равно нет выхода.
Затем я создал сценарий bash, содержащий инструкцию по выполнению моего сценария:
$ vim test.sh
logger "$PATH"
/usr/bin/python2.7 /home/dropbox/monitor.py | logger
Это дает следующий результат:
$ tail /var/log/syslog
Nov 9 23:50:28 vps incrond[1354]: (dropbox) CMD (/home/dropbox/test.sh)
Nov 9 23:50:28 vps logger: /usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin
Так что ничего из monitor.py, и мы видим, что каталог, содержащий python, находится в среде incrontab, поэтому нам даже не нужно указывать путь так же точно, как мы.
Я чувствую себя идиотом, заметив это.
Мой скрипт monitor.py пытается получить блокировку файла, прежде чем он начнет возиться с вещами Dropbox. В основном это делается для того, чтобы другие экземпляры monitor.py не вмешивались. Путь к заблокированному мной файлу не был абсолютным.
Итак, урок для всех, кто найдет эту страницу в будущем. Проверьте каждый путь, который вы используете, чтобы убедиться, что он 1) на пути 2) абсолютен.
Между cron и incron большая разница: в способе выполнения команд. Cron видит команду как один аргумент и вызывает оболочку для ее выполнения. Примерно так:
execvp('/bin/sh', ['/bin/sh', '-c', 'whatever is in the crontab']);
Итак, все конструкции оболочки, такие как &&
и |
работай. Incron этого не делает, он анализирует саму команду и запускает ее напрямую. Итак, что incron работает в вашем случае:
execvp('/home/dropbox/monitor.py', ['/home/dropbox/monitor.py', '|', 'logger']);
Итак, ваш monitor.py запускается с |
и logger
как аргументы. Вы можете заключить свой сценарий в другой сценарий, который monitor.py | logger
или используйте питон logging
модуль для ведения журнала из самого monitor.py.