it-swarm-es.tech

¿Cómo ver el resultado de un proceso en ejecución en otra sesión bash?

He dejado una secuencia de comandos ejecutándose en una máquina remota desde que estaba trabajando localmente en ella. Puedo conectarme a través de SSH a la máquina como el mismo usuario y ver el script que se ejecuta en ps.

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

Simplemente está enviando a stdout en una sesión local (ejecuté ./ipchecker.sh forma una ventana de terminal local, sin redireccionamiento, sin uso de screen etc.).

¿Hay alguna forma de que desde una sesión SSH pueda ver el resultado de este comando en ejecución (sin detenerlo)?

Hasta ahora, lo mejor que he encontrado es usar strace -p 18386 pero recibo hordas de texto volando por la pantalla, es demasiado detallado. Puedo detener strace y luego examinar la salida y encontrar el texto impreso en stdout, pero es muy largo y confuso, y obviamente mientras está detenido podría perder algo. Me gustaría encontrar una manera de ver la salida del script en vivo como si estuviera trabajando localmente.

¿Alguien puede mejorar en esto? La respuesta obvia es reiniciar el script con redirección o en una sesión screen, etc., este no es un script de misión crítica, por lo que podría hacer eso. Sin embargo, veo esto como un ejercicio de aprendizaje divertido.

223
jwbensley

Si todo lo que quiere hacer es espiar el proceso existente, puede usar strace -p1234 -s9999 -e write donde 1234 es la ID del proceso. (-s9999 evita tener cadenas truncadas a 32 caracteres, y write la llamada al sistema que produce la salida.) Si desea ver solo los datos escritos en un descriptor de archivo en particular, puede usar algo como strace -p1234 -e trace= -e write=3 para ver solo los datos escritos en el descriptor de archivo 3 (-e trace= evita que se registren las llamadas del sistema). Eso no le dará salida que ya ha sido producida.

Si el resultado se desplaza demasiado rápido, puede canalizarlo a un localizador como less, o enviarlo a un archivo con strace -o trace.log ….

Con muchos programas, puede desviar la salida posterior con un hack de ptrace, ya sea a su terminal actual o a una nueva sesión de pantalla. Consulte ¿Cómo puedo rechazar un proceso en ejecución y asociarlo a un nuevo shell de pantalla? y otros hilos vinculados.

Tenga en cuenta que dependiendo de cómo esté configurado su sistema, es posible que deba ejecutar todos estos comandos strace como root, incluso si el proceso se ejecuta bajo su usuario sin privilegios adicionales. (Si el proceso se ejecuta como un usuario diferente o es setuid o setgid, necesitará ejecutar strace como root). La mayoría de las distribuciones solo permiten que un proceso rastree a sus hijos (esto proporciona un beneficio de seguridad moderado: evita la inyección directa de malware, pero no evita la inyección indirecta al modificar los archivos). Esto es controlado por el kernel.yama.ptrace_scome sysctl.

Puede acceder a la salida a través del sistema de archivos proc.

tail -f /proc/<pid>/fd/1

1 = stdout, 2 = stderr

164
tvlooy

En BSD, puede usar watch que espía un tty dado, p.

watch /dev/pts/0

En Linux, no será posible si el proceso no se ejecutó bajo multiplexor antes, como screen o tmux. Consulte también: Reptyr: Adjunte un proceso en ejecución a una nueva terminal

Parece que la única forma es depurar el proceso (por ejemplo, strace, dtrace/dtruss, gdb , lldb, etc.).

Como ha utilizado strace, para obtener cualquier resultado significativo, debe filtrar por una expresión de calificación (como file), luego analizar el resultado. Aquí hay un ejemplo:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

Lo que hace imprime la operación de escritura del proceso (1000 de longitud) especificado por PID (use pgrep para encontrarlo por su nombre), redirige el error estándar en la salida (para ser filtrado) e imprime una cadena entre comillas dobles.

Si está tratando con salida binaria, puede analizar caracteres de secuencias de escape utilizando read (con -r) y printf (con %b), p.ej.

while read -r -t1 line; do printf "%b" $line; done

Cheque help read para más parámetros (por ejemplo, -n para imprimir después de cierta cantidad de caracteres, en lugar de nueva línea).

Aquí hay un ejemplo más completo:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

Para ver ejemplos de cualquier proceso, verifique: ¿Cómo analizar strace en Shell en texto plano? en stackoverflow

10
kenorb

Aconsejaría hacer una tubería con nombre (mkfifo) y luego escribir en ese archivo. Entonces, lea de ella. Siempre puede hacer eso con cosas como tail, para minimizar la salida, etc. Cada vez que borra la tubería (leída de ella), se borra, por lo que la salida no se conserva.

La otra opción sería escribir todo en un archivo (como un archivo de registro) y luego analizarlo en cualquier momento. Esta sería la acción preferida, si desea conservar toda la salida.

4
polemon
  1. Es posible que pueda mirar la pantalla remota usando ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scale donde localhost debe ser reemplazado por las credenciales de inicio de sesión del servidor remoto y :0.0 con el número de pantalla de su GUI.

  2. Utilizar x11vnc, que es un servidor VNC para su sesión X en pantalla.

  3. Cuando se ejecuta en una de las 6 consolas virtuales, intente Sudo setterm -dump 2 -file /dev/stdout, donde reemplazas 2 con el vc apropiado.

4
jippie

Siempre puede iniciar un proceso con Nohup y &

Nohup rsync source_file dest_file &

Luego, podrá verificar el progreso desde cualquier tty con:

tail -f Nohup.out

Esto me funciona bien.

3
Pablo Luna

Analizando la salida de strace:

Usé respuesta superior (con mi ID de proceso de 28223) ...

> Sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

Para determinar que me preocupo por write(9. (El 9 se usa a continuación, probablemente sea un identificador de archivo y puede ser diferente para su proceso). Luego escribí un script rápido Ruby para analizar y mostrarlos.

Pegue lo siguiente en /usr/bin/parse_strace.rb

#!/usr/bin/Ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

No te olvides chmod a+x /usr/bin/parse_strace.rb

Invoco strace -xx (genera hexadecimal, por lo que la expresión regular coincide correctamente), canalizando (incluido STDERR) a mi script con 9 como el primer argumento.

Sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

Y, voila, ¡muestra el STDOUT original del proceso, las nuevas líneas, el color y todo!

Attaching to process STDOUT

3
Jeff Ward

Una forma muy simple de obtener la salida sería capturar su salida en un archivo y seguir ese archivo.

SI LO HACE: ./ipcheck

INSTEAD DO: ./ipcheck> [replacewithyourfilename]

Esto crearía un archivo de salida donde se encuentra su script. Luego, desde cualquier otro bash Shell, simplemente puede seguir el archivo:

cola [reemplazar con su nombre de archivo] -f

1
MrAllen

¿No puede obtener la ID del proceso y comunicarse con USR1?

$pgrep -l '^ipchecker.sh$'

que imprime el PID de su script, luego lo usa para

$ kill -USR1 PID

Entiendo que USR1 es una señal "definida por el usuario", lo que significa que quien creó el programa puede usarlo para significar "apagar" o "volcar sus registros" o "imprimir miles de veces" o lo que sea.

0
Saeed