¿Cómo escribir datos en el stdin del proceso existente desde el proceso externo?
-
28-10-2019 - |
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?
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.