¿Cómo puedo saber si un comando se está ejecutando o está esperando la entrada del usuario?

14

En la línea de comando, escribí un comando y presioné enter. No da salida a nada. ¿Cómo puedo saber si se está ejecutando y aún no se emite, o si está solicitando la entrada del usuario?

Gqqnbig
fuente
Si está esperando, no recibirá un PS1aviso.
Prvt_Yadav
1. Por favor díganos qué programa es (que es silencioso), y podemos darle consejos más precisos sobre qué esperar y cómo verificarlo; 2. ¿Desea recibir una alerta cuando el programa finalmente solicite información o haya finalizado (para que se escriba algo en la ventana del terminal?
sudodus
si se espera una entrada, supongo que recibirá un mensaje con un mensaje en frente pidiéndole entrada.
Rinzwind
55
@Rinzwind - Esa es una suposición pobre. El primer contraejemplo a la mente es el catcomando. Simplemente escriba catpor sí mismo y esperará la entrada de stdin, pero no da ningún aviso. Muchos otros comandos se comportan de manera similar porque esperan la entrada de stdin o de un archivo, pero no diferencian entre diferentes fuentes de entrada (terminal interactiva, tubería, archivo ...).
Dave Sherohman

Respuestas:

15

Hay varios enfoques:

  1. Intente señalar el final de la entrada : sin privilegios de superusuario, es difícil saber qué está sucediendo debajo del capó. Lo que se puede hacer es presionar Ctrl+ d. Los terminales y las utilidades en modo canónico envían todo el texto disponible a read()syscall al recibir la señal EOT vinculada a esta combinación de teclas, y si no hay entrada, read()devuelve el estado de salida negativo que la mayoría de las utilidades aceptan como señal de salida. Por lo tanto, si una utilidad está esperando la entrada, saldrá al recibir la combinación de teclas. De lo contrario, la utilidad está ejecutando tareas o no está escrita correctamente.

  2. Espiar llamadas de sistema : si tiene privilegios de superusuario, puede ejecutar straceen otro terminal para ver lo que se está haciendo actualmente. Para eso necesitas averiguar el PID del programa. Por ejemplo, en otra pestaña de terminal ejecute pgrep -f firefoxque puede 1234 como ejemplo y luego sudo strace -f -p 1234. Si la salida que ve está atascada en read()syscall, significa que el comando probablemente esté esperando entrada. De lo contrario, si ve syscalls corriendo, entonces el comando está haciendo otra cosa. Consulte una pregunta relacionada para usar stracetambién para averiguar si el comando de ejecución prolongada ha salido.

  3. Utilice los métodos propios del comando : entre otras cosas, utilidades como las ddseñales de uso. Por ejemplo, si usa kill -USR1 1234(donde 1234 es PID del ddcomando en ejecución ), se imprimirá para almacenar la cantidad de bytes procesados ​​actualmente. Por supuesto, esto requiere saber sobre tal comportamiento del comando en primer lugar. Los dos métodos anteriores son más generales y no requieren un conocimiento profundo del comportamiento de cada comando (aunque siempre es mejor saber lo que realmente está ejecutando; de lo contrario, corre el riesgo de ejecutar un comando que puede dañar).

Sergiy Kolodyazhnyy
fuente
+1. Gracias por el stracemétodo :-) Pero los métodos más simples también son útiles (generales o específicos para cada programa). Algunos de ellos funcionan sin privilegios de superusuario. Ejemplos: verifique si ddestá haciendo algo y verifique por qué grep --color asdfestá esperando en silencio.
sudodus
@sudodus Ah, buen recordatorio sobre ddque agregaré ese.
Sergiy Kolodyazhnyy
No necesita privilegios de superusuario para depurar un proceso propiedad de su usuario. Bueno, a menos que no haya configurado el sistema adecuadamente .
Ruslan
6

Cómo saber si un programa se está ejecutando o si desea la entrada del usuario

Depende del programa y de cómo lo invoques.

  • A menudo, pero no siempre, habrá un mensaje que indica que el programa está solicitando información.

  • Si no está seguro, puede verificar si el proceso del programa está ocupado

    • usa CPU - usa topohtop

    • lee o escribe - use sudo iotop -o

  • Y cuando el programa haya finalizado, verá el indicador del shell.

Shellscript running

Tenía un shellscript que verifica si un programa se está ejecutando, y ahora he agregado la opción -spara que se ejecute sudo strace -f -p <PID>(según la respuesta de Sergiy Kolodyazhnyy) cuando se encuentra un ...

El shellscript usa

  • ps -ef para encontrar la mayoría de los programas
  • systemctl is-active --quiet para encontrar algunos programas
  • y si lo deseas straceen una xtermventana.

    Instale xtermsi desea usar stracepara ver la actividad de un programa.

Uso

$ ./running
Usage:    ./running <program-name>
          ./running <part of program name>
Examples: ./running firefox
          ./running term                     # part of program name
          ./running dbus
          ./running 'dbus-daemon --session'  # words with quotes
          ./running -v term                  # verbose output
          ./running -s term                  # strace checks activity

Puede instalar el shellscript runningen un directorio PATHsi desea acceder fácilmente a él.

El código shellscript

#!/bin/bash

# date        sign     comment
# 2019-02-14  sudodus  version 1.0

verbose=false
strace=false
if [ "$1" == "-v" ]
then
 verbose=true
 shift
fi
if [ "$1" == "-s" ]
then
 strace=true
 shift
fi

if [ $# -ne 1 ]
then
 echo "Usage:    $0 <program-name>
          $0 <part of program name>
Examples: $0 firefox
          $0 term                     # part of program name
          $0 dbus
          $0 'dbus-daemon --session'  # words with quotes
          $0 -v term                  # verbose output
          $0 -s term                  # strace checks activity"
 exit
fi

inversvid="\0033[7m"
resetvid="\0033[0m"
redback="\0033[1;37;41m"
greenback="\0033[1;37;42m"
blueback="\0033[1;37;44m"

runn=false
#tmpfil=$(mktemp)
tmpdir=$(mktemp -d)
tmpfil="$tmpdir/tmpfil"
vtfile="$tmpdir/vtfile"
vthead="$tmpdir/vthead"

# check by systemctl

systemctl is-active --quiet "$1"
if [ $? -eq 0 ]
then
 echo "systemctl is-active:"
 runn=true
fi

# check by ps

ps -ef | tr -s ' ' ' ' | cut -d ' ' -f 8- | grep "$1" | grep -vE -e "$0 *$1" -e "$0 *.* *$1" -e "grep $1" | sort -u > "$tmpfil"
#cat "$tmpfil"
if $verbose || $strace
then
 ps -ef |head -n1 > "$vthead"
 ps -ef | grep "$1" | grep -vE -e "$0 *.* *$1" -e "grep $1" | sort -u > "$vtfile"
fi

tmpstr=$(head -n1 "$tmpfil")
#echo "tmpstr=$tmpstr"
tmpess=$(grep -om1 "$1" "$tmpfil")
#echo "tmpess=$tmpess"
if [ "$tmpstr" == "$1" ] || [ "${tmpstr##*/}" == "$1" ] || [ "${1##*/}" == "${0##*/}" ] || [ "$tmpess" == "$1" ]
then
 echo "ps -ef: active:"
 runn=true
 if $verbose
 then
  cat "$vthead" "$vtfile"
 fi
elif test -s "$tmpfil"
then
 if $runn
 then
  echo "----- consider also ------------------------------------------------------------"
  if $verbose
  then
   cat "$vthead" "$vtfile"
  else
   cat "$tmpfil"
  fi
  echo "--------------------------------------------------------------------------------"
 else
  echo "----- try with: ----------------------------------------------------------------"
  if $verbose
  then
   cat "$vthead" "$vtfile"
  else
   cat "$tmpfil"
  fi
  echo "--------------------------------------------------------------------------------"
 fi
fi

if $runn
then
 echo -en "$greenback '$1"
 if [ "$tmpstr" != "$tmpess" ]
 then
  echo -n " ..."
 fi
 echo -e "' is running $resetvid"

 if $strace
 then
  which xterm
  if [ $? -eq 0 ]
  then
   pid=$(head -n1 "$vtfile" | sed 's/^ *//' | tr -s ' ' '\t' | cut -f 2)
   echo "checking pid=$pid; quit with 'ctrl + c' in the xterm window"
   xterm -title "'strace' checks '$1'" 2> /dev/null -e sudo strace -f -p $pid
  else
   echo "Please install 'xterm' for this function to work"
   exit
  fi
 fi
else
 inpath=$(which "$1")
 if [ "$inpath" == "" ]
 then
  echo -e "$redback no path found to '$1' $resetvid"
 else
  echo -e "$blueback '$1' is not running $resetvid"
 fi
fi
rm -r "$tmpdir"

Manifestación

Comprobando las ventanas de terminal en Lubuntu (LXTerminal comenzó como x-terminal-emulatory gnome-terminalventanas personalizadas ),

$ running -v -s term 
----- try with: ----------------------------------------------------------------
UID        PID  PPID  C STIME TTY          TIME CMD
sudodus   2087  1384  0 13:33 ?        00:00:00 x-terminal-emulator
sudodus   2108  1269  0 13:33 ?        00:00:17 /usr/lib/gnome-terminal/gnome-terminal-server
--------------------------------------------------------------------------------
 no path found to 'term' 

$ running -v -s x-terminal-emulator
ps -ef: active:
UID        PID  PPID  C STIME TTY          TIME CMD
sudodus   2087  1384  0 13:33 ?        00:00:00 x-terminal-emulator
 'x-terminal-emulator' is running 
/usr/bin/xterm
checking pid=2087; quit with 'ctrl + c' in the xterm window

Hay mucha actividad tan pronto como el cursor está en la ventana de terminal.

ingrese la descripción de la imagen aquí

Iniciando grep(esperando la entrada de /dev/stdin)

$ grep -i --color 'hello'
asdf
Hello World    
Hello World

Comprobándolo

$ running -s grep
ps -ef: active:
 'grep ...' is running 
/usr/bin/xterm
checking pid=14982; quit with 'ctrl + c' in the xterm window

No hay mucha actividad y puedes identificar lo que está sucediendo.

ingrese la descripción de la imagen aquí

sudodus
fuente
Buena mención de iotop, aunque el uso de la CPU no necesariamente sea un indicador si un proceso está ocupado. Un programa escrito en C y optimizado podría estar usando una CPU mínima. Algunos de los indicadores que he escrito en Python programan una tarea repetida para ejecutarse, por lo que podría usar la CPU para actualizar el menú del indicador por un breve momento y luego simplemente se queda allí.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy, Sí, tienes razón en eso. El stracemétodo es mejor, pero quizás no sea necesario o no esté disponible.
sudodus
Convenido. No creo que venga preinstalado con Ubuntu, y podría ser excesivo.
Sergiy Kolodyazhnyy
1

No estoy seguro si todavía necesita esto, pero sigue siendo un truco útil para saber: si el programa parece salir sin ningún resultado, puede verificar si se está ejecutando en segundo plano ejecutando

ps -efa | grep "program_name"

¡Salud!

Marcel Ferrari
fuente
1

Si está ejecutando el shell en una terminal, por ejemplo, un emulador de terminal o una sesión ssh típica, su shell seguramente ha habilitado el control de trabajos. Esto hace que obtener una respuesta a su pregunta sea muy fácil en la mayoría de los casos.

Escriba Ctrl+Zpara suspender el proceso y luego bgcontinuarlo en segundo plano, luego escriba una línea vacía al shell para que verifique si el programa se detuvo por una señal.

Si el proceso está tratando de leer desde la terminal, inmediatamente recibirá una SIGTTINseñal y se suspenderá. (Cuando el control de trabajo está habilitado, el sistema solo permite leer un proceso a la vez desde el terminal). El shell informará esto. Luego puede escribir fgpara continuar el proceso en primer plano y luego escribir la entrada para que el programa la lea de manera normal.

mp@ubuntu:~$ sleep 30 # a program that is not reading from the terminal
^Z
[1]+  Stopped                 sleep 30
mp@ubuntu:~$ bg
[1]+ sleep 30 &
mp@ubuntu:~$ 
mp@ubuntu:~$ 


mp@ubuntu:~$ cat - # a program that is reading from the terminal
^Z
[1]+  Stopped                 cat -
mp@ubuntu:~$ bg
[1]+ cat - &
mp@ubuntu:~$ 
[1]+  Stopped                 cat -
mp@ubuntu:~$ jobs -l
[1]+  3503 Stopped (tty input)     cat -
mp@ubuntu:~$ fg
cat -
hi
hi

Algunos programas, como los editores, atrapan o ignoran la señal generada por Ctrl+Zel terminal o lo ponen en un modo donde los caracteres de control ni siquiera generan señales. Tendrá que utilizar técnicas más avanzadas en este caso, como el uso stracepara ver si el proceso está haciendo read, select, poll, etc.

Mark Plotnick
fuente