Comment savoir si une commande est en cours d'exécution ou attend une entrée utilisateur?

14

Sur la ligne de commande, j'ai tapé une commande et appuyez sur Entrée. Il ne produit rien. Comment savoir s'il est en cours d'exécution et pas encore sorti, ou s'il demande une entrée utilisateur?

Gqqnbig
la source
S'il attend, vous ne recevrez pas d' PS1invite.
Prvt_Yadav
1. Veuillez nous dire de quel programme il s'agit (qui est silencieux), et nous pouvons vous donner des conseils plus précis sur ce à quoi vous attendre et comment le vérifier; 2. Souhaitez-vous recevoir une alerte, lorsque le programme demande enfin une entrée ou a terminé (pour que quelque chose soit écrit dans la fenêtre du terminal?
sudodus
s'il y a une entrée attendue, je suppose que vous obtenez une invite avec un message devant lui demandant une entrée.
Rinzwind
5
@Rinzwind - C'est une mauvaise hypothèse. Le premier contre-exemple à l'esprit est la catcommande. Tapez simplement catpar lui-même et il attendra l'entrée de stdin, mais ne donnera aucune invite. De nombreuses autres commandes se comportent de manière similaire car elles attendent des entrées de stdin ou d'un fichier, mais ne différencient pas les différentes sources d'entrée (terminal interactif, pipe, fichier ...).
Dave Sherohman

Réponses:

15

Il existe plusieurs approches:

  1. Essayez de signaler la fin de l'entrée : sans privilèges de superutilisateur, il est difficile de savoir ce qui se passe sous le capot. Ce qui peut être fait est d'appuyer sur Ctrl+ d. Les terminaux et les utilitaires en mode canonique envoient tout le texte disponible à read()syscall lors de la réception du signal EOT lié à cette combinaison de touches, et s'il n'y a pas d'entrée - read()renvoie un état de sortie négatif que la plupart des utilitaires acceptent comme signal de sortie. Par conséquent, si un utilitaire attend une entrée, il se fermera lors de la réception de la combinaison de touches. Sinon, l'utilitaire exécute des tâches ou n'est pas écrit correctement.

  2. Espionner les appels système : si vous disposez du privilège de superutilisateur, vous pouvez exécuter stracedans un autre terminal pour voir ce qui est actuellement en cours. Pour cela, vous devez connaître le PID du programme. Par exemple, dans un autre onglet de terminal, exécutez pgrep -f firefox1234 comme exemple, puis sudo strace -f -p 1234. Si la sortie que vous voyez est bloquée sur read()syscall, cela signifie que la commande attend probablement une entrée. Sinon, si vous voyez des appels système s'exécuter, alors la commande fait autre chose. Voir une question connexe pour l'utilisation de straceafin de déterminer également si la commande longue s'est terminée.

  3. Utilisez les propres méthodes de la commande : entre autres, des utilitaires tels que l' ddutilisation de signaux. Par exemple, si vous utilisez kill -USR1 1234(où 1234 est le PID de la ddcommande en cours d'exécution ), il s'imprime pour afficher la quantité d'octets actuellement traités. Bien sûr, cela nécessite en premier lieu de connaître un tel comportement de la commande. Les deux méthodes ci-dessus sont plus générales et ne nécessitent pas une connaissance approfondie du comportement de chaque commande (bien qu'il soit toujours préférable de savoir ce que vous exécutez réellement - sinon vous risquez d'exécuter une commande qui peut endommager).

Sergiy Kolodyazhnyy
la source
+1. Merci pour la straceméthode :-) Mais des méthodes plus simples sont également utiles (générales ou spécifiques à chaque programme). Certains d'entre eux fonctionnent sans privilèges de superutilisateur. Exemples: vérifiez si ddfait quelque chose et pourquoi grep --color asdfattend en silence.
sudodus
@sudodus Ah, bon rappel ddje vais ajouter celui-là.
Sergiy Kolodyazhnyy
Vous n'avez pas besoin des privilèges de superutilisateur pour déboguer un processus appartenant à votre utilisateur. Eh bien, à moins que vous n'ayez pas configuré le système correctement .
Ruslan
6

Comment savoir si un programme est en cours d'exécution ou si vous souhaitez une entrée utilisateur

Cela dépend du programme et de la façon dont vous l'invoquez.

  • Souvent, mais pas toujours, il y aura une invite, qui indique que le programme demande une entrée.

  • Si vous n'êtes pas sûr, vous pouvez vérifier si le processus du programme est occupé

    • utilise le processeur - utilisez topouhtop

    • lit ou écrit - utilisez sudo iotop -o

  • Et lorsque le programme sera terminé, vous verrez l'invite du shell.

Shellscript running

J'avais un shellscript qui vérifie si un programme est en cours d'exécution, et maintenant j'ai ajouté l'option -spour le faire fonctionner sudo strace -f -p <PID>(selon la réponse de Sergiy Kolodyazhnyy) lorsqu'un ... est trouvé.

Le shellscript utilise

  • ps -ef pour trouver la majorité des programmes
  • systemctl is-active --quiet trouver des programmes
  • et si vous le souhaitez stracedans une xtermfenêtre.

    Installez xtermsi vous souhaitez utiliser stracepour regarder l'activité d'un programme.

Usage

$ ./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

Vous pouvez installer le shellscript runningdans un répertoire de PATHsi vous souhaitez y accéder facilement.

Le code 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"

Démo

Vérification des fenêtres de terminal à Lubuntu (LXTerminal démarré en tant x-terminal-emulatorque gnome-terminalfenêtres personnalisées ),

$ 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

Il y a beaucoup d'activité dès que le curseur est dans la fenêtre du terminal.

entrez la description de l'image ici

Démarrage grep(en attente de l'entrée de /dev/stdin)

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

Le vérifier

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

Il n'y a pas beaucoup d'activité et vous pouvez identifier ce qui se passe.

entrez la description de l'image ici

sudodus
la source
Bonne mention iotop, bien que l'utilisation du processeur ne soit pas nécessairement un indicateur si un processus est occupé. Un programme écrit en C et optimisé peut utiliser un minimum de CPU. Certains des indicateurs que j'ai écrits en Python planifient une tâche répétée à exécuter, il peut donc utiliser le processeur pour mettre à jour le menu des indicateurs pendant un bref instant, puis rester là.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy, Oui, vous avez raison. La straceméthode est meilleure, mais peut-être pas nécessaire ou non disponible.
sudodus
D'accord. Je ne pense pas qu'il soit préinstallé avec Ubuntu et pourrait être exagéré.
Sergiy Kolodyazhnyy
1

Je ne sais pas si vous en avez toujours besoin, mais c'est une astuce utile à savoir: si le programme semble se terminer sans sortie, vous pouvez vérifier s'il s'exécute en arrière-plan en exécutant

ps -efa | grep "program_name"

À votre santé!

Marcel Ferrari
la source
1

Si vous exécutez le shell dans un terminal, par exemple un émulateur de terminal ou une session ssh typique, votre shell a presque certainement activé le contrôle des travaux. Cela rend la réponse à votre question très facile dans la plupart des cas.

Tapez Ctrl+Zpour suspendre le processus, puis bgpour le poursuivre en arrière-plan, puis tapez une ligne vide dans le shell pour qu'il vérifie si le programme a été arrêté par un signal.

Si le processus tente de lire à partir du terminal, il recevra immédiatement un SIGTTINsignal et sera suspendu. (Lorsque le contrôle des travaux est activé, le système autorise un seul processus à la fois à lire à partir du terminal.) Le shell le signale. Vous pouvez ensuite taper fgpour continuer le processus au premier plan, puis taper l'entrée à lire par le programme comme d'habitude.

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

Certains programmes, tels que les éditeurs, piègent ou ignorent le signal généré par Ctrl+Zou mettent le terminal dans un mode où les caractères de contrôle ne génèrent même pas de signaux. Vous aurez besoin d'utiliser des techniques plus avancées dans ce cas, comme l' utilisation stracede voir si le processus est en train de faire read, select, poll, etc.

Mark Plotnick
la source