Articles

Tworzenie usługi linuksowej za pomocą systemd

Posted on
Tworzenie własnych usług – fot. your own services – Photo by Jeff Sheldon on Unsplash

Podczas pisania aplikacji internetowych, często potrzebuję odciążyć ciężkie obliczeniowo zadania do asynchronicznego skryptu robotniczego, zaplanować zadania na później, lub nawet napisać demona, który nasłuchuje gniazda, aby komunikować się bezpośrednio z klientami.

Choć czasami mogą istnieć lepsze narzędzia do wykonania tego zadania – zawsze najpierw rozważ użycie istniejącego oprogramowania, takiego jak serwer kolejki zadań – napisanie własnej usługi może dać ci poziom elastyczności, którego nigdy nie uzyskasz, będąc związanym ograniczeniami oprogramowania firm trzecich.

Ciekawe jest to, że stworzenie usługi dla Linuksa jest dość proste: użyj swojego ulubionego języka programowania, aby napisać długo działający program i zamień go w usługę za pomocą systemd.

Ztwórzmy mały serwer używając PHP. Już widzę, jak podnoszą się Twoje brwi, ale działa to zaskakująco dobrze. Będziemy nasłuchiwać na porcie UDP 10000, a każdą otrzymaną wiadomość będziemy zwracać z transformacją ROT13:

Uruchommy go:

$ php server.php

I przetestujmy go w innym terminalu:

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

Cool, działa. Teraz chcemy, aby ten skrypt działał przez cały czas, był restartowany w przypadku awarii (nieoczekiwanego wyjścia), a nawet przetrwał restart serwera. To jest miejsce gdzie systemd wchodzi do gry.

Zamieniamy go w usługę

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


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

WantedBy=multi-user.target

Będziesz potrzebował:

  • ustawić swoją rzeczywistą nazwę użytkownika po User=
  • ustawić właściwą ścieżkę do swojego skryptu w ExecStart=

To wszystko. Możemy teraz uruchomić usługę:

$ systemctl start rot13

I automatycznie uruchomić ją przy starcie:

$ systemctl enable rot13

Dalej

Teraz, gdy twoja usługa (miejmy nadzieję) działa, ważne jest, aby zagłębić się nieco w opcje konfiguracyjne i upewnić się, że zawsze będzie działać tak, jak tego oczekujesz.

Start we właściwej kolejności

Możesz się zastanawiać, co robi dyrektywa After=. Oznacza ona po prostu, że twoja usługa musi zostać uruchomiona po tym, jak sieć będzie gotowa. Jeśli twój program oczekuje, że serwer MySQL będzie gotowy do pracy, powinieneś dodać:

After=mysqld.service

Restart przy wyjściu

Domyślnie systemd nie uruchamia ponownie twojej usługi, jeśli program kończy pracę z jakiegokolwiek powodu. To zazwyczaj nie jest to, czego chcesz dla usługi, która musi być zawsze dostępna, więc instruujemy ją, aby zawsze restartowała się przy wyjściu:

Restart=always

Możesz również użyć on-failure aby restartować tylko wtedy, gdy status wyjścia nie jest 0.

Domyślnie, systemd próbuje restartować system po 100ms. Możesz określić liczbę sekund, które należy odczekać przed próbą ponownego uruchomienia, używając:

RestartSec=1

Unikanie pułapki: limit startu

Ja osobiście wpadłem w tę pułapkę więcej niż raz. Domyślnie, gdy skonfigurujesz Restart=always tak jak my, systemd rezygnuje z ponownego uruchomienia twojej usługi, jeśli nie uda się jej uruchomić więcej niż 5 razy w odstępie 10 sekund. Na zawsze.

Istnieją dwie opcje konfiguracyjne odpowiedzialne za to:

StartLimitBurst=5
StartLimitIntervalSec=10

Dyrektywa RestartSec również ma wpływ na wynik: jeśli ustawisz ją na ponowne uruchomienie po 3 sekundach, wtedy nigdy nie możesz osiągnąć 5 nieudanych prób w ciągu 10 sekund.

Prostą poprawką, która zawsze działa, jest ustawienie StartLimitIntervalSec=0. W ten sposób systemd będzie próbował zrestartować twoją usługę na zawsze.

Dobrym pomysłem jest ustawienie RestartSec na co najmniej 1 sekundę, aby uniknąć zbyt dużego stresu na twoim serwerze, gdy rzeczy zaczynają iść źle.

Jako alternatywę możesz pozostawić ustawienia domyślne i poprosić systemd o ponowne uruchomienie serwera, jeśli limit startu zostanie osiągnięty, używając StartLimitAction=reboot.

Czy to naprawdę wszystko?

.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *