Inicialização / encerramento do servidor Minecraft com o systemd

3

Estou executando um servidor Minecraft com um script init sysV. É um roteiro muito bom; Ele executa o Minecraft em uma "tela", ele pode garantir que o Minecraft nunca seja iniciado duas vezes e aguarda que o Minecraft seja desligado quando parado. Ele pode até mesmo passar um comando para o Minecraft com o comando "/etc/init.d/minecraft" - isso é útil para backups agendados.

Agora eu atualizei para o Debian Jessie, que possui o systemd. Mas por enquanto, eu mantenho meu script de estilo antigo porque é incrível. Ainda assim, eu realmente sou muito favorável ao systemd - realmente parece muita melhoria, simplificação e centralização. Eu me lembro de desenvolvedores do systemd prometendo que "velhos scripts sysV funcionarão como antes", mas acontece que não é tão fácil ...

Eu lembro de ter problemas com alguns scripts de inicialização antes; aparentemente, apenas colocar um script em /etc/init.d e marcá-lo como executável não é mais suficiente - eu tive que "ativá-los" para fazê-los funcionar. "Bem", pensei, "agora ele é reconhecido pelo systemd, e agora posso controlá-lo via systemctl - e provavelmente deve usar meu script antigo para processar os comandos!" E acontece que eu estava muito errada.

Ele não inicia corretamente, não para de forma adequada, não exibe o status corretamente, sem mencionar a ausência do comando "command". Comecei a procurar informações sobre como o systemd é melhor que o sysV e o que posso fazer para simplificar e capacitar tudo. Aparentemente, o systemctl apenas torna o arquivo de unidade mais simples possível, e espera que seja suficiente! Agora eu estou querendo saber se o systemd é realmente incapaz de lidar com tais situações complexas ...

Eu vejo que um serviço systemd médio consiste basicamente em alguns requisitos e ExecStart. Como se todo o systemd precisasse monitorar o daemon. Digite as condições e o nome do executável e o systemd tratará de iniciar, parar e quem sabe o que mais. Mas não é assim tão fácil !! Você não pode simplesmente matar o PID de Minecraft (para não mencionar que é diferente do PID da tela)! .. Eu quero escrever scripts mais complexos para cada ação, talvez até adicionar novas ações como "comando" (ok, eu já aceitei que provavelmente não é possível a todos). Para "status", ele precisa monitorar o processo Java e, para parar, ele precisa enviar um comando para o console do Minecraft e aguardar que o Java e a tela morram! .. E quero ter certeza de que o systemd não será apenas tente SIGHUP ou SIGINT ou SIGTERM!

Então, qual é a moderna, planejada "maneira sistêmica" de fazê-lo que realmente nos permite utilizar todas as "melhorias" e "simplificações" que o sistema nos oferece? Certamente, ele deve ser capaz de lidar com algo mais complexo do que um simples daemon de um processo iniciado em uma única linha e morto com um SIGINT? .. Devo talvez criar uma unidade systemd e especificar manualmente a chamada do meu script antigo em todos os comandos, como isso:

ExecStart=/etc/init.d/minecraft start
ExecReload=/etc/init.d/minecraft reload
(and how do I make the "stop" command and explain how to find the processes to watch for the "status" command?..)
Eu sou muito pró-inovação, pró-Poettering e pro-systemd a este respeito, e acredito que deveria haver uma maneira de fazer melhor do que era antes - talvez de uma maneira completamente diferente, como geralmente é com Poettering (que eu gosto sobre ele!). Mas isso não parece ser uma grande melhoria - mais como uma enorme regressão que precisa de uma enorme quantidade de kludges para continuar como antes. "SysV scripts continuarão funcionando", meu rabo de cavalo! Eu não posso nem mesmo ter certeza se ele chama meu script para parar Minecraft corretamente no desligamento do sistema, ou apenas olha para "statusctl status" e vê que ele já está "inativo (morto)".

Alguma idéia melhor? ..

    
por darkpenguin 11.08.2016 / 11:17

2 respostas

8

Após navegar pelas manpages mais algumas vezes (sim, a resposta nunca está lá pela primeira vez ...), eu encontrei uma solução ... que não funcionou. Depois de navegar ainda mais, finalmente encontrei a solução mais elegante possível.

[Unit]
Description=Minecraft server
After=local-fs.target network.target

[Service]
WorkingDirectory=/home/minecraft/minecraft_server
User=minecraft
Group=minecraft
Type=forking
# Run it as a non-root user in a specific directory

ExecStart=/usr/bin/screen -h 1024 -dmS minecraft ./minecraft_server.sh
# I like to keep my commandline to launch it in a separate file
# because sometimes I want to change it or launch it manually
# If it's in the WorkingDirectory, then we can use a relative path

# Send "stop" to the Minecraft server console
ExecStop=/usr/bin/screen -p 0 -S minecraft -X eval 'stuff \"stop\"5'
# Wait for the PID to die - otherwise it's killed after this command finishes!
ExecStop=/bin/bash -c "while ps -p $MAINPID > /dev/null; do /bin/sleep 1; done"
# Note that absolute paths for all executables are required!

[Install]
WantedBy=multi-user.target

Isso realmente parece melhor do que o meu roteiro original! No entanto, existem algumas regressões.

  • Se eu quiser passar comandos para o console do servidor, terei que criar um script separado para fazer isso.
  • Depois de executar systemctl start minecraft ou systemctl stop minecraft , verifique systemctl status minecraft , porque esses comandos não fornecem nenhuma saída, mesmo que eles realmente falhem. Esta é a única grande regressão comparada aos scripts - "sempre examine sua saída" é a regra # 1 em TI, mas o systemd não parece se importar com isso ...
  • Além disso, esperava que o systemd fosse capaz de gerenciar o encerramento do serviço sem a solução alternativa "aguarde o PID morrer". No antigo script de init, eu tive que fazer isso manualmente, porque era um script, e o systemd está tentando eliminar a necessidade de scripts complexos para as mesmas coisas; elimina a necessidade de script manualmente em todos os timeouts e matar quem não morreu, mas "esperar o pid morrer" é a coisa mais comum, e ainda precisamos fazer um script.
por 13.08.2016 / 11:10
0

Eu uso este arquivo de serviço:

[Unit]
Description=Minecraft server
Wants=network.target
After=network.target

[Service]
User=minecraft
Group=minecraft
Nice=5

WorkingDirectory=/home/minecraft/.minecraft/
KillMode=process
KillSignal=SIGINT
SuccessExitStatus=130

ExecStart=/usr/bin/java -Xms1G -Xmx1G -jar /home/minecraft/.minecraft/minecraft_server.jar nogui

[Install]
WantedBy=multi-user.target

Eu uso o SIGINT (ctrl + c) para pará-lo:

KillSignal=SIGINT

e SuccessExitStatus para finalização com sucesso:

SuccessExitStatus=130
    
por 07.01.2017 / 18:52