Wiele niemiłych rzeczy można napisać o systemd i w większości (nie)stety będą prawdą. Niestety również systemd zadomowił się w naszych dystrybucjach na dobre i jakoś trzeba z nim żyć. Przynajmniej serwisy w javie można teraz łatwo uruchamiać...

Prosta aplikacja

Dla przykładu najprostsza możliwa aplikacja springboot'owa:

curl https://start.spring.io/starter.tgz  -d dependencies=web,actuator -d language=java -d type=gradle-project -d baseDir=systemdtest | tar -xzvf -
cd systemdtest
./gradlew build

Jak wiadomo powstały program powinniśmy uruchomić przez:

java -jar build/libs/demo-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.5.RELEASE)

2019-05-28 21:15:10.526  INFO 18588 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on systemd with PID 18588 (/home/multipass/systemdtest/build/libs/demo-0.0.1-SNAPSHOT.jar started by multipass in /home/multipass/systemdtest)
2019-05-28 21:15:10.537  INFO 18588 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2019-05-28 21:15:13.680  INFO 18588 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-05-28 21:15:13.765  INFO 18588 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-05-28 21:15:13.769  INFO 18588 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.19]
2019-05-28 21:15:13.943  INFO 18588 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-05-28 21:15:13.943  INFO 18588 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3270 ms
2019-05-28 21:15:14.980  INFO 18588 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-05-28 21:15:15.519  INFO 18588 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2019-05-28 21:15:15.661  INFO 18588 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-05-28 21:15:15.669  INFO 18588 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 6.137 seconds (JVM running for 6.945)

A jak to zrobić w systemd?

systemd zarządza tzw jednostkami (ang units) czyli tym co tam sobie Leonard P. i spółka wymyślili jako standard reprezentacji zasobów systemowych. Jak to zwykle bywa temat jest rozległy a nas interesuje aktualnie tylko jego fragment, a mianowicie plik konfiguracji takiej jednostki.

plik konfiguracyjny

Minimalny działający plik konfiguracyjny:

[Unit]
Description=Przykładowa aplikacja springboot

[Service]
ExecStart=/usr/bin/java -jar /opt/systemdtest/build/libs/demo-0.0.1-SNAPSHOT.jar --server.port=9004
WorkingDirectory=/opt/systemdtest
User=webservices
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Po kolei od góry:

  1. Description - wiadomo opis (wyświetla się np. po wykonaniu komendy systemctl)
  2. ExecStart - komenda uruchamiająca proces (w naszym przypadku zwykłe wywołanie javy, uwaga dawniej np. systemd 215 wystarczyło samo java, ostatnie wersje wymagają bezwględnej ścieżki)
  3. WorkingDirectory - czyli również proste: katalog "bieżący" uruchomionego procesu
  4. User - użytkownik, który będzie uruchamiał nasz serwis (bo przecież nie chcemy tego odpalać na koncie root prawda?)
  5. SuccessExitStatus - lista kodów wyjściowych procesów, które oprócz std 0 uznajemy za "oczekiwane" w przypadku poprawnego zakończenia procesu. Tu wyjaśnienie skąd 143: otóż taki kod zwraca java jak ktoś wyśle SIGTERM do procesu (i proces w związku z tym zakończy działanie)
  6. WantedBy - czyli zależności. Po pierwsze want czyli, że sugerujemy zależność, ale jej nie wymuszamy (w przypadku gdybyśmy mieliRequiredBy= a zależność nie zostałaby spełniona, to by się program po prostu nie uruchomił). Po drugie multi-user.target: systemd zamienił stare dobrze znane run-levels na tzw (konfigurowalne) targets. multi-user oznacza, że powinniśmy mieć już praktycznie cały system gotowy (pozostałe serwisy, sieć, firewall, etc), z wyjątkiem środowiska graficznego

Instalacja

Instalacja sprowadza się do skopiowania pliku konfiguracyjnego w odpowiednie miejsce w systemie. Np w ubuntu jest to /etc/systemd/system/:

 sudo cp systemdtest.service /etc/systemd/system/

włączamy aby po starcie systemu się uruchamiało:

sudo systemctl enable systemdtest.service 
Created symlink /etc/systemd/system/multi-user.target.wants/systemdtest.service → /etc/systemd/system/systemdtest.service

Uruchamianie

Po raz pierwszy musimy uruchomić sami:

sudo systemctl start systemdtets.service

..sprawdzamy czy działa.

multipass@systemd:~/systemdtest$ journalctl -u systemdtest.service
-- Logs begin at Tue 2019-05-28 20:56:25 CEST, end at Tue 2019-05-28 21:41:37 CEST. --
May 28 21:35:55 systemd systemd[1]: /etc/systemd/system/systemdtest.service:5: Executable path is not absolute: java -jar /home/multipass/systemdtest/build/libs/demo-0.0.1-SNAPSHOT.ja
May 28 21:41:35 systemd systemd[1]: Started Przykładowa aplikacja springboot.
May 28 21:41:36 systemd java[18900]:   .   ____          _            __ _ _
May 28 21:41:36 systemd java[18900]:  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
May 28 21:41:36 systemd java[18900]: ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
May 28 21:41:36 systemd java[18900]:  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
May 28 21:41:36 systemd java[18900]:   '  |____| .__|_| |_|_| |_\__, | / / / /
May 28 21:41:36 systemd java[18900]:  =========|_|==============|___/=/_/_/_/
May 28 21:41:36 systemd java[18900]:  :: Spring Boot ::        (v2.1.5.RELEASE)
May 28 21:41:37 systemd java[18900]: 2019-05-28 21:41:37.133  INFO 18900 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on systemd with PID 
May 28 21:41:37 systemd java[18900]: 2019-05-28 21:41:37.143  INFO 18900 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to defaul
lines 1-12/12 (END)
multipass@systemd:~/systemdtest$ journalctl -u systemdtest.service -f
-- Logs begin at Tue 2019-05-28 20:56:25 CEST. --
May 28 21:41:37 systemd java[18900]: 2019-05-28 21:41:37.143  INFO 18900 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
May 28 21:41:40 systemd java[18900]: 2019-05-28 21:41:40.427  INFO 18900 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9004 (http)
May 28 21:41:40 systemd java[18900]: 2019-05-28 21:41:40.511  INFO 18900 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
May 28 21:41:40 systemd java[18900]: 2019-05-28 21:41:40.517  INFO 18900 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.19]
May 28 21:41:40 systemd java[18900]: 2019-05-28 21:41:40.689  INFO 18900 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
May 28 21:41:40 systemd java[18900]: 2019-05-28 21:41:40.690  INFO 18900 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3402 ms
May 28 21:41:41 systemd java[18900]: 2019-05-28 21:41:41.708  INFO 18900 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
May 28 21:41:42 systemd java[18900]: 2019-05-28 21:41:42.200  INFO 18900 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
May 28 21:41:42 systemd java[18900]: 2019-05-28 21:41:42.344  INFO 18900 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9004 (http) with context path ''
May 28 21:41:42 systemd java[18900]: 2019-05-28 21:41:42.350  INFO 18900 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 6.335 seconds (JVM running for 7.101)

volia! :)

Literatura