Como iniciar corretamente um programa e possibilitar o redirecionamento de sua saída em execução (stdout e stderr) posteriormente?

Como iniciar corretamente um programa e possibilitar o redirecionamento de sua saída em execução (stdout e stderr) posteriormente?

O problema é bastante simples: considero útil ter a possibilidade deligar (e desligar)a saída de algum programa em execução em cada momento que preciso. Para ser mais preciso, quero estar livre para redirecionar sua saída padrão (e erro) do shell atual para outro, para /dev/nullum arquivo ou de volta ao shell original.

Procuro algo direto (e seguro) que aproveite o fato de saberantecipadamenteque vou ligar e desligar as saídas. Eu posto uma resposta também.


Abaixo minha primeira tentativa. Suponhamos que eu trabalhe no shell número 35.

$ who am I                     # the command line to ask where am I
myuser  pts/35  ...            # The answer 

Minha tentativa começa com um link simbólico para esse terminal

ln -s /dev/pts/35  MyOutput  # The command to link

A ideia é lançar o programa com o redirecionamento definido para esse link

./Execute_program > MyOutput

Funciona, redireciona a saída para o meu terminal, mas quando dou o comando para alterar o link,

ln -sf  /dev/null  MyOutput

o link muda,mas o redirecionamento não mudacomo eu esperava. Isso não muda para o processo em execução. Se eu lançar um novo programa da mesma forma, o redirecionamento segue a nova prescrição do link.
Se eu começar de novo e definir o link para /dev/nulla saída será suprimida conforme o esperado, mas novamente quando eu alterar o link o redirecionamento não muda.
Se eu fizer um link para um link, obtenho o mesmo resultado. O uso de hard linknão muda a situação.

Tristementeo shell expande a linha de comando no momento da inicialização.

Existe alguma possibilidade de fazer o trabalho de forma semelhante ou devo descobrir como comunicar ao processo (ou aos PPID) que o link foi alterado?


Notas:

Esta é uma questão da série "Como redirecionar a saída de um processo em execução?", mas não parte do ponto"Ops, lancei o programa e esqueci de redirecionar a saída. Agora quero fazer isso", mas do contrário: "Como posso lançar um programa com o objetivo explícito de redirecionar a saída para outro lugar posteriormente?".

Pretendo utilizar tal procedimento quando não for possível (ou conveniente) modificar o código fonte do programa.
EUlerque é possível disownprocessar, usar screene transferir de uma tela para outra... ou usar um depurador, para interceptar o processo... Todas essas soluções poderiam funcionar com uma boa quantidade de experiência e esforço, mas algumas delas também apresentam uma percentagem de risco.

Responder1

Eu encontro uma solução via mkfifo, que cria um pipe nomeado, ouFIFOs.
Simples como criar um link simbólico e é possível utilizar todos os redirecionamentos permitidos pelo shell.

mkfifo MyOutput

ls -l

0 prw-r--r-- 1 My_username My_username  0 May 11 17:45 MyOut|

Posso iniciar o programa com redirecionamento para esse link

./Execute_program > MyOutput  &  cat MyOutput 

e a saída começa a fluir no terminal.

Se eu pressionar ctrl+ cinterrompo o fluxo, mas não o processo em execução (tenho que usar algo parecido kill pidou kill %1fazer).
Quando numa segunda vez eu pedir aoFIFOspara despejar no terminal (novamente com cat MyOutput) ele começará a despejar a saída a partir desse momento.

Notas e avisos:

  • Até que eu peça um despejo, FIFOsele conterá toda a saída.
    Como vou perguntar da primeira vez, serádescarregartodos.
  • Posso redirecionar (ou anexar) para outro arquivocat MyOutput >> NewRealFile
  • Posso usar cat MyOutputde outro terminal também!
  • Aviso: Se eu pedir a 2 programas (ou instâncias) diferentes para redirecionar a saída para o mesmo, FIFOso fluxo será mesclado (sema priorimaneira de distinguir de quais programas essa linha vem).
  • Aviso: Se eu perguntar 2 ou mais vezes (talvez de terminais diferentes), ele fornecerá uma linha para cada solicitação, dividindo a saída para o solicitante. Talvez haja uma solução alternativa segura ...

Responder2

Se entendi sua pergunta corretamente:

script 1>>~/out.fifo 2>>~/error.fifo 

então para monitorar você pode fazer algo como:

watch cat ~/out.fifo

Você poderia usar arquivos reais em vez de Fifos

script 1>/tmp/$0-out 2>/tmp/$0-error

então tail -f eles, eles serão substituídos quando você executar os scripts novamente.

Eu prefiro o segundo método, ou apenas usar um multiplexador (ou seja, tela ou qualquer que seja a reencarnação popular desta semana)

screen -t "name" bash -c 'script'

então

screen -r

para "monitorar" e ctrl+ad para desanexar.

Certifique-se de fazer uma pausa no final do seu script se quiser ver a saída após sua execução.

Responder3

se eu fosse você, apenas redirecionaria a saída para um arquivo e, em seguida, seguiria esse arquivo quando quisesse ver a saída ... também você pode querer limitar o tamanho desse arquivo se achar que a saída será bastante longa, ou tenha o arquivo escrito na memória RAM em vez de no disco se você acha que a saída será bastante rápida, mas como fazer essas coisas é outra questão, não sei.

informação relacionada