Escribir en stdin del proceso en segundo plano

25

Estoy en un cuadro de Ubuntu 10.04 e inicié un servidor en segundo plano (myserver &) sobre ssh. Ha estado funcionando bien, pero necesito una forma de llegar al stdin del servidor, ya que la única forma de controlar el servidor es a través de este método.

¿Hay alguna forma de llegar al stdin de un proceso que ya se está ejecutando para poder escribirle (y espero leer su stdout)? Obviamente, si fuera a hacer esto ahora, comenzaría con un FIFO que redirige a stdin, pero desafortunadamente ya es un poco tarde para eso.

¿Algunas ideas?

Tajmorton
fuente
¿No podrías traerlo de vuelta al primer plano? ('jobs' enumerará su proceso de fondo actual, 'fg $ X' volverá a poner el trabajo en primer plano, ctrl + b pausará el trabajo y lo regresará a su shell, mientras que 'bg' continuará el proceso en pausa en el fondo)
symcbean

Respuestas:

10

Puede intentar escribir en su directorio / proc pid. Digamos que su pid de demonios es 2000, intente escribir a / proc / 2000 / fd / 0

katriel
fuente
Gracias ... Lo encontré justo después de publicar esto (después de un día de mirar, típico). Eso parece funcionar (en lo que respecta al envío de datos al programa). Desafortunadamente, el programa no acepta los comandos. Lo probé ejecutando el servidor en mi computadora local, y efectivamente, veo que aparecen los datos, pero el programa no reconoce los comandos. Tengo que presionar manualmente enter en la terminal del servidor, y luego solo dice comando no reconocido. Tal vez alguna rareza de Java? Estoy atascado ...
tajmorton
1
¿qué tal echo -e "algo \ n"> / proc / 2000 / fd / 0?
katriel
En realidad, esto no siempre funciona como / proc / <pid> / fd / 0 apunta a / dev / pts <algún número> en al menos algunos sistemas ...
bk138
La primera respuesta a serverfault.com/questions/178457/… señala que este enfoque en realidad no funciona.
barrycarter
2
Esto en realidad no funciona. Su shell normalmente (cuando no se utilizan canalizaciones o redirecciones) inicia un comando con descriptores de archivo a 0través del 2conjunto en el mismo archivo, que normalmente es un terminal virtual (algo así como /dev/pty/...). El comando luego lee desde FD 0y escribe en FD 1y se 2comunica con el terminal virtual (por ejemplo, a través de SSH o directamente con su emulador de terminal). Si algún otro proceso accede a ese archivo (por ejemplo, a través de /proc), sucede exactamente lo mismo, es decir, escribir en él escribe en el terminal y no en el comando.
Feuermurmel
29

Puede iniciar su servidor con una tubería con nombre (fifo) como entrada:

mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
cat /tmp/srv-input | myserver &

El cat > /tmp/srv-input &es importante evitar el servidor para recibir un EOF. Al menos un proceso debe tener el fifo abierto por escrito para que su servidor no reciba un EOF. El PID de este comando se guarda en el /tmp/srv-input-cat-pidarchivo para este último asesinato.

En el caso de que ya haya iniciado su servidor, debe usar un depurador como gdbpara adjuntarlo a su proceso para redirigirlo stdinal fifo:

gdb -p PID
call close(0)
call open(0, "/tmp/srv-input", 0600)

Y luego haga algo como abajo para enviar entradas a su servidor (en otra ventana de terminal si es necesario):

echo "command" > /tmp/srv-input

Para enviar un EOF a su servidor, debe eliminar el cat > /tmp/srv-inputproceso cuyo PID se ha guardado en el /tmp/srv-input-cat-pid file.

En el caso de GDB, simplemente salga de GDB y se enviarán EOF.

jfg956
fuente
1
Este es un enfoque mucho más portátil que el de @katriel, ya que / proc / 2000 / fd / 0 no es estándar en todos los sistemas.
Prior99
El truco con "cat> / tmp / srv-input &" me ahorró algunos dolores de cabeza. ¡Gracias!
Prior99
¿Qué hay de mkfifo /tmp/srv-input; tail -f /tmp/srv-input | myserver &? Esto también mantendrá la tubería abierta ...
bk138
@ bk138: me parece que la cola debería funcionar, pero solo hay una forma de saberlo con certeza: prueba.
jfg956
tailno funciona, pero agregó esto para finalizar el trabajo: cat /tmp/srv-input | myserver; kill -9 cat / tmp / srv-input-cat-pid` && rm / tmp / srv-input-cat * `
Thiago Macedo
4

Igual que el anterior, pero 'gato' no funcionó para mí. El archivo obtuvo EOF y terminó después de enviar un comando.

Esto funcionó para mí:

#!/bin/bash

mkfifo /tmp/srv-input
tail -f /tmp/srv-input | myserver &
Tamir
fuente