Como iniciar corretamente um programa e tornar possível redirecionar sua saída em execução (stdout e stderr) em um estágio posterior?

1

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

Eu procuro por algo direto (e seguro) que aproveite o fato de eu saber antecipadamente que eu ligarei e desligarei as saídas. Eu também postei uma resposta.

Abaixo da minha primeira tentativa. Vamos supor que eu trabalhe no número de shell 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, ele 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 muda como eu esperava. Não muda para o processo em execução. Se eu iniciar um novo programa da mesma maneira, o redirecionamento seguirá a nova prescrição do link.
Se eu começar de novo e definir o link para /dev/null , a saída será suprimida conforme o esperado, mas, novamente, quando eu alterar o link, o redirecionamento não será alterado. Se eu fizer um link para um link, recebo o mesmo resultado. O uso de hard link não altera a situação.

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

Existe alguma possibilidade de fazer o trabalho de maneira semelhante ou tenho que descobrir como comunicar ao processo (ou aos PPIDs) 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 inicia do ponto " Ops Eu lancei o programa e esqueci de redirecionar a saída. Agora eu quero fazer isso ", mas pelo contrário: "Como eu posso lançar um programa com o objetivo explícito de redirecionar a saída para outro lugar posteriormente?".

Eu pretendo usar esse procedimento quando não for possível (ou conveniente) modificar o código-fonte do programa.
Eu leia que é possível para disown do processo, use screen e transfira de uma tela para outra ... ou para 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 deles apresentam uma porcentagem de risco também.

    
por Hastur 12.05.2014 / 09:28

3 respostas

1

Eu acho uma solução via mkfifo , que cria um pipe nomeado, ou FIFOs .
Simples como criar um link simbólico e é possível usar todo o redirecionamento permitido no shell.

mkfifo MyOutput

ls -l

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

Eu 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 + c eu interrompo o fluxo mas não o processo em execução (eu tenho que usar algo como kill pid ou kill %1 para fazer isso ).
Quando, em uma segunda vez, eu pedir para o FIFOs fazer o dump no terminal (novamente com cat MyOutput ), ele começará a despejar a saída daquele momento.

Notas e avisos:

  • Até que eu não peça um despejo de FIFOs , ele armazenará toda a saída.
    Como eu vou perguntar pela primeira vez, ele irá liberar todos.
  • posso redirecionar (ou anexar) para outro arquivo cat MyOutput >> NewRealFile
  • Eu também posso usar cat MyOutput de outro terminal!
  • Warning : Se eu pedir a 2 programas (ou instâncias) diferentes para redirecionar a saída para o mesmo FIFOs , o fluxo será mesclado (sem a priori para distinguir de quais programas essa linha vem).
  • Aviso : Se eu perguntar 2 ou mais vezes (talvez de diferentes terminais), ele fornecerá uma linha para cada solicitação dividindo a saída para o solicitante. Talvez haja uma solução segura ...
por 12.05.2014 / 09:28
1

Se eu 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ê pode usar arquivos reais em vez de Fifos

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

depois, siga-os, eles serão substituídos quando você executar os scripts novamente.

Eu prefiro o segundo método, ou apenas usando um multiplexador (ou seja, tela ou o que nunca a reencarnação popular é esta semana)

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

então

screen -r

para "monitorar" e ctrl + a d para separar.

Não deixe de pausar no final do seu script se quiser ver a saída depois que ela for executada.

    
por 12.05.2014 / 10:53
0

se eu fosse você id apenas redirecionar a saída para um arquivo, então tailf que o arquivo quando eu queria ver a saída ... também você pode querer limitar o tamanho desse arquivo Se você acha que a saída será muito longa, ou se o arquivo foi escrito em RAM, em vez de no disco, se você acha que a saída será bem rápida, mas como fazer essas coisas é outra questão idk.

    
por 03.07.2017 / 17:42