Как мне узнать, выполняется команда или ожидает ввода пользователя?

14

В командной строке я набрал команду и нажал ввод. Это ничего не выводит. Как мне узнать, запущен ли он и еще не выводится, или он запрашивает ввод пользователя?

Gqqnbig
источник
Если он ждет, вы не получите PS1подсказку.
Prvt_Yadav
1. Пожалуйста, сообщите нам, что это за программа (она молчит), и мы можем дать вам более точный совет о том, чего ожидать и как его проверить; 2. Хотели бы вы получать оповещение, когда программа, наконец, запрашивает ввод или завершает работу (чтобы что-то записывалось в окно терминала?
sudodus
если ожидается ввод, я бы предположил, что вы получите подсказку с сообщением перед ним с просьбой о вводе.
Rinzwind
5
@Rinzwind - Это плохое предположение. Первый контрпример к уму - catкоманда. Просто наберите catсам, и он будет ждать ввода от стандартного ввода, но не дает подсказки. Многие другие команды ведут себя аналогично, потому что они ожидают ввода от стандартного ввода или файла, но не различают разные источники ввода (интерактивный терминал, канал, файл ...).
Дейв Шерохман

Ответы:

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

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

Shellscript 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

Там не так много активности, и вы можете определить, что происходит.

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

sudodus
источник
Хорошее упоминание iotop, хотя использование процессора не обязательно может быть индикатором, если процесс занят. Программа, написанная на C и оптимизированная, может использовать минимальный процессор. Некоторые из индикаторов, которые я написал в Python, планируют повторное выполнение задачи, поэтому он может использовать CPU, чтобы на короткое время обновить меню индикаторов, а затем просто сидеть там.
Сергей Колодяжный
@SergiyKolodyazhnyy, да, вы правы в этом. Этот straceметод лучше, но, возможно, не нужен или не доступен.
Судод
Согласовано. Я не думаю, что он предустановлен с 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и т.д.

Марк Плотник
источник