Автозапуск программ при старте сервера (systemd и cron)

Опубликовано Обновлено 5 мин. чтения

Как приложения, игровые серверы и скрипты запускаются сами после каждой перезагрузки: через service-юнит systemd как сегодняшний стандарт или через запись в cron с @reboot.

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

Мы разберём два пути: service-юнит systemd как принятое сегодня решение и более старый вариант через запись в cron с @reboot. Оба способа работают независимо от дистрибутива, то есть одинаково на Debian, Ubuntu, AlmaLinux и Rocky Linux.

systemd или cron: какой путь подходит?

systemd — стандарт для управления сервисами во всех актуальных дистрибутивах Linux. Запись в cron с @reboot тоже запустит ваше приложение, но на этом её возможности заканчиваются.

Характеристикаsystemd-юнитcron с @reboot
Запуск при загрузкедада
Перезапуск после сбояда, автоматическинет
Запрос статусада, через systemctlнет
Журнал выводада, в journalтолько при ручном перенаправлении
Управление порядком запускада, например после сетитолько грубо, через sleep

Для всего, что должно работать постоянно, systemd-юнит — лучший выбор. Запись в cron остаётся быстрым временным решением для простых одиночных команд.

Требования

  • root-доступ к вашему VPS или root-серверу по SSH.
  • Скрипт запуска или программа, которая уже корректно стартует из командной строки. Сначала проверьте это вручную, прежде чем автоматизировать.
  • Абсолютный путь к этому скрипту. Относительные пути при старте системы работают ненадёжно.

Создание service-юнита systemd

Собственные юниты лежат в /etc/systemd/system/ и заканчиваются на .service. Создайте файл:

nano /etc/systemd/system/myservice.service

Простой, сразу готовый к работе каркас выглядит так:

[Unit]
Description=Мой собственный сервис
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myuser
WorkingDirectory=/opt/myservice
ExecStart=/bin/bash /opt/myservice/start.sh
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Что означают отдельные строки

  • Description: Понятное название, которое показывает systemctl status.
  • After и Wants: Сервис стартует только тогда, когда сеть уже доступна. Благодаря этому отпадает трюк с sleep, знакомый по cron.
  • Type=simple: Программа продолжает работать на переднем плане. Если ваш скрипт запуска сам уходит в фон, вместо этого понадобятся Type=forking и указание PIDFile.
  • User: Пользователь, от имени которого работает сервис. Никогда не запускайте приложения от root без необходимости.
  • WorkingDirectory: Заменяет cd из скрипта запуска.
  • Restart=on-failure: systemd перезапускает сервис после сбоя. С параметром Restart=always он делает это и тогда, когда программа завершилась штатно.
  • WantedBy=multi-user.target: Отвечает за то, чтобы сервис поднимался вместе с обычной загрузкой системы.

Активация и проверка сервиса

После каждого изменения файла юнита systemd должен перечитать его заново. Затем включите сервис в автозагрузку и сразу запустите его:

systemctl daemon-reload
systemctl enable --now myservice.service

Работает ли всё, покажет команда:

systemctl status myservice.service

Вывод приложения попадает в journal. Следующей командой вы читаете его в реальном времени, и при поиске ошибок это самый быстрый путь:

journalctl -u myservice.service -f

Для остановки, перезапуска или окончательного отключения:

systemctl stop myservice.service
systemctl restart myservice.service
systemctl disable myservice.service

Пример: автоматический запуск сервера TeamSpeak 3

Штатный скрипт запуска TeamSpeak сам уходит в фон и создаёт PID-файл. Поэтому здесь правильным будет Type=forking:

[Unit]
Description=TeamSpeak 3 Server
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
User=teamspeak
WorkingDirectory=/home/teamspeak
ExecStart=/home/teamspeak/ts3server_startscript.sh start
ExecStop=/home/teamspeak/ts3server_startscript.sh stop
PIDFile=/home/teamspeak/ts3server.pid
Restart=on-failure
RestartSec=15

[Install]
WantedBy=multi-user.target

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

Пример: игровой сервер или бот через скрипт запуска

Для Minecraft, ARK, Arma 3, серверов LinuxGSM или самописного бота, как правило, достаточно простого варианта. Сервис работает на переднем плане, а контроль и перезапуск берёт на себя systemd:

[Unit]
Description=Игровой сервер
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=gameserver
WorkingDirectory=/home/gameserver/server
ExecStart=/bin/bash /home/gameserver/server/start.sh
Restart=always
RestartSec=15

[Install]
WantedBy=multi-user.target

Если несколько сервисов стартуют одновременно и мешают друг другу, разнесите старт разными значениями RestartSec или дополните After= именем того юнита, который должен запуститься первым.

Альтернатива: автозапуск через cron с @reboot

Если при загрузке нужно выполнить всего одну команду и контроль не требуется, хватит записи в cron. Сначала задайте редактор и откройте crontab:

export VISUAL=nano; crontab -e

Впишите там строку с @reboot:

@reboot sleep 60 && cd /<ПУТЬ-К-СКРИПТУ>/ && bash <ВАШ-СКРИПТ>.sh

@reboot отвечает за то, чтобы команда выполнялась один раз при каждом старте системы. Часть sleep 60 ждёт 60 секунд, чтобы сеть и база данных успели подняться. После этого команда переходит в каталог вашего скрипта и запускает его.

Пример для голосового сервера, который должен работать от отдельного пользователя:

@reboot sleep 45 && cd /home/<ДИРЕКТОРИЯ-TEAMSPEAK>/ && sudo -u <ПОЛЬЗОВАТЕЛЬ-TEAMSPEAK> bash ts3server_startscript.sh start

Если вы вносите несколько строк, задайте каждой своё значение sleep (минимум 45), чтобы не все сервисы стартовали одновременно. Значение указывается в секундах.

Частые ошибки

  • Сервис не стартует, хотя вручную работает: Чаще всего не хватает абсолютного пути. В юните и в cron переменная окружения PATH задана очень скудно, поэтому всегда пишите /bin/bash /полный/путь/скрипт.sh.
  • «Unit not found» сразу после создания файла: Вы забыли systemctl daemon-reload.
  • Сервис сразу же завершается: Программа уходит в фон. Используйте Type=forking с подходящим PIDFile или запускайте программу в режиме переднего плана.
  • Ошибки прав при запуске: Пользователь, указанный в User=, не имеет доступа к каталогу. Проверьте владельца командой ls -la.
  • После загрузки ничего не работает: Сервис был запущен, но не активирован. systemctl enable — это тот шаг, который прописывает его в автозагрузку.

И напоследок лучший тест: перезагрузите сервер командой reboot и затем проверьте через systemctl status, все ли сервисы работают как ожидалось.

Частые вопросы

Что лучше: systemd или cron с @reboot?
Для всего, что должно работать постоянно, systemd явно выигрывает. Он перезапускает приложение после сбоя, показывает статус и пишет вывод в журнал. Запись в cron просто выполняет команду один раз при загрузке.
Где размещать собственный юнит systemd?
Собственные файлы юнитов кладутся в /etc/systemd/system/ и заканчиваются на .service. После каждого изменения нужно выполнить systemctl daemon-reload, иначе systemd не увидит файл.
Сервис работает вручную, но не стартует при загрузке. Почему?
Чаще всего не хватает абсолютного пути, потому что переменная окружения PATH при старте системы задана очень скудно. Вторая по частоте причина: сервис только запустили, но так и не активировали командой systemctl enable.
Как посмотреть вывод моего сервиса?
systemd пишет всё в journal. Командой journalctl -u myservice.service -f вы читаете вывод в реальном времени, и при поиске ошибок это самый быстрый путь.
Нужны ли ещё screen или tmux для игрового сервера?
Нет. systemd сам поддерживает процесс запущенным, логирует вывод и автоматически перезапускает его после сбоя. Для постоянной работы screen и tmux уже не нужны.

Автозапуск systemd Crontab Linux Игровой сервер TeamSpeak3 Запуск сервера