Программа работает, когда вы запускаете её вручную, а после выключения питания всё пропадает? Для датчиков, умного дома, метеостанции и любых проектов, которые должны работать «сами по себе», этого мало. Нужно, чтобы плата, включившись, запустила нужную программу, а если та упадёт, запустила её снова.
В 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.
Служба запущена (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), третья выводит записи за сегодня.
Внизу экрана видна строка (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. На снимке запись сделана без ключа -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
На снимке файл создан в 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
На снимке 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
На снимке видно, как 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: у неё нет доступа к рабочему столу. Их запускают после входа пользователя в рабочий стол.
- Убедитесь, что система загружается в рабочий стол и входит в него автоматически. В
sudo raspi-configоткройте 1 System Options → S5 Boot и выберите B2 Desktop. Затем в разделе S6 Auto Login ответьте «Yes» на вопрос про автоматический вход в рабочий стол. То же можно сделать в Control Centre на вкладке System (переключатель Desktop Auto Login).
На снимке вкладка System: в строке Boot выбран вариант To desktop, ниже находятся переключатели Console Auto Login (автовход в консоль) и Desktop Auto Login (автовход в рабочий стол).
- В системе Raspberry Pi OS с Wayland (менеджер окон labwc) команды для автозапуска пишутся в файл
~/.config/labwc/autostart. Создайте его или откройте:
mkdir -p ~/.config/labwc
nano ~/.config/labwc/autostart
- Добавьте по одной команде в строке. Долгоживущие программы запускайте с символом
&в конце:
chromium --kiosk http://localhost:8123 &
В Raspberry Pi OS на Debian 12 «Bookworm» браузер запускается командой chromium-browser, а на Debian 13 «Trixie» командой chromium.
- Перезагрузитесь. После входа в рабочий стол команда выполнится.
Если нужно запускать программу, которой окно не нужно, в этом файле такая же запись, но лучше воспользоваться службой 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: контейнеры тоже запускаются автоматически.
Материалы
- systemd.service — описание параметров служб.
- journalctl — справочник по просмотру журнала.
- crontab(5) — формат записей cron.
- Configure logging in Raspberry Pi OS — настройка журнала в raspi-config.










