Por exemplo, o seguinte funciona bem:
/usr/bin/program
Produz alguma saída e chega ao resultado.
Mas se eu invoco assim:
echo -n | /usr/bin/program
ou isto
echo -n | bash -c "/usr/bin/program"
ou até mesmo isso:
echo -n | bash -c "wc -c; /usr/bin/program"
Produz algumas linhas de saída e falha. Eu não tenho acesso a fonte do programa, então não posso nem olhar o que poderia causar esse comportamento.
E quando tento invocá-lo a partir do script python, recebo o mesmo material:
echo | python -c 'from subprocess import call; call("/usr/bin/program", shell=True)'
(a versão sem "echo" funciona antes)
Eu nem tenho a menor idéia de por que isso poderia estar acontecendo. O Stdin será aberto mesmo que eu não especifique explicitamente de onde o programa deve ler, então essa não deve ser a causa.
Existe alguma maneira de contornar esse problema?
EDITAR:
As últimas quatro linhas de strace
output - as únicas que diferem:
# without echo
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
...
# with echo
select(1, [0], NULL, NULL, {0, 0}) = 1 (in [0], left {0, 0})
write(4, "sleep 20 | /usr/bin/program
/usr/bin/program
echo -n | /usr/bin/program
jecho -n | bash -c "/usr/bin/program"
echo -n | bash -c "wc -c; /usr/bin/program"
echo | python -c 'from subprocess import call; call("/usr/bin/program", shell=True)'
# without echo
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
...
# with echo
select(1, [0], NULL, NULL, {0, 0}) = 1 (in [0], left {0, 0})
write(4, "sleep 20 | /usr/bin/program
%pre%%pre%j%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%7777", 20) = 20
write(3, "%pre%%pre%%pre%j%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%7777", 20) = 20
exit_group(1) = ?
%pre%%pre%%pre%%pre%%pre%%pre%7777", 20) = 20
write(3, "%pre%%pre%%pre%j%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%7777", 20) = 20
exit_group(1) = ?
SOLUÇÃO PARCIAL:
%pre%
Parece que program
espera que algo aconteça no stdin e sai se encontrar uma nova linha ou EOF (podemos ver isso de select
call na saída strace - ele atinge o tempo limite se a entrada vier do usuário "real") . Então, precisávamos de um programa que não escrevesse nada para stdin, mantendo-o aberto - sleep
faz o trabalho.