2011-03-21 11 views
18

Estoy buscando formas de escribir datos en el proceso existente STDIN de procesos externos, y encontré la pregunta similar How do you stream data into the STDIN of a program from different local/remote processes in Python? en stackoverlow.Cómo escribir datos en el proceso STDIN del proceso externo?

En ese hilo, @Michael dice que podemos obtener descriptores de archivos del proceso existente en el camino como se muestra a continuación, y se les permite escribir datos en ellos en Linux.

/proc/$PID/fd/ 

Por lo tanto, he creado un script sencillo que aparece a continuación para probar escritura de datos en la secuencia de comandos de STDIN (y TTY) de proceso externo.

#!/usr/bin/env python 

import os, sys 

def get_ttyname(): 
    for f in sys.stdin, sys.stdout, sys.stderr: 
     if f.isatty(): 
      return os.ttyname(f.fileno()) 
    return None 

if __name__ == "__main__": 
    print("Try commands below") 

    print("$ echo 'foobar' > {0}".format(get_ttyname())) 
    print("$ echo 'foobar' > /proc/{0}/fd/0".format(os.getpid())) 

    print("read :: [" + sys.stdin.readline() + "]") 

Este script de prueba muestra caminos de STDIN y TTY y luego, esperar a que uno de escribirlo es STDIN.

Lancé este script y obtuve mensajes a continuación.

Try commands below 
$ echo 'foobar' > /dev/pts/6 
$ echo 'foobar' > /proc/3308/fd/0 

Así, ejecuté el comando echo 'foobar' > /dev/pts/6 y echo 'foobar' > /proc/3308/fd/0 desde otro terminal. Después de la ejecución de ambos comandos, el mensaje foobar se muestra dos veces en el terminal en el que se ejecuta el script de prueba, pero eso es todo. La línea print("read :: [" + sys.stdin.readline() + "]") no se ejecutó.

¿Hay alguna manera de escribir datos de procesos externos al proceso existente STDIN (u otros descriptores de archivos), es decir, invocar la ejecución de la línea print("read :: [" + sys.stdin.readline() + "]") desde otros procesos?

+1

¿Haría un tubo con nombre (ver 'man mkfifo') lo que quiere? – Andy

+0

Gracias por la sugerencia.Echaré un vistazo a named-pipe. – mooz

Respuesta

16

Su código no funcionará.
/proc/pid/fd/0 es un enlace al archivo /dev/pts/6.

$ echo 'parametro'>/dev/pts/6
$ echo 'parametro'>/proc/PID/fd/0

Dado que tanto los comandos de escritura al terminal. Esta entrada va a la terminal y no al proceso.

Funcionará si stdin inicialmente es una tubería.
Por ejemplo, test.py es:

#!/usr/bin/python 

import os, sys 
if __name__ == "__main__": 
    print("Try commands below") 
    print("$ echo 'foobar' > /proc/{0}/fd/0".format(os.getpid())) 
    while True: 
     print("read :: [" + sys.stdin.readline() + "]") 
     pass 

Ejecutar esto como:

$ (while [ 1 ]; do sleep 1; done) | python test.py 

Ahora desde otra escritura terminal de algo que /proc/pid/fd/0 y vendrá a test.py

+0

La secuencia de comandos y el comando sugeridos funcionan correctamente. Entonces, una vez que creé el proceso desde la terminal sin tubería como '$ python test.py', no hay forma de ejecutar' print ("read :: [" + sys.stdin.readline() + "]") 'desde proceso externo? – mooz

+1

@mooz: AFAIK no hay forma de hacerlo. –

3

quiero dejar aquí una ejemplo que encontré útil. Es una ligera modificación del verdadero truco anterior que falló intermitentemente en mi máquina.

# pipe cat to your long running process 
(cat) | ./your_server & 
server_pid=$! 
# send an echo to your cat process that will close cat and in my hypothetical case the server too 
echo "quit\n" > "/proc/$server_pid/fd/0" 

Fue útil para mí ya que por razones particulares que no podía usar mkfifo, lo cual es perfecto para este escenario.

Cuestiones relacionadas