Como posso saber se um comando está em execução ou aguardando a entrada do usuário?

14

Na linha de comando, digitei um comando e pressione Enter. Não produz nada. Como posso saber se está em execução e ainda não está em exibição ou se está solicitando a entrada do usuário?

Gqqnbig
fonte
Se estiver aguardando, você não será PS1avisado.
Prvt_Yadav 14/02/19
1. Diga-nos qual é o programa (silencioso) e podemos dar conselhos mais precisos sobre o que esperar e como verificá-lo; 2. Gostaria de receber um alerta, quando o programa finalmente pede para entrada ou tenha terminado (de modo que algo é escrito para a janela de terminal?
sudodus
se houver uma entrada esperada, eu assumiria que você recebe uma solicitação com uma mensagem na frente solicitando entrada.
Rinzwind 14/02/19
5
@Rinzwind - Essa é uma suposição ruim. Primeiro contra-exemplo à mente é o catcomando. Basta digitar catsozinho e ele aguardará a entrada de stdin, mas não fornecerá nenhum prompt. Muitos outros comandos se comportam da mesma forma porque esperam entrada do stdin ou de um arquivo, mas não diferenciam entre diferentes fontes de entrada (terminal interativo, canal, arquivo ...).
Dave Sherohman 14/02/19

Respostas:

15

Existem várias abordagens:

  1. Tente sinalizar o fim da entrada : sem privilégios de superusuário, é difícil saber o que está acontecendo sob o capô. O que pode ser feito é pressionar Ctrl+ d. Terminais e utilitários no modo canônico enviam todo o texto disponível para read()syscall ao receber o sinal EOT vinculado a essa combinação de teclas e, se não houver entrada - read()retorna o status de saída negativo que a maioria dos utilitários aceita como sinal de saída. Portanto, se um utilitário estiver aguardando a entrada, ele sairá ao receber a combinação de teclas. Caso contrário, o utilitário está executando tarefas ou não foi gravado corretamente.

  2. Espionando syscalls : se você tiver privilégios de superusuário, poderá executar straceem outro terminal para ver o que está sendo feito no momento. Para isso, você precisa descobrir o PID do programa. Por exemplo, em outra guia do terminal, execute pgrep -f firefox1234 como exemplo e depois sudo strace -f -p 1234. Se a saída que você vê está presa no read()syscall, significa que o comando provavelmente está aguardando a entrada. Caso contrário, se você vir os syscalls sendo executados, o comando estará fazendo outra coisa. Consulte uma pergunta relacionada para o uso de stracepara descobrir também se o comando de execução longa saiu.

  3. Use os próprios métodos do comando : Entre outras coisas, utilitários como ddsinais de uso. Por exemplo, se você usar kill -USR1 1234(em que 1234 é o PID do ddcomando em execução ), ele será impresso para indicar a quantidade de bytes processados ​​atualmente. Obviamente, isso requer conhecimento sobre esse comportamento do comando em primeiro lugar. Os dois métodos acima são mais gerais e não exigem conhecimento profundo do comportamento de cada comando (embora seja sempre melhor saber o que você está realmente executando - caso contrário, você corre o risco de executar um comando que pode causar danos).

Sergiy Kolodyazhnyy
fonte
+1. Obrigado pelo stracemétodo :-) Mas métodos mais simples também são úteis (gerais ou específicos para cada programa). Alguns deles funcionam sem privilégios de superusuário. Exemplos: verifique se ddestá fazendo algo e verifique por que grep --color asdfestá esperando silenciosamente.
sudodus 14/02/19
@sudodus Ah, bom lembrete sobre ddeu vou adicionar esse.
Sergiy Kolodyazhnyy
Você não precisa de privilégios de superusuário para depurar um processo de propriedade do seu usuário. Bem, a menos que você não tenha configurado o sistema adequadamente .
Ruslan
6

Como saber se um programa está sendo executado ou deseja entrada do usuário

Depende do programa e como você o invoca.

  • Freqüentemente, mas nem sempre, haverá um prompt, indicando que o programa está solicitando entrada.

  • Se você não tiver certeza, pode verificar se o processo do programa está ocupado

    • usa CPU - use topouhtop

    • lê ou escreve - use sudo iotop -o

  • E quando o programa terminar, você verá o prompt do shell.

Shellscript running

Eu tinha um shellscript que verifica se um programa está sendo executado e agora adicionei a opção -sde executá-lo sudo strace -f -p <PID>(de acordo com a resposta de Sergiy Kolodyazhnyy) quando um ... é encontrado.

O shellscript usa

  • ps -ef para encontrar a maioria dos programas
  • systemctl is-active --quiet para encontrar alguns programas
  • e se você desejar straceem uma xtermjanela.

    Instale xtermse você deseja usar stracepara assistir à atividade de um programa.

Uso

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

Você pode instalar o shellscript runningem um diretório, PATHse desejar acesso fácil a ele.

O código do 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"

Demo

Verificando as janelas do terminal no Lubuntu (o LXTerminal foi iniciado como x-terminal-emulatore as gnome-terminaljanelas personalizadas ),

$ 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

muita atividade assim que o cursor está na janela do terminal.

insira a descrição da imagem aqui

Iniciando grep(aguardando entrada de /dev/stdin)

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

Verificando

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

Não há muita atividade e você pode identificar o que está acontecendo.

insira a descrição da imagem aqui

sudodus
fonte
Boa menção iotop, embora o uso da CPU possa não ser necessariamente um indicador se um processo estiver ocupado. Um programa escrito em C e otimizado pode estar usando CPU mínima. Alguns dos indicadores que eu escrevi no Python agendam uma tarefa repetida para execução, portanto, ele pode usar a CPU para atualizar o menu do indicador por um breve momento e então fica lá.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy, Sim, você está certo sobre isso. O stracemétodo é melhor, mas talvez não seja necessário ou não esteja disponível.
sudodus 14/02/19
Acordado. Eu não acho que ele vem pré-instalado com o Ubuntu e pode ser um exagero.
Sergiy Kolodyazhnyy
1

Não tenho certeza se você ainda precisa disso, mas ainda é um truque útil para saber: se o programa parece sair sem nenhuma saída, você pode verificar se está executando em segundo plano executando

ps -efa | grep "program_name"

Felicidades!

Marcel Ferrari
fonte
1

Se você estiver executando o shell em um terminal, por exemplo, um emulador de terminal ou uma sessão ssh típica, seu shell quase certamente ativou o controle de tarefas. Isso facilita muito a obtenção de uma resposta para sua pergunta na maioria dos casos.

Digite Ctrl+Zpara suspender o processo e, em seguida, bgcontinue em segundo plano, digite uma linha vazia no shell para verificar se o programa foi interrompido por um sinal.

Se o processo estiver tentando ler no terminal, ele receberá imediatamente um SIGTTINsinal e será suspenso. (Quando o controle de trabalho está ativado, o sistema permite a leitura de apenas um processo de cada vez no terminal.) O shell relatará isso. Você pode digitar fgpara continuar o processo em primeiro plano e digitar a entrada a ser lida pelo programa normalmente.

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

Alguns programas, como editores, capturam ou ignoram o sinal gerado por Ctrl+Zou colocam o terminal em um modo em que os caracteres de controle nem geram sinais. Você vai precisar usar técnicas mais avançadas neste caso, como o uso stracepara ver se o processo está fazendo read, select, poll, etc.

Mark Plotnick
fonte