все статьи
12 октября 2026 г.·7 мин

Как запускать Python-скрипт по расписанию в Linux через systemd

Настройте запуск Python по расписанию через systemd timer: сервисный пользователь, виртуальное окружение, права на файлы, проверка времени и просмотр логов.

PythonLinuxsystemdАвтоматизация

Автор: Shcoder, независимый разработчик

Чтобы запускать Python-скрипт по расписанию на Linux-сервере, оформите его как systemd service и привяжите к нему timer. Сервис задаёт пользователя, рабочую папку и команду запуска; timer отвечает за календарное расписание. Такой вариант подходит для отчётов и небольших фоновых задач, если сервер работает на systemd.

Ниже настроим запуск ежедневно в 08:30 по часовому поясу сервера. Python-код остаётся обычной программой: сначала он должен запускаться вручную из виртуального окружения.

Подготовьте проект

Допустим, проект расположен в /opt/csv-report, а точка входа — merge_csv.py:

/opt/csv-report/
  .venv/bin/python
  merge_csv.py
  data/inbox/
  data/out/

Создайте виртуальное окружение и установите зависимости, если они есть:

cd /opt/csv-report
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python merge_csv.py

Убедитесь, что скрипт завершается с кодом 0, читает нужные входные файлы и сохраняет результат туда, куда ожидается. Планировщик не исправит неверные пути, отсутствующие переменные окружения или права на папку.

Создайте отдельного непривилегированного пользователя automation и выдайте ему чтение проекта и запись только в папку результата. Не запускайте регулярную задачу от root, если ей не нужны системные привилегии.

Опишите одноразовый сервис

Создайте /etc/systemd/system/csv-report.service:

[Unit]
Description=Build the scheduled CSV report

[Service]
Type=oneshot
User=automation
Group=automation
WorkingDirectory=/opt/csv-report
ExecStart=/opt/csv-report/.venv/bin/python /opt/csv-report/merge_csv.py
UMask=0077
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/csv-report/data/out

Путь в ExecStart должен указывать прямо на Python из виртуального окружения: systemd не запускает интерактивную оболочку и не активирует .venv автоматически. Проверьте, что automation может читать data/inbox, а папка data/out существует и доступна для записи.

Если программе нужны переменные окружения, задайте отдельный файл с ограниченными правами и добавьте EnvironmentFile=/etc/csv-report.env. Не помещайте токены и пароли в публичный репозиторий или командную строку процесса.

Добавьте расписание

Создайте /etc/systemd/system/csv-report.timer:

[Unit]
Description=Run the CSV report every day

[Timer]
OnCalendar=*-*-* 08:30:00
Persistent=true
RandomizedDelaySec=5m
Unit=csv-report.service

[Install]
WantedBy=timers.target

OnCalendar задаёт локальное календарное время сервера. Persistent=true позволяет выполнить пропущенный календарный запуск после повторной активации timer. RandomizedDelaySec добавляет небольшой случайный сдвиг, чтобы множество задач не стартовали строго одновременно. Это не обещание запуска до секунды: systemd допускает окно точности таймера.

До установки проверьте выражение:

systemd-analyze calendar '*-*-* 08:30:00'
timedatectl

Перечитайте units и включите расписание:

sudo systemctl daemon-reload
sudo systemctl enable --now csv-report.timer
systemctl list-timers csv-report.timer

Выражение OnCalendar и поведение Persistent описаны в официальной документации systemd timer; синтаксис календаря проверяет команда systemd-analyze calendar.

Проверьте запуск и разберите сбой

Не ждите следующего утра: запустите сервис вручную и посмотрите его статус и журнал:

sudo systemctl start csv-report.service
systemctl status csv-report.service
journalctl -u csv-report.service --since today

Для такой задачи print() и стандартный Python logging попадут в журнал systemd. Добавляйте туда статус и количество обработанных записей, но не содержимое строк, персональные данные или секреты.

Если сервис не сработал, проверьте по порядку: абсолютные пути, WorkingDirectory, права пользователя automation, зависимости в .venv, переменные окружения и доступность входных файлов. Ошибка задачи не должна считаться успешным пустым отчётом. Для важных операций добавьте в сам скрипт понятный код завершения, безопасные повторы и уведомление об ошибке.

Таймер не заменяет мониторинг результата: смотрите время последнего успешного выполнения и проверяйте, что отчёт действительно обновился. Для задачи дольше интервала запуска отдельно продумайте защиту от параллельного выполнения и повторную обработку.

Соберите автоматизацию целиком

Расписание полезно, когда скрипт уже умеет проверять данные и сохранять воспроизводимый результат. В примере объединения CSV-файлов на Python показана обработка входных выгрузок, а в руководстве по Python-парсерам — получение и проверка данных из разрешённых источников. Оба материала входят в бесплатный курс Python для автоматизации, где эти шаги собраны в проектную последовательность.

Собрать первого Telegram-бота

Бесплатный практикум Aiogram 3 помогает пройти путь от первого ответа до FSM и деплоя на VPS.

Начать бесплатный практикум

Хотите автоматизировать рутинные задачи?

Создаю парсеры, интеграции и скрипты, которые экономят время команды.