#python #raspberry-pi
#python #raspberry-pi
Вопрос:
Я запускаю скрипт Python из скрипта bash при /etc/init.d
использовании sudo /etc/init.d/fanservice.sh start
(или остановке)
Он запускается и останавливается, как и ожидалось, и запускается при загрузке. Скрипт Python работает хорошо.
Однако в top
или htop
я вижу, что скрипт выполняется несколько раз.
Что может быть причиной этого и как мне это остановить? Кроме поиска других триггеров (я проверил, что в crontab нет старых ссылок на скрипт) Я не уверен, где еще искать.
Это /etc/init.d/fanservice.sh
Я запускаю скрипт Python от имени root, чтобы разрешить доступ к GPIO.
#!/bin/sh
### BEGIN INIT INFO
# Provides: myservice
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Put a short description of the service here
# Description: Put a long description of the service here
### END INIT INFO
# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/home/pi
DAEMON=$DIR/fanservice.py
DAEMON_NAME=fanservice
# Add any command line options for your daemon here
DAEMON_OPTS=""
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root
# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" amp;amp; exit 0 || exit $?
;;
*)
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
exit 1
;;
esac
exit 0
Скрипт Python использует WiringPi, GPIO, tach и Paho.mqtt для считывания температуры, установки скорости вентилятора, считывания скорости из тахометра, а затем отправки сообщения MQTT брокеру. Все, что содержится в цикле while True: цикл с time.sleep(58) в конце, поэтому я ожидаю, что «сервис» будет запускаться и повторяться каждые 58 секунд.
Он делает это, но каждую минуту или около того новый экземпляр появляется в top.
Если я проверю /var/run/fanservice.pid
, где хранится PID скрипта, я увижу, что у него есть PID первого экземпляра.
Например, через 15 или 20 минут htop покажет скрипт, запущенный с идентификатором PID, который соответствует идентификатору, хранящемуся в файле PID, и этот процесс будет иметь время XX минут и секунд с момента загрузки. Тогда будет XX повторяющихся процессов со своими собственными PID, все со временем 00:00.00, и их количество будет соответствовать (я думаю) количеству минут с момента загрузки.
Любые советы приветствуются. Сценарий init.d — это тот, который я нашел в Интернете, не могу вспомнить где, но я думаю, что я, вероятно, каким-то образом его сломал! Тем не менее, я перешел к выполнению этих задач в цикле таймера, а не из cron, потому что скрипт Python не завершался после вызова cron. У меня также есть другие скрипты, работающие таким образом, которым требуется более быстрый цикл, чем минимум 1 минута от cron, поэтому я хотел бы узнать, как заставить это работать правильно.
Спасибо!
Комментарии:
1. Почему вы используете сценарии инициализации в стиле SysV? Даже если вы придерживаетесь крошечных, минимальных систем, все равно есть лучшие способы сделать это — если у вас нет или вы не хотите запускать systemd, взгляните на runit или его более современный кузен s6 . И если используемый вами дистрибутив отправляет systemd, то… что ж, он у вас уже есть, и вы оплачиваете расходы; с таким же успехом можно использовать его для того, что он делает хорошо.
2. (cron также очень ошибочен; реальная система контроля процессов может автоматически запускать перезапуск или другое желаемое / настроенное событие всякий раз, когда он получает SIGCHILD от вашего процесса, завершающего работу, поэтому он немедленно реагирует с нулевыми затратами на опрос; никаких
sleep
циклов нигде).3. Спасибо, вместо этого я попробую systemd и обновлю!
4. Я успешно перешел на systemd, спасибо за совет. Однако существует та же проблема — через некоторое время выполняется несколько копий скрипта Python. Может ли быть так, что systemd обнаруживает, что мой скрипт не отвечает, и запускает новую копию?
5. Это интересный результат. Завершает ли основной PID и оставляет ли дочерние процессы запущенными? Какой тип службы вы указываете?