Enganar um aplicativo para pensar que seu stdout é um terminal, não um pipe

Eu estou tentando fazer o oposto

Detectar se stdin é um terminal ou tubo?

Estou executando um aplicativo que está alterando seu formato de saída porque ele detecta um canal no stdout e quero que ele seja um terminal interativo para que eu obtenha a mesma saída ao redirect.

Eu estava pensando que envolvê-lo em um script de expect ou usando um proc_open() em PHP faria isso, mas isso não acontece.

Alguma idéia por aí?

Ah!

O comando de script faz o que queremos …

 script --return -c "[executable string]" /dev/null 

Faz o truque!

Com base na solução de Chris , eu criei a seguinte pequena function auxiliar:

 faketty() { script -qfc "$(printf "%q " "$@")" /dev/null } 

O printf aparência peculiar é necessário para expandir corretamente os argumentos do script em $@ , protegendo partes possivelmente citadas do comando (veja o exemplo abaixo).

Uso:

 faketty   

Exemplo:

 $ python -c "import sys; print sys.stdout.isatty()" True $ python -c "import sys; print sys.stdout.isatty()" | cat False $ faketty python -c "import sys; print sys.stdout.isatty()" | cat True 

O script unbuffer que vem com o Expect deve lidar com isso ok. Se não, o aplicativo pode estar olhando para algo diferente do que sua saída está conectada, por exemplo. o que a variável de ambiente TERM está configurada.

Referindo-se a resposta anterior, no Mac OS X, “script” pode ser usado como abaixo …

 script -q /dev/null commands... 

Mas, como ele pode alterar o código de retorno de “\ n” para “\ r \ n”, eu precisava rodar assim.

 script -q /dev/null commands... | perl -pe 's/\r\n/\n/g' 

Se houver algum canal entre esses comandos, você precisará liberar o stdout. por exemplo:

 script -q /dev/null commands... | ruby -ne 'print "....\n";STDOUT.flush' | perl -pe 's/\r\n/\n/g' 

Anywhere Python está instalado,

 echo fakepassword | python -c 'import pty, sys; pty.spawn(sys.argv[1:])' ssh 

Eu não sei se é factível a partir do PHP, mas se você realmente precisa do processo filho para ver um TTY, você pode criar um PTY .

Em C:

 #include  #include  #include  #include  #include  int main(int argc, char **argv) { int master; struct winsize win = { .ws_col = 80, .ws_row = 24, .ws_xpixel = 480, .ws_ypixel = 192, }; pid_t child; if (argc < 2) { printf("Usage: %s cmd [args...]\n", argv[0]); exit(EX_USAGE); } child = forkpty(&master, NULL, NULL, &win); if (child == -1) { perror("forkpty failed"); exit(EX_OSERR); } if (child == 0) { execvp(argv[1], argv + 1); perror("exec failed"); exit(EX_OSERR); } /* now the child is attached to a real pseudo-TTY instead of a pipe, * while the parent can use "master" much like a normal pipe */ } 

Eu estava realmente sob a impressão de que a expect si cria um PTY, no entanto.

Demasiado novo para comentar a resposta específica, mas pensei em acompanhar a function postada pela ingomueller-net acima, uma vez que recentemente me ajudou.

Descobri que isso estava criando um arquivo de texto typescript que eu não queria / precisava, então adicionei / dev / null como o arquivo de destino do script:

function faketty { script -qfc "$(printf "%q " "$@")" /dev/null ; }

Há também um programa pty incluído no código de exemplo do livro “Programação Avançada no Ambiente UNIX, Segunda Edição”!

Veja como compilar o Pty no Mac OS X:

http://codesnippets.joyent.com/posts/show/8786