
Estou usando esta definição para um systemd
trabalho:
[Unit]
Description=Some job
[Service]
ExecStart=/usr/local/sbin/somejob
User=dlt
Type=forking
[Install]
WantedBy=multi-user.target
O script chamado é o seguinte (chamar uma rotina simples que escuta em um soquete tcpip e anexa a entrada a um arquivo):
#!/bin/sh
cd /home/user/tmp/testout
nohup java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar </dev/null >/dev/null &
Após systemctl start somejob
o processo aparecer como em execução, tendo init
como pai:
user@CANTANDO ~$ ps -u dlt eo pid,ppid,command
PID PPID COMMAND
8718 1 java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar
Após realizar systemctl stop somejob
o processo não aparece mais (e a porta é fechada).
Então tudo parece bem e elegante
Minha pergunta é: isso é umsolução aceitávelpara executar um daemon java com systemd
ou há ressalvas e, portanto, outras maneiras mais estáveis ou seguras de conseguir isso?
Responder1
Aqui estão algumas pequenas modificações:
- Como ele escuta em um soquete de rede, torne-o uma dependência do
network.target
. nohup
não é necessário, poissystemd
irá daemonizar o executável para você.- Acho que um script de shell separado seria um exagero, então apenas mescle-o no arquivo de serviço.
- O redirecionamento (
< /dev/null
e assim por diante) não é necessário, pois o systemd configura um contexto de E/S padrão apropriado. Na verdade, se você tomar o redirecionamentoforaO systemd registrará qualquer coisa enviada para a saída padrão pelo programa Java em seu diário, sem a necessidade de nenhum mecanismo de registro especial. - A execução assíncrona a partir do shell de chamada (
&
) não é necessária nem apropriada. - Há um padrão de comportamento específico exigido pelo
Type=forking
, e se ele não for seguido pelo daemon, as coisas dão errado. Então tenteType=simple
(ouType=notify
).
Portanto, o arquivo de serviço fica assim:
[Unit]
Description=Some job
After=network.target
[Service]
WorkingDirectory=/home/user/tmp/testout
SyslogIdentifier=SocketTest
ExecStart=/bin/sh -c "exec java -jar /home/user/programming/tests/java/core/SocketTest/SocketTest.jar"
User=dlt
Type=simple
[Install]
WantedBy=multi-user.target
Notas:
- Você não pode simplesmente usar
java
como nome do programa a ser executado. O systemd não procuraPATH
executáveis, e o nome do executável fornecidoExecStart
deve ser absoluto. Portanto, se você quiser pesquisar o caminho, precisará invocar por meio de um shell ou arquivo/usr/bin/env
. Nós escolhemos/bin/sh
aqui. - Porque este é
Type=simple
o shell que deveexec
Java, não executá-lo como um processo filho. systemd controla o serviço por meio do processo principal, e isso precisa ser Java, não um processo shell pai. - Como isso não invoca diretamente o executável Java, o systemd colocará o nome
sh
em seu diário como o nome do serviço. VerComo evitar que /usr/bin/env seja marcado nos logs do systemd como executávelpara saber mais sobre isso.
Até onde eu sei, não há nenhuma advertência especial sobre a execução de aplicativos Java com Systemd.