Se bem entendi, você deseja detectar quando a.out
está lendo dados da entrada padrão, e quando envia esses dados e também grava esses dados no mesmo arquivo de log, o stdout é redirecionado para simular a% localecho
para o terminal quando executado interativamente?
Então talvez uma solução (bash syntax) seja algo como:
mkfifo strace.fifo
{
while read -d, trace; do
if [[ $trace = *"read(0" ]]; then
IFS= read -rn1 answer <&3 || break
answer=${answer:-$'\n'}
printf %s "$answer" >&2
printf %s "$answer"
fi
done < strace.fifo 3< answers.txt |
strace -o strace.fifo -e read ./a.out
} > log 2>&1
A idéia é usar strace
(supondo que você esteja no Linux), rastrear as chamadas do sistema read
e sempre que houver um read
no descritor de arquivo 0, alimente um caractere por vez de answers.txt
.
Editar : se o programa usa stdio ou algo assim. O que é provável que aconteça quando a saída é redirecionada para um arquivo regular e não é mais um terminal é que todos os prompts que estão emitindo são armazenados em buffer e só serão liberados no final quando o programa sair.
Uma solução seria usar stdbuf
: replace ./a.out
with stdbuf -oL ./a.out
. Isso diria ao aplicativo (supondo que é um aplicativo dinamicamente vinculado e o buffer é devido ao stdio) para fazer o buffer de linha no stdout como se fosse um terminal. No entanto, o que ainda não é liberar stdout em stdio reads de stdin como faria normalmente se stdin / stdout fosse terminais. Assim, por exemplo, um prompt não terminado por um caractere de nova linha não seria exibido até que um caractere fflush
ou até que um caractere de nova linha seja escrito. Então, o melhor seria usar stdbuf -o0
para desativar completamente o buffer.
Se a.out
puder separar processos ou threads, adicione a opção -f
a strace
.
Essa abordagem não funcionará se o aplicativo usar select
ou poll
chamadas do sistema para verificar se há algo para ler no stdin antes de realmente fazer o read
. E / S sem bloqueio também podem nos fazer enviar dados muito rapidamente.
Como mencionado nos comentários. expect
é a ferramenta para simular a interação do usuário, ele usa um pseudo-terminal, para que você obtenha automaticamente o eco de entrada e não tenha o problema saída em buffer . Como uma alternativa para stdbuf
, você pode usar o script unbuffer
que vem com ele para agrupar a.out
em um pseudo-terminal. Nesse caso, você pode adicionar um pequeno atraso entre detectar uma leitura e enviar a resposta para permitir que expect
reproduza os prompts em sua stdout.