Pregunta

Estoy buscando formas de escribir datos en los procesos existentes STDIN de procesos externos y encontró una pregunta similar ¿Cómo se transmite los datos en el stdin de un programa de diferentes procesos locales/remotos en Python? en Stackoverlow.

En ese hilo, @Michael dice que podemos obtener descriptores de archivos del proceso existente en la ruta como a continuación, y permitidos escribir datos en Linux.

/proc/$PID/fd/

Entonces, he creado un script simple que se enumera a continuación para probar la escritura de datos en el script. STDIN (y TTY) del 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 rutas de STDIN y TTY Y luego, espera a que uno escriba es STDIN.

Lanzé este script y recibí mensajes a continuación.

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

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

¿Hay alguna forma de escribir datos de procesos externos a los procesos existentes? STDIN (u otros descriptores de archivo), es decir, invocar la ejecución de la líneaprint("read :: [" + sys.stdin.readline() + "]") de otros procesos?

¿Fue útil?

Solución

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

$ echo 'foobar'>/dev/pts/6
$ echo 'foobar'>/proc/pid/fd/0

Dado que ambos comandos escriben a la terminal. Esta entrada va al terminal y no al proceso.

Funcionará si Stdin es una tubería intencionalmente.
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

Ejecute esto como:

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

Ahora desde otra terminal escriba algo a /proc/pid/fd/0 y llegará a test.py

Otros consejos

Quiero dejar aquí un ejemplo que me pareció útil. Es una ligera modificación del truco verdadero por encima de lo 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í porque por razones particulares no pude usar mkfifo, que es perfecto para este escenario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top