Как мне узнать, выполняется команда или ожидает ввода пользователя?
В командной строке я набрал команду и нажал ввод. Это ничего не выводит. Как мне узнать, запущен ли он и еще не выводится, или он запрашивает ввод пользователя?
4 ответа
Есть несколько подходов:
Попробуйте сигнализировать о конце ввода: без привилегий суперпользователя трудно понять, что происходит под капотом. Что можно сделать, это нажать Ctrl+d. Терминалы и утилиты в каноническом режиме отправляют весь доступный текст
read()системный вызов при получении сигнала EOT, связанного с этой комбинацией клавиш, и если нет ввода -read()возвращает отрицательный статус выхода, который большинство утилит принимают в качестве сигнала на выход. Поэтому, если утилита ожидает ввода, она выйдет при получении комбинации клавиш. В противном случае утилита либо выполняет задачи, либо написана неправильно.Следите за системными вызовами: если у вас есть привилегия суперпользователя, вы можете запустить
straceв другом терминале, чтобы увидеть, что в настоящее время делается. Для этого вам нужно узнать PID программы. Например, в другой вкладке терминала запуститьpgrep -f firefoxкоторый может 1234 в качестве примера, а затемsudo strace -f -p 1234, Если вывод, который вы видите, застрял наread()syscall, это означает, что команда, вероятно, ожидает ввода. В противном случае, если вы видите запущенные системные вызовы, тогда команда делает что-то еще. Смотрите связанный вопрос для использованияstraceтакже выяснить, вышла ли длительная команда.Используйте собственные методы команды: среди прочего, такие утилиты, как
ddиспользовать сигналы. Например, если вы используетеkill -USR1 1234(где 1234 - PID работающегоddкоманда), он выведет на вывод количество обработанных байтов. Конечно, для этого необходимо знать, прежде всего, о таком поведении команды. Вышеупомянутые два метода являются более общими и не требуют глубоких знаний о поведении каждой команды (хотя всегда лучше знать, что вы на самом деле выполняете - в противном случае вы рискуете выполнить команду, которая может нанести ущерб).
Как определить, запущена ли программа или требуется ввод пользователя
Это зависит от программы и от того, как вы ее вызываете.
Часто, но не всегда, появляется подсказка, указывающая, что программа запрашивает ввод.
Если вы не уверены, можете проверить, занят ли процесс программы
использует процессор - использовать
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
Там не так много активности, и вы можете определить, что происходит.
Если вы запускаете оболочку в терминале, например, в эмуляторе терминала или в типичном сеансе 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, так далее.
Не уверен, что вам все еще нужно это, но все же полезный трюк, чтобы знать: если кажется, что программа завершает работу без вывода, вы можете проверить, работает ли она в фоновом режиме, выполнив
ps -efa | grep "program_name"
Ура!
Почему бы просто не взглянуть на столбец S (Состояние) верхней команды. Если ваша программа ожидает ввода, велика вероятность, что она спит, а не запущена, что означает, что top выведет S (на этот раз для сна), а не R (для выполнения). Попробуйте эту команду в качестве примера:
top -b -n 1 | sed -n '7,12p' | awk '{printf "%6s %-10s %-4s %-s\n",$1,$2,$8,$NF}'
