Jak używać systemd do uruchomienia usługi Linux przy starcie systemu
Zapewnienie, że usługi krytyczne uruchamiają się automatycznie po ponownym uruchomieniu serwera, jest jedną z najbardziej fundamentalnych odpowiedzialności każdego administratora systemów Linux. Niezależnie od tego, czy uruchamiasz aplikację internetową, silnik bazy danych czy niestandardowy demon na środowisku VPS Hosting, nieoczekiwane ponowne uruchomienie nigdy nie powinno oznaczać przedłużonej przerwy w działaniu. Dzięki systemd — nowoczesnemu systemowi init zasilającemu większość dzisiejszych dystrybucji Linux — możesz dokładnie zdefiniować jak, kiedy i jako kto uruchamiają się Twoje usługi, wszystko poprzez czysty, deklaratywny plik jednostki.
Ten kompleksowy przewodnik przeprowadzi Cię przez każdy krok: zrozumienie czym jest systemd, tworzenie gotowego do produkcji pliku jednostki usługi, weryfikacja uprawnień, testowanie pliku wykonywalnego i zarządzanie cyklem życia usługi. Na koniec Twoja niestandardowa aplikacja będzie automatycznie przetrwać każde ponowne uruchomienie.
Czym jest systemd i dlaczego to ważne?
systemd to system init i menedżer usług, który zastąpił starsze alternatywy takie jak SysVinit i Upstart w większości głównych dystrybucji Linux, w tym Ubuntu, Debian, CentOS, Rocky Linux, AlmaLinux i Fedora. Zamiast wykonywać sekwencyjny łańcuch skryptów powłoki podczas uruchamiania, systemd paralelizuje uruchamianie usług, rozwiązuje porządkowanie zależności i zarządza całym cyklem życia procesów systemowych z jednego, ujednoliconego interfejsu.
Kluczowe zalety systemd dla środowisk serwerowych
| Funkcja | Korzyść |
|---|---|
| Równoległy startup usług | Szybsze czasy uruchamiania na serwerach z wieloma usługami |
| Zarządzanie zależnościami | Usługi uruchamiają się tylko po przygotowaniu ich wymagań wstępnych |
| Automatyczne zasady ponownego uruchamiania | Usługi, które się zawiesiły, odzyskują się bez ręcznej interwencji |
| Centralne logowanie poprzez journald | Wszystkie dane wyjściowe usługi przechwytywane w przeszukiwalnym dzienniku |
| Kontrola zasobów oparta na cgroup | Limity CPU i pamięci wymuszane na usługę |
| Aktywacja gniazda i urządzenia | Usługi uruchamiają się na żądanie, nie bezwarunkowo |
Dla każdego, kto zarządza aplikacjami na Dedicated Servers lub instancjach VPS, te możliwości przekładają się bezpośrednio na wyższą dostępność i bardziej przewidywalne zachowanie pod obciążeniem.
Zrozumienie plików jednostek systemd
Wszystko, czym zarządza systemd, jest reprezentowane przez plik jednostki — zwykły plik konfiguracyjny podzielony na sekcje. Plik jednostki service mówi systemd:
- Co to jest usługa (metadane, opis, zależności)
- Jak ją uruchomić (ścieżka pliku wykonywalnego, katalog roboczy, kontekst użytkownika)
- Kiedy ją uruchomić (cel uruchamiania, porządkowanie względem innych jednostek)
- Co zrobić jeśli się nie powiedzie (zasada ponownego uruchamiania, opóźnienie ponownego uruchamiania)
Pliki jednostek usługi dla usług całego systemu znajdują się w /etc/systemd/system/. Pliki umieszczone tutaj mają pierwszeństwo przed jednostkami dostarczonymi przez dostawcę w /lib/systemd/system/ i utrzymują się podczas aktualizacji pakietów.
Krok po kroku: Tworzenie jednostki usługi systemd
Poniższy przewodnik używa fikcyjnej aplikacji o nazwie myapp. Zastąp każde wystąpienie myapp, myapp-user i /opt/myapp wartościami odpowiednimi dla Twojego własnego środowiska.
Krok 1: Przygotuj katalog roboczy
Przed napisaniem pliku jednostki zdecyduj, skąd będzie uruchamiana Twoja aplikacja. Dedykowany katalog roboczy utrzymuje pliki konfiguracyjne, dzienniki i dane czasu wykonywania zorganizowane i czyni zarządzanie uprawnieniami proste.
Utwórz katalog, jeśli jeszcze nie istnieje:
sudo mkdir -p /opt/myapp> Dlaczego /opt/myapp zamiast /etc/systemd/?
> Drzewo /etc/systemd/ jest zarezerwowane dla własnej konfiguracji systemd. Umieszczanie tam danych aplikacji jest niestandardowe i może powodować zamieszanie. Użyj /opt/, /srv/ lub /var/lib/ w zależności od kategorii Filesystem Hierarchy Standard, która najlepiej pasuje do Twojego obciążenia.
Przypisz własność użytkownikowi, który będzie uruchamiać usługę:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myuser
sudo chown -R myuser:myuser /opt/myappUżywanie dedykowanego konta systemowego (bez powłoki logowania, bez katalogu domowego) jest najlepszą praktyką bezpieczeństwa. Ogranicza to zasięg szkód, jeśli aplikacja kiedykolwiek zostanie zagrożona.
Zweryfikuj wynik:
ls -ld /opt/myapp
# Expected output: drwxr-xr-x 2 myuser myuser 4096 Jan 1 00:00 /opt/myappKrok 2: Utwórz plik jednostki usługi
Otwórz nowy plik jednostki za pomocą preferowanego edytora:
sudo nano /etc/systemd/system/myapp.serviceWklej poniższą zawartość, dostosowując wartości do Twojej aplikacji:
[Unit]
Description=My Custom Application
Documentation=https://example.com/docs
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/myapp --config /opt/myapp/myapp.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
User=myuser
Group=myuser
WorkingDirectory=/opt/myapp
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.targetZapisz plik za pomocą Ctrl+O, a następnie wyjdź za pomocą Ctrl+X.
Krok 3: Zrozumienie każdej dyrektywy
Sekcja [Unit]
| Dyrektywa | Cel |
|---|---|
| Description= | Nazwa czytelna dla człowieka wyświetlana w danych wyjściowych systemctl |
| Documentation= | Odnośnik URL lub strona man dla usługi |
| After= | Zapewnia, że usługa uruchamia się *po* aktywacji wymienionej jednostki |
| Wants= | Miękka zależność — systemd *spróbuje* uruchomić wymienioną jednostkę, ale się nie powiedzie, jeśli jest niedostępna |
> After=network-online.target vs After=network.target: Użyj network-online.target (w połączeniu z Wants=) dla usług, które naprawdę potrzebują w pełni skonfigurowanego interfejsu sieciowego — na przykład aplikacji, która łączy się ze zdalną bazą danych lub zewnętrznym API podczas uruchamiania. network.target gwarantuje tylko, że podsystem sieciowy został *uruchomiony*, a nie że interfejsy są aktywne i mają przypisane adresy.
Sekcja [Service]
| Dyrektywa | Cel |
|---|---|
| Type=simple | Proces uruchomiony przez ExecStart= jest procesem głównym (domyślnie dla większości aplikacji) |
| ExecStart= | Pełna ścieżka do pliku binarnego i wszelkich argumentów. Zawsze używaj ścieżek bezwzględnych. |
| ExecReload= | Polecenie do przeładowania konfiguracji bez pełnego ponownego uruchomienia (opcjonalne, ale zalecane) |
| Restart=on-failure | Uruchom ponownie usługę tylko wtedy, gdy wyjdzie z kodem niezerowym lub zostanie zabita przez sygnał. Użyj always, jeśli chcesz ponownych uruchomień nawet przy czystych wyjściach. |
| RestartSec= | Sekundy oczekiwania przed próbą ponownego uruchomienia |
| User= / Group= | Uruchom proces jako ten użytkownik/grupę zamiast root |
| WorkingDirectory= | Ustaw bieżący katalog przed wykonaniem ExecStart= |
| StandardOutput= / StandardError= | Kieruj stdout/stderr do dziennika systemd |
| SyslogIdentifier= | Tag używany do filtrowania wpisów dziennika dla tej usługi |
| NoNewPrivileges= | Uniemożliwia procesowi uzyskanie dodatkowych uprawnień poprzez binarne setuid |
| ProtectSystem=strict | Montuje /usr, /boot i /etc jako tylko do odczytu dla usługi |
| ProtectHome= | Czyni /root, /home i /run/user niedostępnymi |
| PrivateTmp= | Daje usłudze własną prywatną przestrzeń nazw /tmp |
Sekcja [Install]
| Dyrektywa | Cel |
|---|---|
| WantedBy=multi-user.target | Włącza usługę, gdy system osiąga standardowy poziom wieloużytkownika (bez grafiki). To jest prawidłowy cel dla praktycznie wszystkich demonów serwerowych. |
Krok 4: Zweryfikuj uprawnienia pliku i katalogów
Przed przeładowaniem systemd, potwierdź, że użytkownik usługi może faktycznie uzyskać dostęp do wszystkiego, czego potrzebuje:
# Check working directory ownership and permissions
ls -ld /opt/myapp
# Confirm the executable exists and is executable
ls -l /usr/bin/myapp
# Verify the config file is readable by myuser
sudo -u myuser cat /opt/myapp/myapp.confJeśli którekolwiek z tych sprawdzeń się nie powiedzie, popraw uprawnienia przed kontynuowaniem:
# Make the binary executable
sudo chmod +x /usr/bin/myapp
# Grant read access to the config file
sudo chmod 640 /opt/myapp/myapp.conf
sudo chown myuser:myuser /opt/myapp/myapp.confKrok 5: Testuj plik wykonywalny ręcznie
Zawsze zweryfikuj, że Twoja aplikacja działa prawidłowo *przed* przekazaniem kontroli systemd. To izoluje błędy aplikacji od problemów konfiguracji systemd:
sudo -u myuser /usr/bin/myapp --config /opt/myapp/myapp.confJeśli aplikacja uruchamia się bez błędów, naciśnij Ctrl+C, aby ją zatrzymać i przejść dalej. Jeśli się nie powiedzie, rozwiąż samą aplikację — sprawdź, czy wszystkie zależności są zainstalowane, zmienne środowiskowe są ustawione i wymagane porty są dostępne.
Krok 6: Przeładuj systemd i włącz usługę
Po zapisaniu pliku jednostki poinstruuj systemd, aby ponownie przeczytał swoją konfigurację:
sudo systemctl daemon-reloadWłącz usługę, aby uruchamiała się automatycznie przy każdym kolejnym uruchomieniu:
sudo systemctl enable myapp.serviceTo polecenie tworzy dowiązanie symboliczne w odpowiednim katalogu /etc/systemd/system/multi-user.target.wants/, łącząc Twój plik jednostki w sekwencję uruchamiania multi-user.target. Powinieneś zobaczyć dane wyjściowe podobne do:
Created symlink /etc/systemd/system/multi-user.target.wants/myapp.service → /etc/systemd/system/myapp.service.Uruchom usługę natychmiast bez ponownego uruchamiania:
sudo systemctl start myapp.serviceKrok 7: Zweryfikuj, że usługa działa
Sprawdź bieżący stan usługi:
sudo systemctl status myapp.serviceZdrowa usługa daje dane wyjściowe podobne do:
● myapp.service - My Custom Application
Loaded: loaded (/etc/systemd/system/myapp.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2025-01-01 12:00:00 UTC; 5s ago
Main PID: 12345 (myapp)
Tasks: 4 (limit: 4915)
Memory: 12.3M
CPU: 45ms
CGroup: /system.slice/myapp.service
└─12345 /usr/bin/myapp --config /opt/myapp/myapp.confKluczowe pola do weryfikacji:
- Loaded — potwierdza, że plik jednostki został pomyślnie przeanalizowany i pokazuje, czy jest enabled czy disabled dla uruchamiania
- Active — usługa jest aktualnie uruchomiona
- Main PID — identyfikator procesu Twojej aplikacji
Krok 8: Monitoruj dzienniki za pomocą journalctl
systemd kieruje wszystkie dane wyjściowe usługi do dziennika, strukturalnego, przeszukiwalnego magazynu dzienników. Użyj journalctl, aby go sprawdzić:
# View all logs for myapp (most recent last)
journalctl -u myapp.service
# Follow live log output (like tail -f)
journalctl -u myapp.service -f
# Show only logs since the last boot
journalctl -u myapp.service -b
# Show the last 50 lines
journalctl -u myapp.service -n 50
# Show logs since a specific time
journalctl -u myapp.service --since "2025-01-01 12:00:00"Jeśli Twoja usługa nie uruchamia się, dziennik prawie zawsze zawiera dokładny komunikat błędu wyjaśniający dlaczego. To jest pierwsze miejsce, w którym należy szukać przed dokonaniem jakichkolwiek zmian.
Krok 9: Testuj zachowanie podczas uruchamiania
Aby potwierdzić, że usługa przetrwa ponowne uruchomienie bez ręcznego sprawdzania sekwencji uruchamiania, możesz to symulować:
# Reboot the server (only if safe to do so)
sudo rebootPo powrocie serwera do trybu online, sprawdź ponownie stan usługi:
sudo systemctl status myapp.serviceJeśli pokazuje active (running), Twoja usługa jest prawidłowo skonfigurowana do automatycznego uruchamiania.
Zarządzanie cyklem życia usługi
Gdy Twoja usługa jest uruchomiona, będziesz regularnie używać następujących poleceń:
Typowe polecenia systemctl
# Start the service
sudo systemctl start myapp.service
# Stop the service gracefully
sudo systemctl stop myapp.service
# Restart the service (stop + start)
sudo systemctl restart myapp.service
# Reload configuration without restarting (if ExecReload is defined)
sudo systemctl reload myapp.service
# Enable automatic startup at boot
sudo systemctl enable myapp.service
# Disable automatic startup at boot
sudo systemctl disable myapp.service
# Check whether the service is enabled
sudo systemctl is-enabled myapp.service
# Check whether the service is currently active
sudo systemctl is-active myapp.service
# View the full unit file as systemd interprets it
sudo systemctl cat myapp.service
# Edit the unit file and reload in one step
sudo systemctl edit --full myapp.serviceRozwiązywanie typowych problemów
Usługa nie uruchamia się: „No such file or directory”
Zwykle oznacza to, że ExecStart= wskazuje na nieistniejący plik binarny lub WorkingDirectory= nie istnieje. Zweryfikuj obie ścieżki:
which myapp
ls -l /opt/myappUsługa uruchamia się, ale natychmiast wychodzi
Sprawdź dziennik dla własnych danych wyjściowych błędu aplikacji:
journalctl -u myapp.service -n 100 --no-pagerRównież zweryfikuj, że Type= jest prawidłowy dla Twojej aplikacji. Jeśli Twój plik binarny rozwidla się w tle, użyj Type=forking zamiast Type=simple.
Błędy „Permission denied”
Użytkownik usługi nie ma dostępu do wymaganego pliku lub katalogu. Użyj ls -la, aby przeprowadzić audyt uprawnień i sudo -u myapp-user test, aby testować dostęp interaktywnie.
Port już w użyciu
Inny proces jest powiązany z portem, którego potrzebuje Twoja aplikacja. Zidentyfikuj go za pomocą:
sudo ss -tlnp | grep :<port>Usługa uruchamia się w pętli
Jeśli Restart=on-failure powoduje szybkie pętle ponownego uruchamiania, systemd ostatecznie ograniczy ponowne uruchamianie. Sprawdź StartLimitInterval= i StartLimitBurst= w sekcji [Service], aby dostroić to zachowanie, i zawsze zbadaj główną przyczynę w dzienniku.
Zaawansowane wzorce systemd dla serwerów produkcyjnych
Zmienne środowiskowe i pliki środowiskowe
Nigdy nie koduj na stałe sekretów w plikach jednostek. Zamiast tego użyj pliku środowiskowego:
[Service]
EnvironmentFile=/etc/myapp/myapp.env
ExecStart=/usr/bin/myappUtwórz /etc/myapp/myapp.env z chmod 600 i chown myapp-user:myapp-user, aby ograniczyć dostęp:
DATABASE_URL=postgresql://user:password@localhost/mydb
API_KEY=supersecretkeyZależności usług i porządkowanie
Jeśli Twoja aplikacja zależy od usługi bazy danych (np. PostgreSQL lub MySQL), zadeklaruj tę zależność jawnie:
[Unit]
After=network-online.target postgresql.service
Requires=postgresql.serviceRequires= jest twardą zależnością — jeśli PostgreSQL nie uruchomi się, systemd również nie spróbuje uruchomić Twojej usługi.
Integracja Watchdog
Dla usług krytycznych dla misji włącz wbudowany watchdog systemd, aby wykryć zawieszone procesy:
[Service]
WatchdogSec=30s
Restart=on-watchdogTwoja aplikacja musi okresowo wywoływać sd_notify(0, “WATCHDOG=1”), aby zresetować timer watchdoga. Jeśli tego nie zrobi w ciągu WatchdogSec=, systemd zabija i uruchamia ponownie usługę.
Wybór odpowiedniego środowiska hostingowego
Wzorce konfiguracji systemd opisane w tym przewodniku dotyczą równomiernie wszystkich typów serwerów Linux, ale Twój wybór infrastruktury hostingowej wpływa na to, ile kontroli masz nad systemem init i zarządzaniem usługami.
- VPS Hosting — Pełny dostęp root, pełna kontrola systemd, idealny do niestandardowych wdrożeń aplikacji. Plany VPS AlexHost działają na wirtualizacji KVM, dając Ci prawdziwe izolowane środowisko jądra.
- Dedicated Servers — Maksymalna wydajność i izolacja dla usług wymagających dużych zasobów. Pełny dostęp do sprzętu bez hałaśliwych sąsiadów.
- VPS z cPanel — Łączy dostęp na poziomie root do systemd z graficznym panelem kontrolnym dla zespołów, które zarządzają zarówno usługami systemowymi, jak i hostingiem internetowym z jednego interfejsu.
- Shared Web Hosting
on All Hosting Services
