Як дізнатись, чи працює команда чи чекає введення користувача?


14

У командному рядку я набрав команду і натиснув клавішу enter. Це нічого не виводить. Як я можу дізнатися, чи працює він і ще не виводиться, або він запитує користувача?


Якщо він чекає, то ви не отримаєте PS1підказки.
Prvt_Yadav

1. Скажіть, будь ласка, про яку програму йде мова (що мовчить), і ми можемо дати точніші поради щодо того, чого очікувати та як її перевірити; 2. Чи хотіли б ви отримати сповіщення, коли програма нарешті запитує введення або закінчиться (щоб щось було записано у вікно терміналу?
sudodus

якщо очікується введення, я б припустив, що ви отримаєте запит із повідомленням перед ним із проханням ввести.
Rinzwind

5
@Rinzwind - Це погане припущення. Перший контрприклад на думку - це catкоманда. Просто введіть catсам, і він буде чекати введення від stdin, але не дає підказки. Багато інших команд поводяться аналогічно, тому що вони очікують введення або stdin, або файлу, але не розрізняють різні джерела введення (інтерактивний термінал, труба, файл ...).
Дейв Шерохман

Відповіді:


15

Є кілька підходів:

  1. Спробуйте сигналізувати кінець введення : Без привілеїв суперпользователя важко дізнатися, що відбувається під капотом. Що можна зробити, це натиснути Ctrl+ d. Термінали та утиліти в канонічному режимі надсилають весь доступний текст до read()системного виклику після отримання сигналу EOT, пов'язаного з цією комбінацією клавіш, а якщо немає вводу - read()повертає негативний статус виходу, який більшість утилітів приймає як сигнал для виходу. Тому, якщо утиліта чекає на вхід, вона вийде після отримання комбінації клавіш. В іншому випадку утиліта або виконує завдання, або записана неправильно.

  2. Шпигунство на системних дзвінках : Якщо у вас є привілей суперпользователя, ви можете запустити straceв інший термінал, щоб побачити, що зараз робиться. Для цього потрібно з’ясувати PID програми. Наприклад, в іншій вкладці термінала запустіть, pgrep -f firefoxяка може бути, наприклад, 1234 sudo strace -f -p 1234. Якщо вихід, який ви бачите, застряг на read()системному виклику, це означає, що команда, ймовірно, чекає на введення. В іншому випадку, якщо ви бачите системні виклики, що виконується, команда робить щось інше. Дивіться пов’язане питання щодо використання, straceщоб також з’ясувати, чи тривала команда, що триває.

  3. Використовуйте власні методи команди : Крім усього іншого, такі утиліти, як ddвикористання сигналів. Наприклад, якщо ви використовуєте kill -USR1 1234(де 1234 є PID запущеної ddкоманди), він надрукує для викреслення кількості оброблених байтів. Звичайно, для цього потрібно знати в першу чергу про таку поведінку команди. Зазначені вище методи є загальнішими і не потребують глибокого знання поведінки кожної команди (хоча завжди краще знати, що ви насправді виконуєте - інакше ви ризикуєте виконати команду, яка може завдати шкоди).


+1. Дякую за straceметод :-) Але простіші методи також корисні (загальні або специфічні для кожної програми). Деякі з них працюють без пільг суперпользователя. Приклади: перевірити, чи ddщось робить, і перевірити, чому grep --color asdfчекає мовчки.
sudodus

@sudodus Ага, гарне нагадування про те, що ddя додам це.
Сергій Колодяжний

Для налагодження процесу, що належить вашому користувачеві, вам не потрібні привілеї суперпользователя. Ну, якщо ви не встановили систему належним чином .
Руслан

6

Як визначити, чи працює програма чи бажає ввести користувача

Це залежить від програми та способу її виклику.

  • Часто, але не завжди, з'явиться підказка, що вказує на те, що програма просить ввести.

  • Якщо ви не впевнені, можете перевірити, чи зайнятий процес програми

    • використовує процесор - використовувати topабоhtop

    • читає чи пише - користуйся sudo iotop -o

  • І коли програма закінчиться, ви побачите підказку оболонки.

Оболонка running

У мене був оболонка, яка перевіряє, чи працює програма, і тепер я додав можливість -sзапустити її sudo strace -f -p <PID>(згідно відповіді Сергія Колодяжного), коли буде знайдено ...

Оболонка використовує

  • ps -ef щоб знайти більшість програм
  • systemctl is-active --quiet щоб знайти деякі програми
  • і якщо ви хочете straceу xtermвікні.

    Встановіть, xtermякщо ви хочете використовувати straceдля перегляду активності програми.

Використання

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

Ви можете встановити оболонку оболонки runningв каталог, PATHякщо ви хочете легкий доступ до неї.

Код оболонки

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

Демо

Перевірка вікон терміналів у Lubuntu (LXTerminal запускався як x-terminal-emulatorі власні gnome-terminalвікна),

$ 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

Як тільки курсор знаходиться у вікні терміналу, відбувається велика активність.

введіть тут опис зображення

Початок grep(очікування введення з /dev/stdin)

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

Перевіряючи це

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

Активності не так багато, і ви можете визначити, що відбувається.

введіть тут опис зображення


iotopХоча згадати , хоча використання процесора може не обов'язково бути показником, якщо процес зайнятий. Програма, написана на С та оптимізована, може використовувати мінімальний процесор. Деякі з індикаторів, які я записав у Python, планують запустити повторне завдання, тому він може використовувати CPU для оновлення меню індикаторів на короткий момент, а потім просто сидить там.
Сергій Колодяжний

@SergiyKolodyazhnyy, Так, ви маєте рацію з цього приводу. straceМетод краще, але , можливо , не потрібен чи ні в наявності.
sudodus

Домовились. Я не думаю, що він попередньо встановлений з Ubuntu, і може бути зайвим.
Сергій Колодяжний

1

Не впевнений, чи потрібно вам це все-таки, але все ж корисний трюк, щоб знати: якщо програма, здається, виходить без жодного виводу, ви можете перевірити, чи працює вона у фоновому режимі, виконавши

ps -efa | grep "program_name"

Ура!


1

Якщо ви запускаєте оболонку в терміналі, наприклад, емуляторі терміналу або типовому сеансі ssh, ваша оболонка майже напевно включила контроль роботи. У більшості випадків це дуже легко отримати відповідь на ваше запитання.

Введіть, Ctrl+Zщоб призупинити процес, а потім bgпродовжити його у фоновому режимі, а потім введіть порожній рядок у оболонку, щоб він перевірив, чи зупинилась програма сигналом.

Якщо процес намагається прочитати з терміналу, він негайно отримає SIGTTINсигнал і зупиниться. (Коли ввімкнено контроль за роботою, система дозволяє одночасно зчитувати з терміналу лише один процес.) Оболонка повідомить про це. Потім ви можете ввести, fgщоб продовжити процес на передньому плані, а потім наберіть введення, щоб прочитати програму як звичайне.

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

Деякі програми, такі як редактори, або захоплюють або ігнорують сигнал, що генерується, Ctrl+Zабо переводять термінал у режим, коли символи управління навіть не генерують сигнали. Ви повинні будете використовувати більш складні методи , в цьому випадку, наприклад, з використанням , straceщоб побачити , якщо процес робить read, select, pollі т.д.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.