Como faço para criar um script de shell que envia a saída para um processo

11

Atualmente, estou executando um programa de console do servidor em uma tela porque preciso lê-lo e enviar ocasionalmente comandos.

Gostaria de executar o aplicativo como um daemon em segundo plano (inicie / pare com init).

Eu poderia tail -ffazer o log, mas isso não me deixará enviar informações para o processo.

Existe alguma maneira de configurar isso para que eu possa ler e enviar entradas, mas ainda assim executá-las em segundo plano?

Também gostaria de poder enviar entrada para o daemon de diferentes processos (um script de shell que poderia enviar um comando "Stop \ n", por exemplo).

Bill K
fonte
Apenas um comentário para quem vem ler isso - a resposta aqui é fantástica. Se você não conhece os pipes nomeados, recomendo que você os experimente. Usando isso, eu poderia executar o Minecraft como um serviço e interagir com o console a partir de outros scripts, escrevendo no canal nomeado - para que seja possível escrever scripts para parar o servidor, enviar mensagens aos usuários, etc. enquanto ainda analisa o log de saída procurar linhas-chave (como enviar mensagens de bate-papo endereçadas a um usuário como textos) #
K Bill Bill

Respostas:

9

Leia de um pipe, grave em um arquivo

Se você deseja que o daemon leia as entradas produzidas por algum processo arbitrário, é necessário conectar esse processo a um canal. Aqui, o processo arbitrário é você ecoando comandos, e será executado em um contexto diferente. Portanto, crie um pipe nomeado (geralmente chamado de fifo em contextos unix).

mkfifo /var/run/daemon.fifo
</var/run/daemon.fifo /path/to/daemond --option >daemon.log

E basta escrever comandos no canal:

echo 'FORWARD 10' >/var/run/daemon.fifo
echo 'LEFT 72' >/var/run/daemon.fifo

No entanto, é improvável que funcione como está: existe uma boa chance de o daemon sair quando vê um final de arquivo em sua entrada padrão, o que acontece assim que o primeiro processo que grava no canal termina. Você pode usar tail -fpara evitar esse problema.

</var/run/daemon.fifo tail -c +1 -f | {
  echo $$ >/var/run/daemon.pid
  exec /path/to/daemond --option >daemon.log
}

Em algumas tailimplementações, você pode ser mordido pelo buffer: o tailprocesso aguardará até que acumule bytes suficientes para emitir alguma saída. Eu não acho que isso possa ser solucionado na caixa de ferramentas POSIX; se isso for um problema, use um programa trivial C, Perl ou Python. Até onde eu sei, o tailcoreutils do GNU (como encontrado no Linux e em outros lugares) é seguro a esse respeito.

Quando você para o daemon, echo >/var/run/daemon.fifomata o tailprocesso.


Iniciando o programa dentro da tela

Em vez de chamar o daemon diretamente do seu gerente de serviço (você realmente está usando apenas o SysV init ou algo adicional como scripts de wrapper ou Upstart?), Chame

screen -c daemon.screenrc -L -d -m -S daemon_name /path/to/daemond --option

Como o daemon não será um processo filho do gerenciador de serviços, você deve enviar um sinal para o processo correto. Como fazer isso depende exatamente de como o daemon é iniciado e por quê.

É tecnicamente possível anexar um processo em execução a um terminal, mas há o risco de você travar o programa, portanto, isso definitivamente está fora do sistema de produção.

A -Lopção faz com que a tela grave tudo o que aparece em sua janela em um arquivo. O nome do arquivo é fornecido daemon.screenrccom a logfilediretiva.

Gilles 'SO- parar de ser mau'
fonte
Na verdade, eu realmente gostaria de poder enviar mensagens para o stdin a partir de um script - talvez seja essa a pergunta que eu deveria ter feito. Atualmente eu só estou executando o servidor a partir de um roteiro e sou capaz de digitar, em um terminal, mas ele só parece que deve ser executado como um serviço ...
Bill K
@ Bill: Ok, entendo. Então a primeira coisa que me vem à cabeça é um cachimbo nomeado.
Gilles 'SO- stop be evil'
Eu acho que é exatamente isso que eu quero @Gilles! Eu preciso entender melhor ainda. Passarei algum tempo examinando as páginas de manual para descobrir - honestamente, recebo muito pouco disso (recebo quase tudo o que você está fazendo e quase nada como você fez - e pensei que meio que tinha um minha teoria não era conectar-se diretamente ao processo, mas criar outro script que associasse sua entrada / saída aos daimons / para fazer parecer que o console original está sendo executado, mas com a capacidade para fazer o eco 'FORWARD 10' de outro script ao mesmo tempo.
Bill K
Eu acho que entendi muito. Se eu dividi-lo, agora entendo "mkfifo pipe" e "tail -f pipe | command> output", testei esses e eles funcionam. Eu acho que a maioria das outras coisas que você tinha eram truques para executá-lo em uma linha - estou perdendo algo crítico?
Bill K
@ Bill: Você pode escrever para o terminal dentro da tela a partir do exterior (usando o stuffcomando da tela ). Mas você não precisa da sobrecarga (processamento, mas, principalmente, cognitiva) de um terminal aqui; um canal é quase o suficiente (basta com um pequeno processo de retransmissão para ignorar o final do arquivo). Você pode experimentar um pouco com <fifo catou <fifo tail -f | catem um terminal e echo >fifo; echo >fifoem outro terminal; Eu acho que você vai ficar bem.
Gilles 'SO- stop be evil'