Enviar comando a la pantalla separada y obtener la salida

12

He estado buscando para encontrar una manera de enviar un comando a una sesión de pantalla separada. Hasta aquí todo bien. Esto es lo que se me ocurrió:

$ screen -S test -p 0 -X stuff 'command\n'

Este comando funciona como debería. Pero, también me gustaría que la salida se repitiera directamente frente a mis ojos (no es necesario un .logarchivo o algo, solo quiero la salida).

Usar el screen -Lcomando no es una opción.

Robin
fuente
¿Por qué tiene que ser screen? ¿No es para esto que están hechos los procesos secundarios?
Anko

Respuestas:

10

Use una tubería de primero en entrar, primero en salir:

mkfifo /tmp/test

Use un operador de redireccionamiento. Redireccione la salida del comando a / tmp / test, por ejemplo, así:

screen -S test -p 0 -X stuff 'command >/tmp/test\n'

Luego en otro caparazón

tail -f /tmp/test.

Tenga en cuenta que también es posible que desee redirigir los mensajes de error utilizando el operador 2> & 1 .

Ejemplo

Como se solicitó en los comentarios, supongamos que tenemos un script php que acepta la entrada del usuario e imprime la carga del servidor en la entrada de "estado":

# cat test.php
<?php
  $fp=fopen("php://stdin","r");
  while($line=stream_get_line($fp,65535,"\n")) 
  {
    if ($line=="status") {echo "load is stub";} 
  } 
  fclose($fp);
?>

Creas dos fifos:

 # mkfifo /tmp/fifoin /tmp/fifoout

Llamas a una pantalla:

screen

En otra consola, llamémosla consola 2, encontrará el nombre de su pantalla:

# screen -ls
There is a screen on:
        8023.pts-3.tweedleburg  (Attached)
1 Socket in /var/run/screens/S-root.

En la consola 2, envía el comando a la pantalla:

 # screen -S 8023.pts-3.tweedleburg -p 0 -X stuff 'php test.php </tmp/fifoin >/tmp/fifoout\n'

verá el comando que aparece en la pantalla. Ahora en la consola 2 puede enviar comandos a su proceso php:

echo "status" >/tmp/fifoin

y lee de ella:

# cat /tmp/fifoout
load is stub
Thorsten Staerk
fuente
1
Lo siento, pero esto no funciona. Si estoy enviando un comando a la pantalla como 'command> / tmp / test', el proceso debe admitir la sintaxis> / tmp / test ... Y no lo hace.
Robin
Para mí funciona, tenga en cuenta que pongo "prueba" como el nombre de su pantalla. Puede encontrar el nombre de su pantalla con el comando screen -ls. Además, "comando" debe ser reemplazado por su comando real, probé con el comando ls. Además, probé con el shell bash.
Thorsten Staerk
Yo sé eso. Y no funciona. Por ejemplo, inicie un script PHP en una ventana de pantalla, que, por ejemplo, responde a un comando "estado", que devuelve la carga actual del servidor, por ejemplo. Eso es lo que intento hacer.
Robin
entonces necesitará tuberías bidireccionales, estoy agregando esto a mi respuesta
Thorsten Staerk
6

Tengo un script de Python que realiza un seguimiento de numerosas sesiones de pantalla separadas y captura la salida de cada una (cuando los comandos de utilización como free, top -bn2, iostat se envían periódicamente a través de 'cosas').

En lugar de redirigir a un archivo y, por lo tanto, administrar al menos un archivo por sesión de pantalla separada ... Simplemente redirijo a cualquier tty / pts que esté utilizando mi sesión principal.

Paso # 1: Comience una nueva sesión de pantalla (con un nombre legible por humanos) en modo separado.

$ screen -dmS chad 

Paso # 2: envíe sus comandos (usaré el comando 'free -g' junto con 'uname -r') a través de cosas. Es importante especificar la ventana que desea usar (en nuestro caso, la primera y única ventana) con -p.

$ screen -r chad -p0 -X stuff "free -g; uname -r" 

Paso # 3: El paso anterior solo envía el texto del comando. También debemos enviar un retorno de carro a esta sesión de pantalla separada para que el shell ejecute nuestro comando. El carácter ASCII 015 es un retorno de carro en la mayoría de los sistemas * nix.

$ screen -r chad -p0 -X eval "stuff \015"

Paso 4: redirige la salida de nuestra sesión de pantalla separada a nuestro tty / pts actual:

$ screen -r chad -p0 -X hardcopy $(tty)

El resultado del Paso 4 se verá más o menos así:

$ free -g; uname -r
             total       used       free     shared    buffers     cached
Mem:             7          1          6          0          0          0
-/+ buffers/cache:          0          7
Swap:            1          0          1
2.6.32-358.el6.x86_64

Aunque esto parece un poco complicado, el proceso es fácilmente programable. Con python, puedo analizar el resultado del Paso # 4 y capturar solo los datos que me interesan.

Al elegir un escenario simple como obtener detalles de IP, escribí un script de ejemplo para demostrar los conceptos anteriores. Siéntase libre de reemplazar y retocar como mejor le parezca.

Ejemplo de secuencia de comandos de Python para obtener detalles de IP de una sesión de pantalla separada:

#!/usr/bin/python

import pexpect, time

#spawn a new bash session
session = pexpect.spawn('/bin/bash')
#send screen commands
session.sendline('screen -dmS netIP')
session.sendline('screen -r netIP -p0 -X stuff "ifconfig eth0 | grep -v eth0 | head -1"')
session.sendline('screen -r netIP -p0 -X eval "stuff \\015"')
#give the command a chance to execute before reading the output of our detached screen
time.sleep(0.1)

#use the output of the uname command as our string to expect
session.sendline('screen -r netIP -p0 -X hardcopy $(tty); $(uname)')
session.expect('Linux')

#parse the output - only concerned with the 'inet' line
output = session.before.split('\n')
for o in output:
    if 'inet' in o:
        print o

#kill the screen
session.sendline('screen -r netIP -p0 -X quit')
time.sleep(0.1)

session.close()

Guión anterior en acción:

$ python screen-output-test.py 
      inet addr:192.168.1.201  Bcast:192.168.1.255  Mask:255.255.255.0
chad_walker
fuente
Me gusta esta respuesta mucho mejor que la aceptada, porque no se basa en que la pantalla esté en estado de "shell shell", sino que también funciona con lo que se está ejecutando en esa pantalla.
Guntram Blohm apoya a Monica
Sin embargo, requiere que la salida se ajuste a la pantalla. Encontré screen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log offpara trabajar aún mejor en ese escenario.
Guntram Blohm apoya a Monica
-1
screen -S myscreen

screen -R myscreen -X exec command

Ejemplo:

screen -R myscreen -X exec top
aod
fuente