Автозапуск программ при старте сервера (systemd и cron)
Как приложения, игровые серверы и скрипты запускаются сами после каждой перезагрузки: через 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?
Сервис работает вручную, но не стартует при загрузке. Почему?
Как посмотреть вывод моего сервиса?
Нужны ли ещё screen или tmux для игрового сервера?
2024-2026 KernelHost GmbH. Все права защищены. Эта инструкция охраняется авторским правом. Публикация на других сайтах, в том числе частично или в изменённом виде, без нашего письменного согласия не разрешается. Цитирование с указанием источника и активной ссылкой мы приветствуем.

