Como não fazer nada para sempre de uma forma elegante?

Como não fazer nada para sempre de uma forma elegante?

Eu tenho um programa que produz informações úteis, stdoutmas também lê stdin. Quero redirecionar sua saída padrão para um arquivo sem fornecer nada na entrada padrão. Até agora, tudo bem: eu posso fazer:

program > output

e não faça nada no tty.

No entanto, o problema é que quero fazer isso em segundo plano. Se eu fizer:

program > output &

o programa será suspenso ("suspenso (entrada tty)").

Se eu fizer:

program < /dev/null > output &

o programa termina imediatamente porque atinge EOF.

Parece que o que eu preciso é entrar em programalgo que não faz nada por um período indefinido de tempo e não lê stdin. As seguintes abordagens funcionam:

while true; do sleep 100; done | program > output &
mkfifo fifo && cat fifo | program > output &
tail -f /dev/null | program > output &

Porém, tudo isso é muito feio. Látemser uma maneira elegante, usando utilitários Unix padrão, de "não fazer nada, indefinidamente" (parafraseando man true). Como eu poderia conseguir isso? (Meus principais critérios de elegância aqui: sem arquivos temporários; sem espera ocupada ou ativações periódicas; sem utilitários exóticos; o mais curto possível.)

Responder1

Eu não acho que você vai ficar mais elegante do que o

tail -f /dev/null

que você já sugeriu (supondo que isso use o inotify internamente, não deve haver pesquisas ou ativações; portanto, além de ter uma aparência estranha, deve ser suficiente).

Você precisa de um utilitário que será executado indefinidamente, manterá seu stdout aberto, mas na verdade não gravará nada no stdout e não sairá quando seu stdin for fechado. Algo como yesrealmente grava no stdout. catsairá quando seu stdin for fechado (ou o que quer que você redirecione para ele estiver concluído). Acho sleep 1000000000dque pode funcionar, mas tailé claramente melhor. Minha caixa Debian tem um tailfcomando que encurta um pouco.

Tomando uma abordagem diferente, que tal executar o programa em screen?

Responder2

sleep infinityé a solução mais clara que conheço.

Você pode usar infinityporque sleepaceita um número de ponto flutuante*, que pode serdecimal,hexadecimal,infinidade, ouNaN, de acordo com man strtod.

* Isso não faz parte do padrão POSIX, portanto não é tão portátil quanto o tail -f /dev/null. No entanto, é suportado em GNU coreutils (Linux) e BSD (usado no Mac) (aparentemente não suportado em versões mais recentes do Mac - veja os comentários).

Responder3

sleep 2147483647 | program > output &

Sim, 2^31-1é um número finito e não funcionapara sempre, mas eu lhe darei US$ 1.000 quando o sono finalmente acabar. (Dica: um de nós estará morto até lá.)

  • sem arquivos temporários; verificar.
  • sem espera ocupada ou despertares periódicos; verificar
  • sem utilidades exóticas; verificar.
  • o mais curto possível. Ok, poderia ser mais curto.

Responder4

Você pode criar um binário que faça exatamente isso com:

$ echo 'main(){pause();}'| gcc -Wno-all -xc - -o pause

Acho isso elegante porque a pausechamada do sistema é literalmente a única chamada do sistema cujo único propósito é não fazer nada para sempre (ou até que um sinal interrompa o processo) sem esperar ocupado, fazendo isso como um efeito colateral de outra coisa ou sem informar o processo pai (os pais podem elegantemente não bloquear waitpidseus filhos para serem interrompidos pelo sinal, e muitos (principalmente os shells) o fazem, embora seja um pouco mais difícil esperar que um filho seja bloqueado em uma chamada de sistema sem aumento de sinal) .

informação relacionada