
Lo que estoy tratando de hacer es ejecutar Python en una ventana de terminal y redirigir su entrada estándar desde una tubería con nombre. Luego escribo en la canalización con nombre en otra terminal y hago que ese comando se ejecute en Python.
Terminal 1:
mkfifo p1
python < p1
Terminal 2:
echo -n "print \"Hello World\"" > p1
Lo que sucede es que Python se imprime Hello World
y sale. Lo que quiero hacer es mantener Python ejecutándose para ejecutar el siguiente comando. ¿Cómo hago esto en el shell?
Respuesta1
Necesitas
- Ejecute Python de forma interactiva aunque su entrada estándar no sea una terminal: use
python -i
- mantenga abierto el extremo de escritura de la tubería; de lo contrario, Python detectará EOF y saldrá.
Entonces:
python -i < p1
Y en otros lugares:
# open p1 on fd 3 of the shell process¹ for instance so stdout is
# left untouched in case you still want to write messages there.
exec 3> p1
# write something on fd 3. For instance with ksh/zsh's print
# builtin:
print -u3 '1j*1j'
# or for commands such as echo that can only print things
# on stdout (fd 1), duplicate that fd 3 to their fd 1:
echo '1j*1j' >&3 # short for 1>&3
# after echo (a builtin² in virtually all shells) returns, fd 1
# is restored to what it was before, but fd 3 remains open on
# the writing end of the pipe, so python still doesn't see EOF
# there.
echo normal message on stdout
echo 1+1 >&3 # more instructions for python
...
# and when done, close that file descriptor so python sees the EOF
# (assuming that fd 3 was the only file descriptor left open on
# the writing end of that pipe):
exec 3>&-
Especialmente en los scripts, como alternativa, puede redirigir un grupo de comandos completo en lugar de abrir y cerrar manualmente el fd con exec
³.
{
echo ... >&3
...
...
} 3> p1
¹ que fd 3 será heredado por procesos secundarios y (excepto en ksh93 que establece el indicador close-on-exec) por otros comandos ejecutados en esos procesos, si los hay.
² eso también funciona para comandos no integrados, por supuesto. Para los no integrados, el shell no necesita guardar y restaurar fd 1 ya que la redirección solo se realiza en el proceso hijo que se bifurca para ejecutar el comando. Para los comandos externos, excepto en ksh93 que lo hace automáticamente, es posible que desee cerrar ese fd 3 para que no se filtre y no se generen procesos en segundo plano con el tiempo ( cmd >&3 3>&-
).
³ tenga en cuenta que en ese caso, ksh93 no establece el indicador de cierre en ejecución en ese fd 3.
Respuesta2
Puede usarlo tail -f
para mantener el quince abierto después de echo
escribir en él.
tail -n1 -f p1 | python
¿Por qué esto funciona?
python
está leyendo de p1
. Cuando llega al final del archivo, deja de leer. Este es un comportamiento normal para las lecturas de archivos, incluso si el archivo es una canalización con nombre. tail
con el -f
indicador (seguir) seguirá leyendo un archivo una vez que se llegue a su final.
Respuesta3
Debe enviar el programa completo de una vez.
Cuando llamas a ejecutar, python < p1
el shell está esperando una entrada antes de invocar a Python. Es decir, Python ni siquiera comienza a ejecutarse.en absolutohasta que el shell haya leído todo el flujo de datos y luego se pase en su totalidad a python
.
Incluso ejecutarlo python -u p1
(es decir, sin búfer y leer desde el archivo p1
) python
intentará leer el archivo completo antes de ejecutarlo.
Prueba este experimento.
Terminal 1:
mkfifo p1
python < p1
Terminal 2:
cat > p1
print "Hello World"
print "Hello World"
Verá que puede enviar varias líneas pero Python en el Término 1 no hace nada. Ahora presione ctrl+ D. Todo el programa se ejecuta a la vez.
Entonces, para resumir, si desea que Python lea desde una tubería, debe enviar el programa completo. No puedes usar Python de forma interactiva de esta manera.
Respuesta4
Aquí hay otra solución. Terminal 1:
alec@MacBook-Air ~/hello $ rm -f my.fifo; mkfifo my.fifo
alec@MacBook-Air ~/hello $ cat my.fifo
command1
command2
...
alec@MacBook-Air ~/hello $
Terminal 2:
alec@MacBook-Air ~/hello $ cat > my.fifo
command1
command2
...
alec@MacBook-Air ~/hello $
Escribe sus comandos en la Terminal 2 y los ve aparecer en la Terminal 1. Puede canalizar la salida de la Terminal 1 a otro proceso, por ejemplo cat my.fifo | node ...
. Cuando termine, cierre stdin
la Terminal 2 con Ctrl-D. Esto se cerrará my.fifo
y cat
se cerrará el comando en la Terminal 1.