systemd i serwisy w javie
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:
Description
- wiadomo opis (wyświetla się np. po wykonaniu komendysystemctl
)ExecStart
- komenda uruchamiająca proces (w naszym przypadku zwykłe wywołanie javy, uwaga dawniej np.systemd 215
wystarczyło samojava
, ostatnie wersje wymagają bezwględnej ścieżki)WorkingDirectory
- czyli również proste: katalog "bieżący" uruchomionego procesuUser
- użytkownik, który będzie uruchamiał nasz serwis (bo przecież nie chcemy tego odpalać na koncieroot
prawda?)SuccessExitStatus
- lista kodów wyjściowych procesów, które oprócz std0
uznajemy za "oczekiwane" w przypadku poprawnego zakończenia procesu. Tu wyjaśnienie skąd 143: otóż taki kod zwraca java jak ktoś wyśleSIGTERM
do procesu (i proces w związku z tym zakończy działanie)WantedBy
- czyli zależności. Po pierwszewant
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 drugiemulti-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! :)