Tanto quanto eu entendo, se eu digitar o seguinte ...
python -i
... o interpretador python agora lerá a partir de stdin, comportando-se (obviamente) assim:
>>> print "Hello"
Hello
Eu esperaria que ele fizesse a mesma coisa se eu fizer isso:
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
Mas esta é a saída (sendo uma linha vazia real):
>>> print "Hello"
<empyline>
Parece-me que apenas peguei print "Hello"\n
e escrevi stdout
, mas não o interpretei. Por que isso não está funcionando e o que eu teria que fazer para fazê-lo funcionar?
proc
file-descriptors
Sheppy
fonte
fonte
Respostas:
O envio de informações para shells / intérpretes dessa maneira é muito suscetível a problemas e muito difícil de ser trabalhado de maneira confiável.
A maneira correta é usar soquetes; é por isso que eles foram inventados; você pode fazer isso na linha de comando usando
ncat
nc
ousocat
para vincular um processo python a um soquete simples. Ou escreva um aplicativo python simples que se ligue à porta e ouça os comandos para interpretar em um soquete.soquetes podem ser locais e não expostos a nenhuma interface da web.
O problema é que, se você iniciar a
python
partir da linha de comando, ela normalmente está conectada ao seu shell, conectada a um terminal, na verdade, podemos verportanto, quando você escreve para
stdin
python, na verdade você está gravando nopty
psuedo-terminal, que é um dispositivo de kernel, não um arquivo simples. Eleioctl
não usaread
ewrite
, portanto, você verá a saída na tela, mas não será enviada para o processo gerado (python
)Uma maneira de replicar o que você está tentando é com um
fifo
ounamed pipe
.Você também pode usar
screen
apenas para entradafonte
sleep 300 > python_i.pipe &
), o outro lado não fechará epython
continuará a aceitar comandos no tubo. Não há EOF como tal enviado porecho
.|
tubos, no entanto, correto?echo something > fifo
faria com que EOF parasse muitos aplicativos. Asleep infinity > fifo
solução alternativa não passou pelo meu meio, obrigado!python -i <> fifo
o que também irá impedir que o EOFO acesso não acessa o descritor de arquivo 0 do processo PID , ele acessa o arquivo que o PID abriu no descritor de arquivo 0. Essa é uma distinção sutil, mas é importante. Um descritor de arquivo é uma conexão que um processo possui com um arquivo. A gravação em um descritor de arquivo grava no arquivo, independentemente de como o arquivo foi aberto.
/proc/PID/fd/0
Se for um arquivo regular, a gravação nele modifica o arquivo. Os dados não são necessariamente o que o processo lerá a seguir: depende da posição anexada ao descritor de arquivo que o processo está usando para ler o arquivo. Quando um processo é aberto , ele obtém o mesmo arquivo que o outro processo, mas as posições do arquivo são independentes.
/proc/PID/fd/0
/proc/PID/fd/0
Se for um tubo, a gravação nele anexa os dados ao buffer do tubo. Nesse caso, o processo que está lendo no canal lerá os dados.
/proc/PID/fd/0
Se for um terminal, a gravação nele gera os dados em um terminal. Um arquivo de terminal é bidirecional: a gravação nele gera os dados, ou seja, o terminal exibe o texto; a leitura de um terminal insere os dados, ou seja, o terminal transmite a entrada do usuário.
/proc/PID/fd/0
Python está lendo e gravando no terminal. Quando você corre
echo 'print "Hello"' > /proc/$(pidof python)/fd/0
, está escrevendoprint "Hello"
no terminal. O terminal é exibidoprint "Hello"
conforme as instruções. O processo python não vê nada, ainda está aguardando entrada.Se você deseja alimentar a entrada do processo Python, você precisa obter o terminal para fazer isso. Veja a resposta de crasic para saber como fazer isso.
fonte
Com base no que Gilles disse , se quisermos escrever no stdin de um processo que está anexado a um terminal, precisamos enviar as informações ao terminal. No entanto, como um terminal serve como uma forma de entrada e saída, ao gravá-lo, o terminal não tem como saber que você deseja gravar em um processo em execução nele e não na "tela".
No entanto, o Linux possui uma maneira não-posix de simular a entrada do usuário por meio de uma solicitação ioctl chamada
TIOCSTI
(Controle de E / S do Terminal - Entrada de Simulação de Terminal) que nos permite enviar caracteres para um terminal como se tivessem sido digitados por um usuário.Estou apenas superficialmente ciente de como isso funciona, mas com base nessa resposta, deve ser possível fazer isso com algo parecido com
Alguns recursos externos:
http://man7.org/linux/man-pages/man2/ioctl.2.html
http://man7.org/linux/man-pages/man2/ioctl_tty.2.html
fonte