Diferença entre o systemd e o programa de partida do terminal

9

Estou curioso para saber qual é essa diferença entre os programas que são; iniciado com systemd quando ativado por systemctl, vs iniciado por meio da /etc/rc.localCLI ou por meio dela .

Por exemplo, recentemente usei o shairport-sync para o raspberry pi. Inicialmente, configurei o shairport-sync para iniciar por meio do sudo systemctl ativado pelo shairport-sync.

Posteriormente, usei uma funcionalidade shairport-syncpara executar scripts antes e publicar nos dispositivos conectados.

Para minha surpresa, os scripts quando executado por shairport-syncnão kill arecordouaplay

No entanto, quando eu rodava o script via terminal, o script era executado e morto arecorde aplay.

Para me confundir ainda mais, matei shairport-synce o iniciei via terminal para ver a saída do que estava acontecendo. Quando eu fiz isso, os scripts funcionaram como eu esperava quando o dispositivo se conectou e matou arecorde aplay. Assim, como uma correção I desativada shairport-syncem sysmtectle configurá-lo para ser executado no /etc/rc.localcomo uma solução rápida. Depois de um rebootfuncionou como eu esperava.

Isso me leva a acreditar que há alguma diferença entre um programa executado separadamente systemde um programa que é executado quando iniciado via /etc/rc.localou pela CLI.

Por que isso acontece? Isso é devido a diferentes níveis de execução? Alguma magia negra?

O script que é executado quando um dispositivo se conecta shairport-syncé o seguinte:shairportstart.sh

#!/bin/sh
/usr/bin/sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0

Aqui está o script fade: shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0

O script que é executado quando um dispositivo é desconectado shairport-syncé o seguinte:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0

Eu encontrei o seguinte erro no /var/log/syslogsomente quando o shairport-sync foi executado inicialmente como separado de systemd. Quando shairport-syncfoi executado a partir da CLI ou /etc/rc.localnão houve erros presentes.

Jan 24 00:38:45 raspberrypi shairport-sync[617]: sudo: no tty present and no askpass program specified

Observe que a única diferença é como shairport-syncé iniciado inicialmente, quando os dispositivos se conectam ou desconectam shairport-sync.

Brett Reinhard
fonte
1
Esse ps ... awk ... grep ...material pode ser substituído por um mais simplespkill
thrig
@thrig originalmente a linha era muito mais simples, mas como não funcionou, pensei em tentar usar outros métodos para matar a instância que ainda não funcionava. Matar o processo não era o problema per se, uma vez que funcionou, mas apenas quando executado a partir de um login do usuário
Brett Reinhard
você pode mostrar a lista de /home/pi/shScripts/shairportfade.sh?
Michael D.
@MichaelD. eu adicionei o script de fade, bem como o script que é executado quando um dispositivo desconecta a shairport-sync
Brett Reinhard
@BrettReinhard, qual é o problema com a execução do script?rc.local
Michael D.

Respostas:

18

Variações de "Por que as coisas se comportam de maneira diferente no systemd?" são uma pergunta freqüente.

Sempre que algo é executado a partir da CLI e não do systemd, existem algumas categorias amplas de possibilidades para explicar as diferenças.

  1. Variáveis ​​de ambiente diferentes . systemddocumenta as variáveis ​​de ambiente que ele transmite na man systemd.execseção Variáveis ​​de ambiente em processos gerados . Se você quiser inspecionar a diferença você mesmo, poderá usar systemd-run /path/to/binary, ele executará seu aplicativo em um escopo transitório, como seria executado por um serviço systemd. Você terá uma saída como: Running as unit: run-u160.service. Você pode então journalctl -u run-u160.servicerevisar a saída. Modifique seu aplicativo para despejar as variáveis ​​de ambiente que recebe e comparar a execução da CLI com a do systemd. Se o aplicativo não for convenientemente modificado, você poderá usar apenas systemd-run envpara ver as variáveis ​​de ambiente que seriam passadas e revisar o log de diário resultante para ele. Se você estiver tentando iniciar um aplicativo X11 GUI, a DISPLAYvariável de ambiente precisará ser configurada. Nesse caso, considere usar o recurso "inicialização automática" do seu ambiente de área de trabalho em vez de systemd.
  2. Restrições de recursos . Consulte man systemd.resource-controlos valores de configuração que podem restringir o consumo de recursos. Use systemctl show your-unit-unit.servicepara verificar os valores de configuração completos que afetam o serviço que você está tentando iniciar.
  3. Shell não interativo . Seu bashambiente CLI é um shell de logon interativo . Ele forneceu arquivos como .bashrcesse systemdnão. Além de definir variáveis ​​de ambiente, esses scripts podem fazer várias outras coisas, como conectar um agente SSH para que as ações SSH não exijam um login. Veja também Diferença entre o Shell de Login e o Shell Não-Login?
  4. Não TTY . Sua sessão interativa está conectada a um TTY que alguns programas gostam sudoe sshesperam ao solicitar senhas. Veja também sudo: no tty presente e nenhum programa askpass especificado
  5. Caminhos relativos vs. absolutos . Trabalho binário relativo no shell, mas conforme documentadoman systemd.service , o primeiro argumento a ExecStart=ser um caminho absoluto para um binário.
  6. Sintaxe de linha de comando restrita . As CLIs do shell suportam muitos metacaracteres, enquanto systemdpossuem uma sintaxe de linha de comando muito restrita . Dependendo das suas necessidades, você poderá replicar a sintaxe do Shell systemdexecutando explicitamente seu comando através de um shell:ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

É um recurso que o sistema executa seu código em um ambiente consistente com controles de recursos. Isso ajuda a obter resultados estáveis ​​e reproduzíveis a longo prazo, sem sobrecarregar o hardware.

Mark Stosberg
fonte
Também precisa levar em conta o contexto MAC (SELinux, ...), capacidades, namespaces ...
Bigon
2
@BrettReinhard Não chame sudoum shell script para rodar melhor sudo shairportstart.shno terminal, já que systemd está executando o script como root, não há necessidade de sudo como root.
Michael D.
1
Resolvi meu problema de várias maneiras, na tentativa de entender o que estava acontecendo. Por fim, o que acabei fazendo foi mudar meu comando de matar para /usr/bin/echo "mypassword" | /usr/bin/sudo /bin/pkill arecord. Mais tarde, hoje, tentarei remover os comandos sudoe echodo meu comando kill e ver se isso produz os mesmos resultados. Meu palpite é que funcionará, pois parece que o erro foi causado por nenhuma senha ser enviada com o sudocomando. Obrigado pela ajuda na compreensão de por que há uma diferença entre systemdeo CLI
Brett Reinhard
1
Uma outra diferença, que pode ser óbvia, mas que me incomodou hoje, é que o systemd tenta rastrear o status de um serviço e não o inicia se achar que já está ativo; portanto, pode nem mesmo iniciar um script init.d se acha que o serviço está sendo executado. Por outro lado, os scripts init.d geralmente são escritos para sempre verificar e tentar iniciar o serviço conforme apropriado.
Josh Kelley
1
@ JoshKelley Obrigado pela dica. Essa não é uma diferença entre o systemd e a CLI, mas entre os scripts systemd e sysVinit init.d.
Mark Stosberg