Запуск Python-скриптов в фоновом режиме — фундаментальный навык для любого разработчика, работающего с Linux. Это позволяет выполнять долгие задачи, веб-серверы, ботов или обработчики данных, не блокируя терминал и продолжая работу в системе. В этой статье мы разберем все методы — от простейших до профессиональных, с подробными примерами и объяснением, что происходит «под капотом».
Почему просто закрыть терминал недостаточно?
Если запустить скрипт командой python3 script.py и закрыть терминал, процесс будет завершен вместе с родительской сессией. Это происходит потому, что процесс привязан к управляющему терминалу (controlling terminal). Нам нужно либо отвязать процесс от терминала, либо сделать его независимым.
Важно: Фоновый режим ≠ параллельное выполнение (многопоточность/многопроцессность). Речь идет о запуске процесса, который продолжает жить после закрытия сессии пользователя.
Базовые методы: &, nohup и disown
1. Амперсанд (&) — простейший фон
Добавьте символ & в конец команды:
python3 long_script.py &
Скрипт запустится в фоне, но останется привязан к текущему терминалу. Если терминал закрыть — процесс, скорее всего, получит сигнал SIGHUP и завершится.
2. nohup — игнорирование сигнала HUP
Команда nohup (no hang up) заставляет процесс игнорировать сигнал SIGHUP, отправляемый при закрытии терминала:
nohup python3 script.py &
Вывод скрипта по умолчанию перенаправляется в файл nohup.out. Вы можете перенаправить его самостоятельно:
nohup python3 script.py > output.log 2>&1 &
Совет: Всегда перенаправляйте stdout и stderr в файлы при использовании nohup, иначе вы потеряете логи и сообщения об ошибках.
3. disown — «открепить» уже запущенный процесс
Если вы уже запустили скрипт в фоне с помощью &, но забыли про nohup, можно «открепить» его от сессии:
- Запустите скрипт:
python3 script.py & - Выполните
jobs -lчтобы увидеть ID задания (например, [1] 12345). - Выполните
disown %1(где 1 — номер задания) илиdisown -h 12345(где 12345 — PID).
Теперь процесс переживет закрытие терминала.
Профессиональные подходы: systemd и screen/tmux
systemd — управление как системной службой
Идеально для скриптов, которые должны работать постоянно и автоматически перезапускаться. Создайте файл службы:
sudo nano /etc/systemd/system/my_script.service
Содержимое файла:
[Unit]
Description=My Python Script
After=network.target
[Service]
Type=simple
User=username
WorkingDirectory=/path/to/script
ExecStart=/usr/bin/python3 /path/to/script/script.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
Далее:
sudo systemctl daemon-reloadsudo systemctl start my_scriptsudo systemctl enable my_script(для автозапуска при загрузке)sudo systemctl status my_script(проверка состояния)
tmux/screen — виртуальные терминалы
Эти программы создают сессии, которые можно «отключать» и подключать заново.
# Установка tmux: sudo apt install tmux
# Создание сессии:
tmux new -s mysession
# Запуск скрипта внутри сессии:
python3 script.py
# Отсоединение: Ctrl+B, затем D
# Повторное подключение: tmux attach -t mysession
Сессия tmux продолжит работать в фоне даже после закрытия SSH-соединения.
Практические рекомендации
- Логирование: Всегда настраивайте ротацию логов (logrotate) для долгоживущих процессов.
- Мониторинг: Используйте
htop,ps aux | grep pythonилиsystemctl statusдля отслеживания. - Виртуальные окружения: При использовании systemd укажите полный путь к python в venv в ExecStart.
- Остановка процессов: Найдите PID через
ps aux | grep script.pyи отправьте сигналkill PIDилиkill -9 PID(принудительно).
FAQ — Часто задаваемые вопросы
Как проверить, работает ли мой фоновый Python-скрипт?
Используйте команду ps aux | grep python или pgrep -f "script.py". Для systemd служб — systemctl status имя_службы.
Как остановить фоновый скрипт?
Найдите его PID (идентификатор процесса) через ps aux | grep python и выполните kill PID. Для systemd: sudo systemctl stop имя_службы.
Куда сохраняются логи при использовании nohup?
По умолчанию — в файл nohup.out в текущей директории. Рекомендуется явно перенаправлять вывод: nohup python3 script.py > mylog.log 2>&1 &.
Чем systemd лучше nohup?
Systemd обеспечивает автоматический перезапуск при сбоях, централизованное управление, ротацию логов, запуск от определенного пользователя и интеграцию в систему инициализации.
Можно ли запустить несколько копий скрипта в фоне?
Да, но они должны использовать разные PID. Убедитесь, что скрипты не конфликтуют за ресурсы (порты, файлы). Для systemd можно создать шаблон службы (@).
Как сделать, чтобы скрипт запускался при загрузке системы?
Лучший способ — создать службу systemd и выполнить sudo systemctl enable имя_службы. Альтернатива — добавить команду с nohup в /etc/rc.local (устаревший метод).