Wie kann ich feststellen, ob ein Befehl ausgeführt wird oder auf Benutzereingaben wartet?

14

In der Befehlszeile habe ich einen Befehl eingegeben und die Eingabetaste gedrückt. Es wird nichts ausgegeben. Wie kann ich feststellen, ob es ausgeführt wird und noch nicht ausgegeben wurde oder ob eine Benutzereingabe erforderlich ist?

Gqqnbig
quelle
Wenn es wartet, erhalten Sie keine PS1Eingabeaufforderung.
Prvt_Yadav
1. Sagen Sie uns bitte, um welches Programm es sich handelt (das ist still), und wir können Ihnen genauere Ratschläge darüber geben, was Sie erwarten und wie Sie es überprüfen können. 2. Möchten Sie benachrichtigt werden, wenn das Programm endlich nach Eingaben fragt oder fertig ist (damit etwas in das Terminalfenster geschrieben wird?
sudodus
Wenn eine Eingabe erwartet wird, gehe ich davon aus, dass Sie eine Eingabeaufforderung mit einer Nachricht davor erhalten, in der Sie um Eingabe gebeten werden.
Rinzwind
5
@Rinzwind - Das ist eine schlechte Annahme. Das erste Gegenbeispiel ist der catBefehl. Tippe einfach catvon selbst und es wartet auf die Eingabe von stdin, gibt aber keine Aufforderung. Viele andere Befehle verhalten sich ähnlich, da sie Eingaben von stdin oder einer Datei erwarten, jedoch nicht zwischen verschiedenen Eingabequellen (interaktives Terminal, Pipe, Datei ...) unterscheiden.
Dave Sherohman

Antworten:

15

Es gibt verschiedene Ansätze:

  1. Versuchen Sie, das Ende der Eingabe zu signalisieren : Ohne Superuser-Berechtigungen ist es schwierig zu wissen, was unter der Haube vor sich geht. Was getan werden kann, ist, Ctrl+ zu drücken d. Terminals und Dienstprogramme im kanonischen Modus senden read()beim Empfang des an diese Tastenkombination gebundenen EOT-Signals den gesamten verfügbaren Text an syscall. Wenn keine Eingabe vorhanden ist, wird ein read()negativer Beendigungsstatus zurückgegeben, den die meisten Dienstprogramme als Beendigungssignal akzeptieren. Wenn ein Dienstprogramm auf eine Eingabe wartet, wird es daher nach Erhalt der Tastenkombination beendet. Andernfalls führt das Dienstprogramm entweder Aufgaben aus oder ist nicht richtig geschrieben.

  2. Ausspionieren von Syscalls : Wenn Sie über Superuser-Berechtigungen verfügen, können Sie stracein einem anderen Terminal nachsehen , was gerade ausgeführt wird. Dazu müssen Sie die PID des Programms herausfinden. Zum Beispiel in einem anderen Terminal-Tab ausführen, pgrep -f firefoxder 1234 als Beispiel und dann kann sudo strace -f -p 1234. Wenn die read()angezeigte Ausgabe bei syscall hängen bleibt , bedeutet dies, dass der Befehl wahrscheinlich auf die Eingabe wartet. Andernfalls führt der Befehl etwas anderes aus, wenn Syscalls vorbeirennen. Lesen Sie eine verwandte Frage für die Verwendung von, straceum auch herauszufinden, ob der Befehl für lange Ausführung beendet wurde.

  3. Verwenden Sie die eigenen Methoden des Befehls : Unter anderem Dienstprogramme wie dduse signals. Wenn Sie beispielsweise verwenden kill -USR1 1234(wobei 1234 die PID des ausgeführten ddBefehls ist), wird die Anzahl der aktuell verarbeiteten Bytes ausgegeben. Dies setzt natürlich voraus, dass man überhaupt über ein solches Verhalten des Befehls Bescheid weiß. Die beiden oben genannten Methoden sind allgemeiner und erfordern keine umfassenden Kenntnisse des Verhaltens der einzelnen Befehle (obwohl es immer am besten ist, zu wissen, was Sie tatsächlich ausführen - andernfalls besteht die Gefahr, dass Sie einen Befehl ausführen, der Schaden anrichtet).

Sergiy Kolodyazhnyy
quelle
+1. Danke für die straceMethode :-) Aber auch einfachere Methoden sind nützlich (allgemein oder spezifisch für jedes Programm). Einige von ihnen funktionieren ohne Superuser-Rechte. Beispiele: Überprüfen Sie, ob ddetwas unternommen wird, und überprüfen Sie, warum grep --color asdfstill gewartet wird.
Sudodus
@sudodus Ah, gute Erinnerung daran dd, dass ich das hinzufügen werde.
Sergiy Kolodyazhnyy
Sie benötigen keine Superuser-Berechtigungen, um einen Prozess zu debuggen, der Ihrem Benutzer gehört. Nun, es sei denn, Sie haben das System nicht ordnungsgemäß eingerichtet .
Ruslan
6

Feststellen, ob ein Programm ausgeführt wird oder Benutzereingaben benötigt

Es hängt vom Programm ab und davon, wie Sie es aufrufen.

  • Oft, aber nicht immer, wird eine Eingabeaufforderung angezeigt, die darauf hinweist, dass das Programm Eingaben anfordert.

  • Wenn Sie sich nicht sicher sind, können Sie überprüfen, ob der Programmprozess beschäftigt ist

    • verwendet CPU - Verwendung topoderhtop

    • liest oder schreibt - verwenden sudo iotop -o

  • Und wenn das Programm beendet ist, sehen Sie die Eingabeaufforderung der Shell.

Shell-Skript running

Ich hatte ein Shellscript, das prüft, ob ein Programm ausgeführt wird, und jetzt habe ich die Option hinzugefügt -s, dass es ausgeführt wird sudo strace -f -p <PID>(gemäß der Antwort von Sergiy Kolodyazhnyy), wenn ein ... gefunden wird.

Das Shellscript verwendet

  • ps -ef die Mehrheit der Programme zu finden
  • systemctl is-active --quiet um einige Programme zu finden
  • und wenn du willst stracein einem xtermfenster.

    Installieren xtermSie diese Option, wenn Sie stracedie Aktivität eines Programms verfolgen möchten .

Verwendung

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

Sie können das Shellscript runningin einem Verzeichnis installieren, in dem PATHSie einfach darauf zugreifen können.

Der Shellscript-Code

#!/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"

Demo

Terminalfenster in Lubuntu überprüfen (LXTerminal gestartet als x-terminal-emulatorund benutzerdefinierte gnome-terminalFenster),

$ 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

Sobald sich der Cursor im Terminalfenster befindet, ist viel los.

Bildbeschreibung hier eingeben

Starten grep(Warten auf Eingabe von /dev/stdin)

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

Ich überprüfe es

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

Es gibt nicht viel Aktivität und Sie können feststellen, was gerade passiert.

Bildbeschreibung hier eingeben

Sudodus
quelle
Gute Erwähnung iotop, obwohl die CPU-Auslastung nicht unbedingt ein Indikator dafür ist, ob ein Prozess beschäftigt ist. Ein in C geschriebenes und optimiertes Programm benötigt möglicherweise nur minimale CPU. Einige der Indikatoren, die ich in Python geschrieben habe, planen die Ausführung einer wiederholten Task, sodass das Indikatormenü möglicherweise für einen kurzen Moment über die CPU aktualisiert wird und sich dann einfach dort befindet.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy, Ja, da hast du recht. Die straceMethode ist besser, aber möglicherweise nicht notwendig oder nicht verfügbar.
Sudodus
Einverstanden. Ich glaube nicht, dass es mit Ubuntu vorinstalliert ist, und es könnte übertrieben sein.
Sergiy Kolodyazhnyy
1

Wir sind uns nicht sicher, ob Sie dies noch brauchen, aber es ist immer noch ein nützlicher Trick zu wissen: Wenn das Programm ohne Ausgabe zu beenden scheint, können Sie durch Ausführen prüfen, ob es im Hintergrund ausgeführt wird

ps -efa | grep "program_name"

Prost!

Marcel Ferrari
quelle
1

Wenn Sie die Shell in einem Terminal ausführen, z. B. einem Terminalemulator oder einer typischen SSH-Sitzung, hat Ihre Shell mit ziemlicher Sicherheit die Jobsteuerung aktiviert. Dadurch ist es in den meisten Fällen sehr einfach, eine Antwort auf Ihre Frage zu erhalten.

Geben Sie ein Ctrl+Z, um den Prozess anzuhalten, und bgsetzen Sie ihn im Hintergrund fort. Geben Sie anschließend eine leere Zeile in die Shell ein, um zu überprüfen, ob das Programm durch ein Signal angehalten wurde.

Wenn der Prozess versucht, vom Terminal zu lesen, erhält er sofort ein SIGTTINSignal und wird angehalten. (Wenn die Auftragssteuerung aktiviert ist, kann jeweils nur ein Prozess vom Terminal gelesen werden.) Die Shell meldet dies. Sie können dann eingeben fg, um den Vorgang im Vordergrund fortzusetzen, und anschließend die Eingabe eingeben, die vom Programm wie gewohnt gelesen werden soll.

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

Einige Programme, wie z. B. Editoren, fangen das vom Ctrl+ZTerminal erzeugte Signal ab oder ignorieren es oder versetzen das Terminal in einen Modus, in dem Steuerzeichen nicht einmal Signale erzeugen. Sie benötigen mehr fortgeschrittene Techniken in diesem Fall zu verwenden, wie die Verwendung , straceum zu sehen , ob der Prozess tut read, select, polletc.

Mark Plotnick
quelle