Блог / Статьи

Полезная информация для вашего хостинга

Как заставить Python-скрипт работать без вас: полное руководство по cron, systemd и nohup

Как заставить Python-скрипт работать без вас: полное руководство по cron, systemd и nohup

Представьте: вы написали мощный скрипт на Python — он парсит курсы криптовалют, делает бэкапы баз данных, отправляет уведомления в Telegram и мониторит доступность серверов. Вы запустили его в терминале… и закрыли окно. И всё — процесс убит. Ни логов, ни данных, ни предупреждений. Только пустота.

Это знакомо? Если да — вы не одиноки. Каждый день тысячи разработчиков сталкиваются с одной и той же проблемой: как запустить Python-скрипт так, чтобы он жил, даже когда вы спите, уехали в отпуск или просто забыли про него. В этой статье мы разберём три самых надёжных, проверенных временем метода автозапуска: cron, systemd и nohup. Не просто теорию — реальные, рабочие примеры, пошаговые инструкции, ловушки и лучшие практики, которые используют топовые DevOps-инженеры по всему миру.

Забудьте про “вручную запускать каждый день”. Мы сделаем ваш скрипт непробиваемым, как крепость средневекового замка — с автоматическим восстановлением, логированием и управлением из любой точки мира.

Выбор правильного инструмента: cron, systemd или nohup — что подойдёт именно вам?

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

Cron — это ваш будильник. Он не живёт, он не дышит. Он просто включает свет в определённое время. Идеален для задач, которые нужно выполнять регулярно, но не постоянно: ежедневный бэкап, ежечасный сбор статистики, еженедельный отчёт. Если ваш скрипт работает 5 минут и завершается — cron ваш лучший друг.

Systemd — это не просто запуск. Это управление жизнью. Он превращает ваш скрипт в полноценную системную службу — как Apache или MySQL. Он следит за процессом: если он упал — перезапускает. Если сервер перезагрузился — автоматически запускает заново. Подходит для длительных, непрерывных процессов: Telegram-ботов, веб-сервисов, мониторинга, очередей задач. Это решение для тех, кто хочет, чтобы его скрипт работал всегда, даже если вы забудете его включить.

Nohup — это временный спасательный круг. Он не управляет процессом, не перезапускает его, не следит за ресурсами. Но он выживает, когда вы закрываете SSH. Идеален для одноразовых, срочных задач: запустил скрипт на 8 часов, ушёл на совещание, вернулся — он ещё работает. Это решение для разработчика, который не хочет ждать, пока настроит службу, но не хочет терять процесс.

Вот как они сравниваются в реальных условиях:

  • Работает после выхода из SSH? — Cron: нет (он запускается сам, не зависит от сессии), systemd: да, nohup: да.
  • Перезапускается при сбое? — Cron: нет (если скрипт упал — он не запустится до следующего времени), systemd: да, автоматически, nohup: нет.
  • Работает по расписанию? — Cron: да, основная функция, systemd: нет (но можно обойти через timer), nohup: нет.
  • Управление через команды? — Cron: через crontab, systemd: systemctl start/stop/status, nohup: через ps и pkill.
  • Логирование? — Все три требуют ручной настройки, но systemd и cron делают это проще и надёжнее.

Если вы запускаете бота, который должен отвечать на сообщения 24/7 — systemd. Если вы собираете данные каждые 10 минут — cron. Если вы запустили долгий парсинг на ночь и не хотите, чтобы он упал при закрытии терминала — nohup.

pscript03

Cron: ваш надёжный цифровой будильник для регулярных задач

Крон — это старейший и самый проверенный инструмент в Linux-мире. Он работает как механические часы: точный, простой, ненавязчивый. И хотя он не умеет перезапускать процессы, его надёжность в выполнении задач по расписанию не имеет равных.

Шаг 1: Убедитесь, что Python установлен и скрипт работает

Подключитесь к серверу через SSH:

ssh user@ваш_сервер.домен

Проверьте версию Python:


python3 --version
# Ожидаемый вывод: Python 3.10.12

Если команда не найдена — установите Python (для Ubuntu/Debian):

sudo apt update && sudo apt install python3 python3-pip -y

Теперь протестируйте скрипт вручную. Предположим, ваш скрипт называется data_collector.py и лежит в /home/user/scripts/:

cd /home/user/scripts
python3 data_collector.py

Если он отработал без ошибок — отлично. Теперь найдите полный путь к интерпретатору:


which python3
# Вывод: /usr/bin/python3

Шаг 2: Откройте редактор cron

Введите команду:

crontab -e

Впервые — система предложит выбрать редактор. Для новичков — nano (нажмите 1 и Enter). Если вы опытный пользователь — выбирайте vim или emacs.

Шаг 3: Добавьте задачу

Теперь добавьте строку в формате:

минута час день_месяца месяц день_недели команда

Пример: запускать скрипт каждый день в 3:00 ночи:

0 3 * * * /usr/bin/python3 /home/user/scripts/data_collector.py >> /home/user/logs/data_collector.log 2>&1

Разберём каждую часть:

  • 0 3 * * * — означает: «в 0 минут 3-го часа каждого дня каждого месяца». Звёздочки — это «любое значение».
  • /usr/bin/python3обязательно используйте полный путь. Крон работает в минимальной среде — он не знает переменных PATH, как ваш терминал.
  • /home/user/scripts/data_collector.py — абсолютный путь к вашему скрипту. Никогда не используйте ~ или относительные пути.
  • >> /home/user/logs/data_collector.log 2>&1 — это ключевая часть! >> добавляет вывод в файл (не перезаписывает), 2>&1 перенаправляет ошибки (stderr) в тот же файл, что и стандартный вывод (stdout). Без этого вы не узнаете, почему скрипт сломался.

Частые расписания:

  • Каждые 15 минут: */15 * * * *
  • Каждый понедельник в 8:00: 0 8 * * 1
  • Каждый первый день месяца в 2:30: 30 2 1 * *
  • Каждую минуту (для теста): * * * * *

Шаг 4: Сохраните и проверьте

В nano: Ctrl+OEnterCtrl+X.

Проверить, что задача добавлена:

crontab -l

Для теста — временно установите запуск каждые 2 минуты:

*/2 * * * * /usr/bin/python3 /home/user/scripts/data_collector.py >> /home/user/logs/data_collector.log 2>&1

Через 3 минуты проверьте лог:

tail -f /home/user/logs/data_collector.log

Важно: cron запускает скрипты от имени пользователя, от которого вы вошли. Убедитесь, что у пользователя есть права на чтение скрипта и запись в лог-директорию. Если скрипт использует файлы в других каталогах — укажите полные пути ко всем ресурсам.

Ловушка №1: Путь к Python в cron не совпадает с путём в терминале. Решение — всегда используйте which python3.

Ловушка №2: Скрипт работает в терминале, но в cron — нет. Часто причина — отсутствие переменных окружения. Решение: в начале crontab добавьте:


SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
Теперь ваш скрипт будет работать, как часы — даже если вы уедете в отпуск на месяц.
pscript02

Systemd: превратите Python-скрипт в системную службу — как Apache или MySQL

Если cron — это будильник, то systemd — это полноценный операционный менеджер. Он не просто запускает процесс. Он управляет жизненным циклом вашего приложения. Это решение для тех, кто хочет, чтобы его бот, мониторинг или сервис работали всегда, независимо от того, что происходит с сервером.

Systemd — это ядро современных Linux-дистрибутивов. Он отвечает за запуск сервисов при загрузке, мониторинг их состояния, логирование и перезапуск при сбоях. Превратить скрипт в службу — значит дать ему статус равный с системными процессами.

Шаг 1: Создайте файл службы

Откройте новый файл службы с правами root:

sudo nano /etc/systemd/system/my-python-service.service

Внимание! Имя файла должно заканчиваться на .service. Лучше использовать понятные имена: telegram-bot.service, price-monitor.service.

Шаг 2: Напишите конфигурацию

Вставьте следующий шаблон (замените всё в угловых скобках):


[Unit]
Description=Python Data Collector Service
After=network.target
Requires=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/user/scripts/data_collector.py
WorkingDirectory=/home/user/scripts
Restart=always
RestartSec=5
User=user
Group=user
Environment=PYTHONPATH=/home/user/scripts
StandardOutput=append:/var/log/my-python-service/output.log
StandardError=append:/var/log/my-python-service/error.log
KillMode=process
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target

Разбор ключевых директив:

  • Description — понятное имя службы, которое вы увидите в статусе.
  • After=network.target — гарантирует, что служба запустится только после того, как сеть будет доступна (важно для скриптов, работающих с интернетом).
  • ExecStart — команда запуска. Здесь обязательно используйте полный путь к python3 и вашему скрипту.
  • WorkingDirectory — директория, из которой будет запущен скрипт. Это критично, если ваш код использует относительные пути к файлам, конфигам или библиотекам.
  • Restart=always — самое важное! Если скрипт упадёт (из-за ошибки, нехватки памяти, сетевого сбоя) — systemd автоматически перезапустит его через 5 секунд (как указано в RestartSec).
  • User и Group — никогда не запускайте службы от root! Создайте отдельного пользователя для вашего скрипта, если это возможно. Это повышает безопасность.
  • Environment — если ваш скрипт использует переменные окружения (например, API-ключи в .env), задайте их здесь. Можно указать Environment=VAR1=value1 VAR2=value2.
  • StandardOutput и StandardError — пишем логи в отдельные файлы. Используем append:, чтобы не стирать предыдущие записи. Убедитесь, что директория /var/log/my-python-service/ существует и доступна для записи пользователем user.
  • TimeoutStopSec=30 — если служба не останавливается за 30 секунд, systemd принудительно завершит её. Полезно для скриптов, которые могут зависнуть.
  • WantedBy=multi-user.target — означает, что служба будет запущена при обычной загрузке системы (не в режиме восстановления).

Шаг 3: Активируйте службу

После сохранения файла (Ctrl+O, Enter, Ctrl+X) выполните:


# Перезагружаем конфигурацию systemd
sudo systemctl daemon-reload

# Включаем автозапуск при загрузке сервера
sudo systemctl enable my-python-service.service

# Запускаем службу немедленно
sudo systemctl start my-python-service.service

# Проверяем статус — это ваш главный инструмент диагностики!
sudo systemctl status my-python-service.service
Если всё хорошо — вы увидите:

● my-python-service.service - Python Data Collector Service
   Loaded: loaded (/etc/systemd/system/my-python-service.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2025-11-21 08:15:32 UTC; 2min ago
 Main PID: 1234 (python3)
    Tasks: 1 (limit: 4915)
   Memory: 25.6M
   CGroup: /system.slice/my-python-service.service
           └─1234 /usr/bin/python3 /home/user/scripts/data_collector.py

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

Шаг 4: Управление службой

Всё просто:

  • Остановить: sudo systemctl stop my-python-service.service
  • Перезапустить: sudo systemctl restart my-python-service.service
  • Посмотреть последние логи: sudo journalctl -u my-python-service.service -f — это мощнее, чем файлы логов! Показывает логи в реальном времени.
  • Посмотреть все логи за день: sudo journalctl -u my-python-service.service --since today

Ловушка №1: Скрипт работает вручную, но systemd не запускает его. Решение: проверьте права на файлы, используйте sudo journalctl -u имя_службы — там будет точная ошибка (например, "Permission denied" или "File not found").

Ловушка №2: Скрипт использует библиотеки, установленные в виртуальном окружении. Решение: замените ExecStart на:


ExecStart=/home/user/scripts/venv/bin/python3 /home/user/scripts/data_collector.py
И убедитесь, что виртуальное окружение активировано и все зависимости установлены.

Systemd — это не просто инструмент. Это философия: ваш код должен быть частью системы. И когда вы настроите службу правильно — вы перестанете думать о скрипте. Он просто будет работать. Как вода в кране. Как свет в лампе. Это — истинное автоматизированное существование.

Nohup: быстрый спасательный круг для срочных задач

Иногда вам не нужно всё это. Иногда вы просто хотите запустить долгий скрипт — например, парсинг 10 тысяч страниц — и уйти. Не ждать 5 часов. Не настраивать службы. Просто запустить и забыть.

Вот где приходит на помощь nohup — легендарная утилита, существующая с 1970-х годов. Её название расшифровывается как “no hang up” — «не отключать». Она игнорирует сигнал SIGHUP, который отправляется процессу при закрытии терминала.

Это не управление службой. Это не автозапуск. Это временное чудо.

Шаг 1: Запустите скрипт с nohup

В терминале введите:

nohup python3 /home/user/scripts/data_collector.py > /home/user/logs/nohup_output.log 2>&1 &

Разберём каждую часть:

  • nohup — говорит системе: «не закрывай этот процесс, даже если я закрою SSH».
  • python3 /home/user/scripts/data_collector.py — ваша команда. Снова — полный путь.
  • > /home/user/logs/nohup_output.log — перенаправляет стандартный вывод (print, logging.info) в файл. Без этого nohup создаёт файл nohup.out в текущей директории — и это плохо, потому что вы можете забыть, где он лежит.
  • 2>&1 — перенаправляет ошибки (stderr) в тот же файл, что и вывод (stdout). Без этого вы не увидите, почему скрипт упал.
  • & — запускает процесс в фоне. Без этого вы не сможете ввести следующую команду — терминал будет «заблокирован» пока скрипт работает.

Шаг 2: Проверьте, что процесс запущен

Закройте терминал. Переподключитесь. И выполните:


ps aux | grep data_collector.py
Вы увидите строку вроде:

user    4567  0.5  2.1 123456 45678 ?    S    10:30   0:12 python3 /home/user/scripts/data_collector.py
Если есть — значит, всё работает. Процесс живёт вне вашей сессии.

Шаг 3: Как остановить?

Нельзя использовать Ctrl+C — он не работает, потому что вы уже не в сессии. Используйте:


pkill -f "data_collector.py"
Или, если нужно точнее — найдите PID и убейте его:

pgrep -f "data_collector.py"
kill -9 4567
Важно: nohup не перезапускает процесс. Если скрипт упал из-за ошибки — он просто умрёт. Логи — ваш единственный источник информации. Поэтому всегда логируйте и проверяйте файлы после завершения.

Когда использовать nohup?

  • Вы запускаете один раз долгий парсинг, конвертацию или импорт данных.
  • Вы тестируете скрипт, но не готовы настраивать systemd.
  • Вы находитесь на сервере, где нет прав на создание служб (например, в shared-хостинге).

Недостатки: нет автозапуска при перезагрузке, нет мониторинга, нет управления через systemctl. Это — «временная мера». Не для продакшена. Но для быстрого решения — незаменима.

pscript

Как выбрать правильный метод? Решение по задаче

Теперь, когда вы знаете все три инструмента, пришло время — принять решение. Не по советам, не по моде. А по логике.

Сценарий 1: Вы делаете бэкап базы данных каждый день в 2:00.

Выбор: cron

Зачем systemd? Скрипт работает 2 минуты, потом завершается. Перезапуск не нужен. Если он не запустился — вы получите уведомление в логе. Cron идеален: прост, надёжен, не требует ресурсов.

Сценарий 2: У вас Telegram-бот, который должен отвечать на сообщения 24/7.

Выбор: systemd

Если бот упадёт — вы потеряете сообщения. Если сервер перезагрузится — бот не запустится. Systemd — единственный способ гарантировать, что ваш бот всегда онлайн. Он перезапустится даже после сбоя в памяти или DDoS-атаки.

Сценарий 3: Вы запустили скрипт на сбор данных с 50 сайтов — он будет работать 12 часов.

Выбор: nohup

Вы не хотите настраивать службу. Вы не хотите, чтобы он запускался снова после перезагрузки. Вам нужно просто, чтобы он не упал, пока вы не вернётесь. Nohup — идеально. Просто запустил, ушёл, вернулся — проверил логи.

Сценарий 4: Вы пишете веб-сервис на Flask, который должен быть доступен по HTTP.

Выбор: systemd

Даже если вы используете Gunicorn или uWSGI — это всё равно служба. Запускайте через systemd. И используйте Nginx как обратный прокси. Это стандарт де-факто в продакшене.

Сценарий 5: Вы тестируете новый скрипт на тестовом сервере — он должен запускаться каждые 5 минут.

Выбор: cron с временным расписанием

Создайте задачу */5 * * * *, проверьте логи, исправьте ошибки. Когда всё будет работать — перейдите на systemd, если нужно постоянное исполнение, или оставьте cron, если задача периодическая.

Запомните правило: если задача периодическая — cron. Если задача постоянная — systemd. Если задача одноразовая, срочная — nohup.

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

Теперь — самое важное. То, что не пишут в туториалах. То, что знают только те, кто уже сломал всё и восстанавливал из резервных копий.

  1. Всегда используйте полные пути. Cron и systemd не знают вашу переменную $PATH. python3 — опасно. /usr/bin/python3 — безопасно. Проверяйте через which python3.
  2. Никогда не запускайте от root. Создайте отдельного пользователя: sudo adduser pythonuser. Дайте ему права только на нужные файлы. Это защитит сервер от вредоносных скриптов.
  3. Логируйте всё. Без логов вы — слепой. Даже если скрипт «работает», логи покажут, что он делал, когда упал, и почему. Используйте logging в Python + файлы логов в системе.
  4. Тестируйте на маленьком интервале. Перед тем как ставить cron на 1 раз в день — поставьте на 1 раз в 2 минуты. Убедитесь, что логи пишутся, что ошибки видны. Только потом — в продакшен.
  5. Проверяйте права на файлы. Скрипт должен читать конфиги. Логи должны писаться. Директории должны быть доступны для записи. Используйте ls -la и chmod при необходимости.
  6. Используйте виртуальные окружения. Не устанавливайте зависимости глобально. Они конфликтуют. Создайте venv и запускайте скрипт через /path/to/venv/bin/python3.
  7. Добавьте обработку исключений в код. Даже в cron-скриптах. Если ваш скрипт падает с ошибкой — он просто умрёт. Добавьте в начало:
    
    
    import sys
    import traceback
    
    try:
        # ваш код
    except Exception as e:
        with open('/home/user/logs/errors.log', 'a') as f:
            f.write(f"{datetime.now()}: {str(e)}\n{traceback.format_exc()}\n")
        sys.exit(1)
    Не забывайте пр
    о ограничения ресурсов.
    Если скрипт потребляет много памяти — добавьте в systemd MemoryLimit=512M. Если он грузит CPU — используйте CPULimit=50.
  8. Делайте бэкап crontab и systemd-файлов. Эти файлы — ваша инфраструктура. Сохраняйте их в Git. Если сервер умрёт — вы сможете восстановить всё за 5 минут.
  9. Пишите документацию. В файле README.md в папке со скриптом напишите: «Как запустить», «Как смотреть логи», «Как перезапустить». Через полгода вы забудете, как всё работает — и ваш коллега будет благодарен.

Автоматизация — это не про то, чтобы не работать. Это про то, чтобы работать умнее. Когда вы настроили cron, systemd или nohup — вы не просто запустили скрипт. Вы создали цифровое существо, которое живёт, работает и не требует вашего внимания. И это — настоящее искусство программирования.

Сегодня вы — не просто разработчик. Вы — создатель систем. И ваша задача — чтобы эти системы работали, даже когда вы спите.