Автозапуск программ на Raspberry Pi: systemd-сервис, cron, @reboot

Программа работает, когда вы запускаете её вручную, а после выключения питания всё пропадает? Для датчиков, умного дома, метеостанции и любых проектов, которые должны работать «сами по себе», этого мало. Нужно, чтобы плата, включившись, запустила нужную программу, а если та упадёт, запустила её снова.

В Linux для этого есть systemd. Это система, которая запускает всё, что работает в фоне. Мы научимся описывать свою программу как службу (сервис): её можно включить в автозапуск, остановить, перезапустить и посмотреть её сообщения. Разберём и запасные варианты: планировщик cron с @reboot и автозапуск программ рабочего стола.

Статья нужна для большинства проектов дальше: метеостанции, отправки показаний по MQTT, датчиков и камер. Как установить Python-библиотеки в окружение, описано в статье про Python и venv.


Какой способ выбрать

СпособКогда использовать
Служба systemdГлавный вариант. Фоновые программы, серверы, датчики. Есть автоперезапуск, журнал, управление командами
cron и @rebootПростой запуск скрипта один раз при включении или по расписанию (раз в час, каждый день)
Автозапуск рабочего столаПрограммы с окном (браузер в киоске, GUI-приложение). Работает только после входа в рабочий стол
rc.localУстаревший способ. В современной Raspberry Pi OS файла нет по умолчанию, не используйте

Что нужно заранее

Допустим, у вас уже есть работающая программа. Для примера возьмём монитор платы из статьи про Python и venv: он лежит в папке /home/admin/monitor, а библиотека psutil установлена в окружение /home/admin/monitor/env. Пользователь называется admin: это имя мы задали в Raspberry Pi Imager. Если вы указали другое имя, подставьте его везде вместо admin. Узнать своё имя можно командой whoami.

Обязательно проверьте программу вручную: если она не запускается в терминале, то и службой не заработает. Заранее запишите полные пути: и к Python, и к скрипту:

/home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor.py

Служба запускается не из вашей папки и без активированного окружения. Поэтому пути должны быть абсолютными.


Служба systemd

Шаг 1. Создаём файл службы

Файлы служб лежат в /etc/systemd/system/. Создайте файл с расширением .service:

sudo nano /etc/systemd/system/monitor.service

Вставьте в него:

[Unit]
Description=Монитор платы Raspberry Pi
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=admin
WorkingDirectory=/home/admin/monitor
ExecStart=/home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor.py
Restart=on-failure
RestartSec=5
Environment=PYTHONUNBUFFERED=1

[Install]
WantedBy=multi-user.target

Сохраните (Ctrl+O, Enter) и выйдите (Ctrl+X).

Что здесь написано:

ПараметрЗначение
DescriptionНазвание службы, которое увидите в списках и логах
After, WantsЗапускать после того, как сеть готова. Нужно, если программе нужен интернет или MQTT. Если сеть не нужна, строки можно убрать
Type=simpleПрограмма остаётся работать и не «уходит в фон» сама. Подходит для большинства скриптов
UserПользователь, от имени которого запускается программа. Он должен существовать в системе: впишите своё имя из Imager (admin в нашем примере), иначе служба не запустится (ошибка 217/USER). Не оставляйте root без необходимости
WorkingDirectoryРабочая папка. Относительные пути в программе отсчитываются от неё
ExecStartКоманда запуска. Только полные пути, без ~ и без source
Restart=on-failureПерезапускать, если программа завершилась с ошибкой
RestartSec=5Подождать 5 секунд перед перезапуском
Environment=PYTHONUNBUFFERED=1Сообщения print сразу попадают в журнал, а не копятся в буфере
WantedBy=multi-user.targetЗапускать при обычной загрузке системы

Шаг 2. Включаем и запускаем

sudo systemctl daemon-reload
sudo systemctl enable --now monitor

Первая команда заставляет systemd перечитать файлы служб. Вторая включает автозапуск (enable) и сразу запускает службу (--now). Проверим состояние:

systemctl status monitor

В ответе должно быть Active: active (running) и несколько последних строк вывода программы:

● monitor.service - Монитор платы Raspberry Pi
     Loaded: loaded (/etc/systemd/system/monitor.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-10-27 19:14:51 MSK; 30s ago

Теперь перезагрузите плату (sudo reboot) и убедитесь, что служба поднялась сама: systemctl status monitor.

Терминал Raspberry Pi 5: systemctl status monitor показывает службу monitor.service в состоянии active (running) и последние строки вывода программы

Служба запущена (active (running)), а под блоком состояния видны последние строки вывода программы: загрузка процессора, память и температура. В строке CGroup видно, что Python запущен из окружения /home/admin/monitor/env.

Шаг 3. Смотрим журнал

Всё, что программа выводит через print и сообщения об ошибках, попадает в журнал systemd. Читать его можно командой journalctl:

journalctl -u monitor -n 30
journalctl -u monitor -f
journalctl -u monitor --since today

Первая команда выводит последние 30 строк, вторая показывает вывод «вживую» (выход по Ctrl+C), третья выводит записи за сегодня.

Терминал Raspberry Pi 5: journalctl -u monitor -n 30 выводит 30 последних строк службы monitor, строки CPU, RAM и температуры с интервалом три секунды

Внизу экрана видна строка (END): журнал открылся в просмотрщике. Листайте его стрелками, а выйти можно клавишей q. Журнал отвечает на главный вопрос «почему не работает»: в нём видны сообщения Python об ошибках.

Журнал после перезагрузки. По умолчанию журнал может храниться только в оперативной памяти и сбрасываться при перезагрузке. Чтобы он сохранялся на диске, откройте sudo raspi-config → 6 Advanced Options → A12 Logging и выберите Persistent. Не забывайте, что запись на карту её изнашивает: программа, которая пишет сообщения каждую секунду, быстро «забьёт» журнал.

Управление службой

КомандаЧто делает
sudo systemctl start monitorЗапустить
sudo systemctl stop monitorОстановить
sudo systemctl restart monitorПерезапустить (нужно после изменения программы)
sudo systemctl enable monitorВключить автозапуск при загрузке
sudo systemctl disable monitorОтключить автозапуск
systemctl status monitorПоказать состояние
systemctl is-enabled monitorПроверить, включён ли автозапуск

После правки самого файла .service перед перезапуском выполняйте sudo systemctl daemon-reload. После правки только Python-программы достаточно restart.

Проверить файл службы на ошибки можно командой:

systemd-analyze verify /etc/systemd/system/monitor.service

Полезные настройки службы

Запуск после готовности сети

Строки After=network-online.target и Wants=network-online.target заставляют systemd подождать, пока сеть заработает. Они нужны для программ, которые отправляют данные по сети. Для обычных скриптов с датчиками их можно не указывать.

Права доступа и группы

Обычный пользователь Raspberry Pi уже входит в группы gpio, i2c, spi и video, поэтому программа с User=admin получает доступ к выводам GPIO, шинам и камере без sudo. Если вы запускаете службу от другого пользователя, добавьте его в нужные группы: sudo usermod -aG gpio,i2c,spi имя.

Пароли и настройки в отдельном файле

Не вписывайте пароли прямо в программу и в файл службы. Создайте файл /etc/monitor.env:

MQTT_USER=pi
MQTT_PASSWORD=секретный_пароль

Закройте его от посторонних: sudo chmod 600 /etc/monitor.env. Подключите в службе строкой EnvironmentFile=/etc/monitor.env (в раздел [Service]). В Python значения читаются через os.environ["MQTT_PASSWORD"].

Запуск bash-скрипта

Если нужно выполнить не программу на Python, а несколько команд, оформите их как скрипт:

#!/bin/bash
cd /home/admin/project
./run-something

Сделайте файл исполняемым: chmod +x /home/admin/project/start.sh. В службе укажите ExecStart=/home/admin/project/start.sh.

Разовый запуск при загрузке

Для скрипта, который выполняется один раз и завершается (например, включает светодиод или настраивает порт), используйте:

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/home/admin/project/setup.sh

cron и @reboot

Планировщик cron умеет запускать команды по расписанию, а специальное значение @reboot означает «один раз при загрузке». Это быстрый способ, когда не нужны автоперезапуск и журнал.

Откройте расписание своего пользователя:

crontab -e

Если программа спросит, каким редактором пользоваться, выберите nano. В конец файла добавьте строку:

@reboot sleep 30 && /home/admin/monitor/env/bin/python3 -u /home/admin/monitor/monitor.py >> /home/admin/monitor/log.txt 2>&1

Что она делает: через 30 секунд после загрузки запускает программу, а вывод и ошибки дописывает в файл log.txt. Пауза sleep 30 нужна, чтобы к этому времени успели подняться сеть и службы. Ключ -u отключает буферизацию вывода Python. Без него print при записи в файл копится в буфере (порядка 8 КБ), и log.txt долго остаётся пустым, хотя программа работает. Эту же роль в службе systemd выполняет Environment=PYTHONUNBUFFERED=1.

Редактор nano с файлом crontab на Raspberry Pi 5: внизу добавлена строка @reboot sleep 30 с запуском monitor.py и записью в log.txt

Так выглядит файл в редакторе nano. На снимке запись сделана без ключа -u: именно из-за этого log.txt долго оставался пустым. Добавьте -u после python3, как в строке выше, затем сохраните (Ctrl+O, Enter) и выйдите (Ctrl+X). Остальные строки cron задают расписание из пяти полей: минуты, часы, день месяца, месяц, день недели.

ЗаписьКогда запускается
@reboot командаОдин раз при загрузке
*/5 * * * * командаКаждые 5 минут
0 * * * * командаКаждый час, в ноль минут
30 7 * * * командаКаждый день в 7:30
0 3 * * 1 командаПо понедельникам в 3:00

Запись состоит из расписания (пять полей или слово @reboot) и команды через пробел. Больше между ними ничего не ставится: && нужен только внутри самой команды, если вы соединяете две команды, как sleep 30 && …. Строки, начинающиеся с #, это комментарии. Посмотреть текущее расписание можно командой crontab -l.

Программа для запуска по расписанию

Наш monitor.py работает бесконечно, поэтому по расписанию его запускать нельзя. Для расписания нужна программа, которая делает одно действие и завершается. Создайте рядом с монитором такую:

nano ~/monitor/monitor_once.py
import time

import psutil


def cpu_temp():
    # Температура процессора в градусах Цельсия
    with open("/sys/class/thermal/thermal_zone0/temp") as f:
        return int(f.read()) / 1000


now = time.strftime("%Y-%m-%d %H:%M:%S")
cpu = psutil.cpu_percent(interval=1)
ram = psutil.virtual_memory().percent
print(f"{now}   CPU: {cpu:5.1f} %   RAM: {ram:5.1f} %   Температура: {cpu_temp():.1f} °C")

Она печатает одну строку со временем и сразу завершается. Время нужно, потому что в файле журнала cron его иначе не будет. Сначала запустите её вручную:

/home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py

Результат будет примерно таким:

2026-10-27 21:19:40   CPU:   0.0 %   RAM:  28.4 %   Температура: 42.5 °C
Терминал Raspberry Pi 5: nano monitor_once.py и ручной запуск, программа печатает одну строку со временем, загрузкой CPU, памятью и температурой и завершается

На снимке файл создан в nano, затем программа запущена вручную: она печатает одну строку и возвращает приглашение командной строки. Именно так должна вести себя программа для расписания.

Готовые записи

Все строки ниже добавляются в crontab -e и используют полные пути из нашего примера (пользователь admin). Включайте по одной записи, а не все сразу: иначе в файле будет неразбериха из разных расписаний. Вывод везде дописывается в ~/monitor/once.log.

Каждые 5 минут:

*/5 * * * * /home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py >> /home/admin/monitor/once.log 2>&1
Терминал Raspberry Pi 5: tail -f once.log, в файле две строки с интервалом ровно пять минут, 21:25:01 и 21:30:01

На снимке tail -f ~/monitor/once.log показывает две записи: 21:25:01 и 21:30:01. Интервал ровно 5 минут, и каждый запуск начинается в первую секунду минуты.

Каждый час, в ноль минут (в 1:00, 2:00 и так далее):

0 * * * * /home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py >> /home/admin/monitor/once.log 2>&1

Каждый день в 7:30:

30 7 * * * /home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py >> /home/admin/monitor/once.log 2>&1

По понедельникам в 3:00 (в пятом поле число дня недели: 0 или 7 воскресенье, 1 понедельник, 6 суббота):

0 3 * * 1 /home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py >> /home/admin/monitor/once.log 2>&1

Один раз при загрузке, через 30 секунд (запустит короткую программу и она завершится):

@reboot sleep 30 && /home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py >> /home/admin/monitor/once.log 2>&1

Бесконечный monitor.py в расписание не ставят. Для него остаётся только запись @reboot из начала раздела (с ключом -u) или служба systemd.

Как проверить, что cron работает

Чтобы не ждать 5 минут, временно поставьте запуск каждую минуту:

* * * * * /home/admin/monitor/env/bin/python3 /home/admin/monitor/monitor_once.py >> /home/admin/monitor/once.log 2>&1

Следите за файлом. Новая строка должна появляться раз в минуту (выход по Ctrl+C):

tail -f ~/monitor/once.log

Если файл пустой, посмотрите, запускал ли cron команду. В журнале должна быть строка CMD (…) с вашей командой:

journalctl -u cron -b
Терминал Raspberry Pi 5: journalctl -u cron -b показывает запуски задачи monitor_once.py в 21:25:01 и 21:30:01 и перезагрузку crontab

На снимке видно, как cron работает. Строка RELOAD (crontabs/admin) появляется после сохранения расписания в crontab -e. Строки (admin) CMD (…monitor_once.py…) в 21:25:01 и 21:30:01 означают запуск вашей команды, а session closed сразу после неё означает, что программа завершилась. Строка (root) CMD (cd / && run-parts … /etc/cron.hourly) относится к системной задаче, не к вашей.

Убедитесь, что не осталось лишних копий программы:

ps aux | grep monitor

Проверив, верните нужное расписание через crontab -e.

Как остановить

Откройте crontab -e и удалите нужную строку (или поставьте в её начало #). Уже запущенную бесконечную программу остановит команда pkill -f monitor.py. Если вы хотите вернуться к службе, отключите cron-запись и включите службу: sudo systemctl enable --now monitor. Не запускайте службу и @reboot-запись одновременно: получится две копии программы, и обе пишут в вывод.

Программа с бесконечным циклом и расписание. Запись вида */5 * * * * запускает команду каждые 5 минут, но не дожидается её завершения. Если программа работает вечно (как наш monitor.py с while True), каждые 5 минут появится ещё одна копия. Для расписания годятся только программы, которые сделали работу и завершились. Бесконечные программы запускайте службой или через @reboot.

Особенности cron. Программы cron запускаются с очень скромным набором переменных окружения: нет вашего PATH и псевдонимов. Поэтому и здесь пишите полные пути. Команду нужно выполнить в терминале вручную и убедиться, что она работает, перед тем как добавлять её в cron.


Автозапуск программ рабочего стола

Программы с окном (браузер, приложение с графикой) нельзя запускать службой systemd: у неё нет доступа к рабочему столу. Их запускают после входа пользователя в рабочий стол.

  1. Убедитесь, что система загружается в рабочий стол и входит в него автоматически. В sudo raspi-config откройте 1 System Options → S5 Boot и выберите B2 Desktop. Затем в разделе S6 Auto Login ответьте «Yes» на вопрос про автоматический вход в рабочий стол. То же можно сделать в Control Centre на вкладке System (переключатель Desktop Auto Login).
Окно Control Centre на Raspberry Pi 5, вкладка System: выбор загрузки To desktop или To CLI, переключатели Console Auto Login и Desktop Auto Login, Splash Screen, браузер по умолчанию и Admin Password

На снимке вкладка System: в строке Boot выбран вариант To desktop, ниже находятся переключатели Console Auto Login (автовход в консоль) и Desktop Auto Login (автовход в рабочий стол).

  1. В системе Raspberry Pi OS с Wayland (менеджер окон labwc) команды для автозапуска пишутся в файл ~/.config/labwc/autostart. Создайте его или откройте:
mkdir -p ~/.config/labwc
nano ~/.config/labwc/autostart
  1. Добавьте по одной команде в строке. Долгоживущие программы запускайте с символом & в конце:
chromium --kiosk http://localhost:8123 &

В Raspberry Pi OS на Debian 12 «Bookworm» браузер запускается командой chromium-browser, а на Debian 13 «Trixie» командой chromium.

  1. Перезагрузитесь. После входа в рабочий стол команда выполнится.

Если нужно запускать программу, которой окно не нужно, в этом файле такая же запись, но лучше воспользоваться службой systemd: она работает независимо от того, вошёл ли кто-то в рабочий стол.


Если служба не запускается

Сначала всегда смотрите журнал: journalctl -u имя -n 50. Частые причины:

Симптом в статусеПричина и решение
status=203/EXECНеверный путь в ExecStart или файл не исполняемый. Проверьте путь командой ls -l, используйте полный путь к Python
status=200/CHDIRПапки из WorkingDirectory не существует
status=217/USERПользователя из User= не существует. В журнале при этом пишет Failed to determine user credentials: No such process, а служба бесконечно перезапускается (activating (auto-restart)). Самая частая причина: в файле остался User=pi, а в Imager вы задали другое имя. Проверьте whoami, исправьте User= и пути /home/…, затем выполните sudo systemctl daemon-reload и sudo systemctl restart monitor
Active: failed (Result: exit-code)Программа завершилась с ошибкой. Причину покажет journalctl: чаще всего это ModuleNotFoundError (запущен не тот Python: берите Python из окружения) или ошибка прав
start request repeated too quicklyПрограмма падает сразу после старта много раз подряд, и systemd перестаёт перезапускать её. Исправьте ошибку, затем выполните sudo systemctl reset-failed имя и запустите службу снова
Вручную работает, а как служба нетСкорее всего, относительные пути, нет доступа к файлам или переменным окружения. Укажите WorkingDirectory, полные пути, нужного пользователя
Нет сети в момент запускаДобавьте After=network-online.target и Wants=network-online.target, а в программе предусмотрите повторные попытки
Нет доступа к GPIO или I2CПроверьте, что пользователь входит в нужные группы (groups admin), а интерфейсы включены в raspi-config

На других платах. Всё, что описано про systemd и cron, работает и на Orange Pi, Banana Pi и NanoPi под Armbian, Debian или Ubuntu. Различаются только имя пользователя и пути.


Что дальше

  • MQTT на Raspberry Pi: отправка показаний датчиков из службы.
  • Метеостанция на Raspberry Pi: всё вместе, автоматически и с графиками.
  • Docker и Docker Compose: контейнеры тоже запускаются автоматически.

Материалы

Оставьте комментарий

Отправляя комментарий, вы соглашаетесь с обработкой ваших данных (имя, адрес электронной почты, текст комментария) в соответствии с политикой конфиденциальности.