Сегодня будет статья / заметка / ответ на часто задаваемый вопрос. Итак, кратчайшая предыстория... На нашем форуме был опубликован вопрос по поводу автозапуска скрипта при включении Raspberry. И внезапно пришло осознание, что вопрос этот возникает достаточно часто, так, почему бы, собственно, не оформить ответ на него более глобально. То есть в виде заметки на основном сайте. Так что, переходим к разбору, как выполнить автозапуск python скрипта на Raspberry Pi.
Итак, способы решения поставленной задачи многообразны и разнообразны. Разберем несколько из них, может пару-тройку... Кстати любые комментарии по данной теме крайне приветствуются - другие варианты, плюсы/минусы, идеи, вопросы )
Создаем подопытный скрипт на python'е - script.py. Что он будет делать в данном случае вообще не важно, я возьму тестовый скрипт с ШИМ:
import RPi.GPIO as GPIO import time GPIO_PWM_0 = 12 WORK_TIME = 300 DUTY_CYCLE = 50 FREQUENCY = 100 print('script execution begins') GPIO.setmode(GPIO.BCM) GPIO.setup(GPIO_PWM_0, GPIO.OUT) pwmOutput_0 = GPIO.PWM(GPIO_PWM_0, FREQUENCY) pwmOutput_0.start(DUTY_CYCLE) time.sleep(WORK_TIME) pwmOutput_0.stop() pwmOutput_1.stop() GPIO.cleanup() print('script execution ends')
Останавливаться на его работе не будем, в общем-то в статье про ШИМ все это есть. Физически файл у меня находится в:
/home/pi/PythonScripts/
Для запуска скрипта соответственно:
sudo python /home/pi/PythonScripts/script.py
Переходим к сути дела - автозапуску.
Вариант 1. Автозапуск скрипта через /etc/profile.
При запуске оболочки bash последняя использует набор стандартизированных файлов для создания окружения. К этим файлам относится и /etc/profile. Мы под шумок можем поместить в этот файл дополнительную команду, выполняющую запуск нашего скрипта. Открываем файл в редакторе:
sudo nano /etc/profile
И добавляем в конец файла строку:
sudo python /home/pi/PythonScripts/script.py
Сохраняем файл, закрываем - на этом все, задача решена. Но тут необходимо упомянуть два дополнительных нюанса.
Первый связан с тем, что в соответствии с механизмом, который мы использовали, команда будет выполняться каждый раз при запуске bash в интерактивном режиме. То есть, в частности, при запуске терминала, либо при подключении к плате по SSH. Скрипт в данных случаях будет запускаться каждый раз. Дальше уже нужно смотреть по конкретной цели - нужно это или нет.
Второй нюанс заключается в том, что работать с командной строкой можно будет лишь по окончанию выполнения скрипта. И если скрипт, например, содержит бесконечный цикл, либо операции, требующие некоторого времени, то в конце команды нужно добавить амперсанд - &:
sudo python /home/pi/PythonScripts/script.py &
Эта модификация приведет к выполнению команды в отдельном потоке, что решает обозначенную выше проблему.
Вариант 2. Автозапуск скрипта через /etc/rc.local.
В данном случае команда, добавленная в этот файл, будет выполняться уже однократно - при запуске ОС (т. е. при включении платы). Сам процесс организации автозапуска по сути идентичен, открываем файл для редактирования:
sudo nano /etc/rc.local
И в конце файла, но(!) перед "exit 0" добавляем запуск скрипта:
sudo python /home/pi/PythonScripts/script.py &
Обращаем внимание на & в конце строки - причина его использования все в том же - обеспечить выполнение скрипта в отдельном потоке. В данном случае это еще более важно. Поскольку команды из rc.local будут выполняться в процессе загрузки системы, то запуск пользовательского скрипта с бесконечным циклом приведет попросту к тому, что система не стартанет. Так что бдительность и внимательность 👍
По той же причине, что скрипт будет выполняться при загрузке системы, получить обратную связь от него проблематично. И если там будет ошибка, и ОС не запустится, то поиск этой ошибки может стать непростой задачей. К счастью, очень просто организовать логирование выполнения скрипта. Для этого модифицируем команду запуска:
sudo python /home/pi/PythonScripts/script.py & > /home/pi/PythonScripts/script_log.txt 2>&1
Теперь в файл /home/pi/PythonScripts/script_log.txt будет записан, во-первых, вывод скрипта (то, что там находится в print() ), и, во-вторых, ошибки, если таковые имели место при его выполнении.
Так, на этом и заканчиваем тогда обзор данной проблемы, спасибо за внимание, прочтение, обратную связь 🤝
это все костыли! правильное решение использовать systemd
Напиши как
Я, по старинке supervisor использую.
приветствую мне это очень интерессно
мне 11 и хочу научится писать игры сам. если может кто взять меня в ученики буду признателен .P.S хочу знать все Так как одно сегодня стоит двух завтра. Бенджемен Франклин