Jak sprawdzić, czy polecenie jest uruchomione, czy czeka na dane wprowadzone przez użytkownika?

14

W wierszu poleceń wpisałem polecenie i wcisnąłem Enter. Nic nie wyprowadza. Skąd mam wiedzieć, czy jest uruchomiony i nie jest jeszcze generowany, czy prosi użytkownika o podanie danych?

Gqqnbig
źródło
Jeśli czeka, nie pojawi się PS1monit.
Prvt_Yadav
1. Powiedz nam, który to program (jest cichy), a my możemy dać ci dokładniejsze porady na temat tego, czego się spodziewać i jak to sprawdzić; 2. Czy chcesz otrzymać alert, gdy program w końcu poprosi o dane wejściowe lub zakończy działanie (aby coś zapisano w oknie terminala?
sudodus
jeśli oczekuje się danych wejściowych, zakładam, że pojawi się monit z komunikatem przed nimi.
Rinzwind
5
@Rinzwind - To złe założenie. Pierwszym kontrprzykładem na myśl jest catpolecenie. Po prostu wpisz catsam i poczeka na dane wejściowe ze standardowego wejścia, ale nie wyświetli monitu. Wiele innych poleceń zachowuje się podobnie, ponieważ oczekują danych wejściowych od standardowego lub pliku, ale nie rozróżniają różnych źródeł wejściowych (terminal interaktywny, potok, plik ...).
Dave Sherohman

Odpowiedzi:

15

Istnieje kilka podejść:

  1. Spróbuj zasygnalizować koniec wejścia : Bez uprawnień administratora bardzo trudno jest wiedzieć, co dzieje się pod maską. Można nacisnąć Ctrl+ d. Terminale i narzędzia w trybie kanonicznym wysyłają cały dostępny tekst do read()syscall po otrzymaniu sygnału EOT związanego z tą kombinacją klawiszy, a jeśli nie ma wejścia - read()zwraca ujemny status wyjścia, który większość narzędzi przyjmuje jako sygnał do wyjścia. Dlatego jeśli narzędzie czeka na dane wejściowe, zakończy działanie po otrzymaniu kombinacji klawiszy. W przeciwnym razie narzędzie uruchomi zadania lub nie zostanie poprawnie zapisane.

  2. Szpiegowanie połączeń syscall : jeśli masz uprawnienia administratora, możesz uruchomić stracew innym terminalu, aby zobaczyć, co jest aktualnie wykonywane. W tym celu musisz znaleźć PID programu. Na przykład w innej zakładce terminala uruchom, pgrep -f firefoxktóra może 1234 jako przykład, a następnie sudo strace -f -p 1234. Jeśli wyjście, które widzisz, utknęło w read()syscall, oznacza to, że polecenie prawdopodobnie czeka na wejście. W przeciwnym razie, jeśli widzisz uruchamiane syscalls, polecenie robi coś innego. Zobacz powiązane pytanie do wykorzystania stracerównież dowiedzieć się, czy polecenie długo uruchomiony został zakończony.

  3. Używaj własnych metod polecenia : między innymi takich narzędzi, jak ddużycie sygnałów. Na przykład, jeśli użyjesz kill -USR1 1234(gdzie 1234 jest PID uruchomionej ddkomendy), to wypisuje na standardowe wyjście ilość aktualnie przetwarzanych bajtów. Oczywiście wymaga to przede wszystkim wiedzy o takim zachowaniu polecenia. Powyższe dwie metody są bardziej ogólne i nie wymagają dogłębnej znajomości zachowania każdego polecenia (chociaż zawsze najlepiej wiedzieć, co faktycznie wykonujesz - w przeciwnym razie ryzykujesz wykonanie polecenia, które może spowodować obrażenia).

Sergiy Kolodyazhnyy
źródło
+1. Dzięki za stracemetodę :-) Przydają się również prostsze metody (ogólne lub specyficzne dla każdego programu). Niektóre z nich działają bez uprawnień administratora. Przykłady: sprawdź, czy ddcoś robi i sprawdź, dlaczego grep --color asdfczeka w ciszy.
sudodus
@sudodus Ah, dobre przypomnienie o dddodaniu tego.
Sergiy Kolodyazhnyy
Nie potrzebujesz uprawnień administratora do debugowania procesu należącego do użytkownika. Cóż, chyba że system nie został odpowiednio skonfigurowany .
Ruslan
6

Jak stwierdzić, czy program jest uruchomiony, czy chce danych wejściowych od użytkownika

To zależy od programu i sposobu jego wywołania.

  • Często, ale nie zawsze, pojawi się monit, który wskazuje, że program prosi o dane wejściowe.

  • Jeśli nie masz pewności, możesz sprawdzić, czy proces programu jest zajęty

    • używa procesora - użyj toplubhtop

    • czyta lub pisze - użyj sudo iotop -o

  • A kiedy program się zakończy, zobaczysz monit powłoki.

Skrypt powłoki running

Miałem skrypt powłoki, który sprawdza, czy program działa, a teraz dodałem opcję -suruchomienia go sudo strace -f -p <PID>(zgodnie z odpowiedzią Sergiy Kolodyazhnyy) po znalezieniu ...

Używa skryptu

  • ps -ef znaleźć większość programów
  • systemctl is-active --quiet znaleźć jakieś programy
  • a jeśli chcesz stracew xtermoknie.

    Zainstaluj, xtermjeśli chcesz użyć stracedo oglądania aktywności programu.

Stosowanie

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

Możesz zainstalować skrypt shellscript runningw katalogu, PATHjeśli chcesz mieć do niego łatwy dostęp.

Kod 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"

Próbny

Sprawdzanie okien terminali w Lubuntu (LXTerminal uruchomił się jako x-terminal-emulatori niestandardowe gnome-terminalokna),

$ 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

Gdy kursor znajdzie się w oknie terminala, jest dużo aktywności.

wprowadź opis zdjęcia tutaj

Uruchamianie grep(oczekiwanie na dane wejściowe z /dev/stdin)

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

Sprawdzam to

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

Aktywność jest niewielka i możesz zidentyfikować, co się dzieje.

wprowadź opis zdjęcia tutaj

sudodus
źródło
Dobra wzmianka o tym iotop, chociaż użycie procesora niekoniecznie musi być wskaźnikiem, jeśli proces jest zajęty. Program napisany w C i zoptymalizowany może używać minimalnego procesora. Niektóre wskaźniki, które napisałem w Pythonie, planują uruchomienie powtarzanego zadania, więc może użyć CPU do aktualizacji menu wskaźników na chwilę, a następnie po prostu tam siedzi.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy, Tak, masz rację. straceMetoda jest lepsza, ale może nie jest konieczne lub nie jest dostępna.
sudodus
Zgoda. Nie sądzę, że jest fabrycznie zainstalowany z Ubuntu i może być przesadą.
Sergiy Kolodyazhnyy
1

Nie jestem pewien, czy nadal tego potrzebujesz, ale wciąż przydatna sztuczka: jeśli program wydaje się wychodzić bez żadnego wyjścia, możesz sprawdzić, czy działa w tle, wykonując

ps -efa | grep "program_name"

Twoje zdrowie!

Marcel Ferrari
źródło
1

Jeśli uruchamiasz powłokę w terminalu, na przykład emulatorze terminala lub typowej sesji ssh, powłoka prawie na pewno włączyła kontrolę zadań. To sprawia, że ​​w większości przypadków uzyskanie odpowiedzi na twoje pytanie jest bardzo łatwe.

Wpisz, Ctrl+Zaby zawiesić proces, a następnie bgkontynuować w tle, a następnie wpisz pustą linię do powłoki, aby sprawdzić, czy program został zatrzymany przez sygnał.

Jeśli proces próbuje odczytać z terminala, natychmiast otrzyma SIGTTINsygnał i zostanie zawieszony. (Gdy kontrola zadań jest włączona, system zezwala tylko na jeden proces do odczytu z terminala). Powłoka to zgłosi. Następnie możesz wpisać, fgaby kontynuować proces na pierwszym planie, a następnie wpisać dane wejściowe do odczytania przez program w normalny sposób.

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

Niektóre programy, takie jak edytory, wychwytują lub ignorują sygnał generowany przez Ctrl+Zlub wprowadzają terminal w tryb, w którym znaki sterujące nawet nie generują sygnałów. Trzeba korzystać z bardziej zaawansowanych technik, w tym przypadku, takie jak wykorzystanie straceaby sprawdzić, czy proces robi read, select, poll, itd.

Mark Plotnick
źródło