Detectando o final da saída TTY
-
21-09-2019 - |
Pergunta
Oi, estou escrevendo um psudo-terminal que pode viver em um TTY e gerar um segundo TTY que é a entrada e saída de filtros de
Estou escrevendo em Python por enquanto, gerando o segundo TTY e a leitura e a escrita é fácil
Mas quando li, a leitura não termina, aguarda mais informações.
import subprocess
pfd = subprocess.Popen(['/bin/sh'], shell=True,
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
cmd = "ls"
pfd.stdin.write(cmd + '\n')
out = ''
while 1:
c = pfd.stdout.read(1)
if not c: # if end of output (this never happends)
break
if c == '\n': # print line when found
print repr(out)
out = ''
else:
out += c
----------------------------- Saídas -------------------- ----
intty $ python intty.py
'intty.py'
'testA_blank'
'testB_blank'
(hangs here does not return)
Parece que está chegando ao final do buffer HTE e, em vez de retornar nenhum, ou '' está esperando por mais informações.
O que devo procurar para ver se a saída foi concluída? o fim do buffer? um personagem não impresso?
---------------- EDIT -------------
Isso acontece também quando eu corro XPCshell em vez de LS, estou assumindo que esses programas interativos tenham alguma maneira de saber exibir o prompt novamente, estranhamente o prompt, neste caso "js>" nunca aparece
Solução
Bem, sua saída na verdade não foi concluída. Porque você gerou /bin/sh
, o shell ainda está em execução após a conclusão do "LS". Não há indicador EOF, porque ainda está em execução.
Por que não simplesmente correr /bin/ls
?
Você poderia fazer algo como
pfd = subprocess.Popen(['ls'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
out, err_output = pfd.communicate()
Isso também destaca subprocess.communicate
, que é uma maneira mais segura de obter saída (para saídas que se encaixam na memória, de qualquer maneira) a partir de uma única execução de programa. Isso retornará apenas quando o programa terminar de executar.
Como alternativa, você pode ler linha -linhas do shell, mas estaria procurando uma sequência de concha especial como a sh~#
linha que poderia aparecer facilmente na saída do programa. Assim, executar uma concha é provavelmente uma má idéia por toda parte.
Editar Aqui está o que eu estava me referindo, mas ainda não é realmente a melhor solução, pois tem muitas advertências:
while 1:
c = pfd.stdout.read(1)
if not c:
break
elif c == '\n': # print line when found
print repr(out)
out = ''
else:
out += c
if out.strip() == 'sh#':
break
Observe que isso será dividido se algum outro comando produzir 'sh#' no início da linha e também se, por algum motivo, a saída for diferente do esperado, você entrará na mesma situação de bloqueio que antes. É por isso que é uma situação muito abaixo do ideal para uma concha.
Outras dicas
Para aplicações como um shell, a saída não terminará até que o shell termine. Use select.select()
Para verificar se ele tem mais saída esperando por você ou encerre o processo.