Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Usługa Linuxa z systemd

Benjamin Morel Full Stack Software Engineer / Nicebooks
Zobacz, jak łatwo i szybko stworzyć Linuxową usługę z systemd.
Usługa Linuxa z systemd

Pisząc aplikacje webowe, często muszę przekazywać część ciężkich zadań asynchronicznemu workerowi, planować niektóre czynności na później lub nawet tworzyć demona, który używa gniazda do bezpośredniej komunikacji z klientem. 

Pomimo że zawsze znajdziesz lepsze narzędzie do pracy (rozważ najpierw użycie istniejącego oprogramowania, takiego jak kolejka zadań), napisanie czegoś swojego być może da Ci poczucie elastyczności, której może zabraknąć przy gotowych rozwiązaniach.   

Fajne jest też to, że można łatwo stworzyć usługę Linuxa. Użyj po prostu swojego ulubionego języka do napisania długo działającego programu i przemień go w usługę przy użyciu systemd. 

Program

Napiszmy mały serwer w PHP. Wyczuwam Twoje zwątpienie, ale zobaczycie, że wszystko będzie sprawnie działać. Będziemy nasłuchiwać na porcie 10000 przy użyciu UDP i zwrócimy każdą wiadomość otrzymaną z ROT13: 

<?php

$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, '0.0.0.0', 10000);

for (;;) {
    socket_recvfrom($sock, $message, 1024, 0, $ip, $port);
    $reply = str_rot13($message);
    socket_sendto($sock, $reply, strlen($reply), 0, $ip, $port);
}


Uruchamiamy: 

$ php server.php


I testujemy na innym terminalu: 

$ nc -u 127.0.0.1 10000
Hello, world!
Uryyb, jbeyq!


Działa! Chcemy teraz, aby nasz skrypt zawsze działał, sam się restartował w przypadku błędu (np. niespodziewanego wyjścia) no i wstawał po restarcie systemu. Tutaj z pomocą przychodzi systemd

Przemiana skryptu w usługę

Stwórzmy plik o nazwie /etc/systemd/system/rot13.service:

[Unit]
Description=ROT13 demo service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=centos
ExecStart=/usr/bin/env php /path/to/server.php

[Install]
WantedBy=multi-user.target


Co musisz zrobić:

  • ustaw swoją nazwę użytkownika na User=
  • ustaw ścieżkę do skryptu jako ExecStar=


I to by było na tyle. Możemy teraz ruszać z usługą: 

$ systemctl start rot13


I od razu sprawić, żeby się odpalała: 

$ systemctl enable rot13


Idąc dalej

Teraz kiedy nasza usługa już działa, trzeba wejść w opcje konfiguracji, aby upewnić się, że nie będzie żadnych niespodzianek. 


Zaczynając w odpowiedniej kolejności

Zastanawiacie się pewnie, co zrobiła dyrektywa After=. Sprawiła, że Twoja usługa zacznie działać po tym, jak sieć będzie gotowa. Jeśli Twój program spodziewa się, że serwer MySQL będzie włączony, powinno się dodać:

After=mysqld.service


Restart przy wyjściu

W domyśle systemd nie restartuje Twojej usługi, jeśli program przestaje działać. Nie chcemy jednak, żeby tak było. Musimy kazać jej odpalać się ponownie w każdym przypadku wyjścia z programu:

Restart=always


Można też użyć on-failure, aby zrestartować usługę, tylko jeśli exit status nie wynosi 0. Domyślnie, systemd próbuje ponownie odpalić program po 100ms. Można jednak samemu sprecyzować czas oczekiwania na restart:  

RestartSec=1


Nie wpadnij w pułapkę limitu startowego!

Sam niestety nie raz w nią wpadłem. Domyślnie, konfiguracja Restart=always w taki sposób, w jaki my to zrobiliśmy, spowoduje, że systemd odmówi restartu Twojej usługi, jeśli nie uda mu się włączyć jej 5 razy w 10-sekundowym interwale.

Istnieją dwie opcje konfiguracji w [Unit] za to odpowiedzialne: 

StartLimitBurst=5
StartLimitIntervalSec=10


Dyrektywa RestartSec również ma wpływ na wynik: jeśli ustawisz ją, żeby restartowała usługę po 3 sekundach, nie osiągniesz poziomu 5 nieudanych prób w 10-sekundowym interwale.

Prosty fix polega na ustawieniu StartLimitIntervalSec=0. W taki sposób systemd zawsze będzie ponowanie odpalać Twoją usługę. 

Dobrze jest jednak ustawić RestartSec na chociaż jedną sekundę, aby nie kłaść zbyt dużo na barki serwera, kiedy coś się popsuje. 

Możesz jeszcze ewentualnie zostawić ustawienia domyślne i poprosić systemd o ponowne odpalenie serwera, jeśli limit startowy został osiągnięty. Zrób to przy pomocy StartLimitAction=reboot.


Ale czy to już wszystko? 

Tak, to wszystko, jeżeli chodzi o tworzenie usługi Linuxa z systemd. Piszemy mały plik konfiguracyjny, który odwołuje się do programu, który ma działać w tle.

Systemd już od kilku lat jest domyślną częścią RHEL/CentOS, Fedora, Ubuntu, Debian i innych. Istnieje więc szansa, że Twój serwer będzie gotowy do uruchamiania własnoręcznie stworzonych usług.

Oryginał tesktu w języku angielskim przeczytasz tutaj.

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej