Posso fazer com que todos os comandos tenham feedback se eles funcionaram ou não?

11

Às vezes, quando eu executo comandos, ele não exibe uma saída, então não tenho certeza se eles funcionaram ou não. É possível fazer com que todos os comandos tenham feedback se eles foram executados corretamente ou não? Ou, no mínimo, para exibir o ID do feedback que eles executaram (corretamente ou não)

rajlego
fonte
6
A idéia geral é: nenhum feedback significa que funcionou.
Rinzwind 01/04
1
isso não é exatamente verdade. Por exemplo, cryptsetuppode , por padrão, pular algumas mensagens de erro. É uma coisa boa de ter $?no seu PS1. O próximo passo é adicionar a hora atual, bem como, sempre saber horários dos comandos;)
d33tah

Respostas:

11

(Acho que desde que você está postando no Ask Ubuntu , podemos assumir que você está falando sobre o shell padrão, ou seja, o Bash .)

Há uma resposta muito boa na pergunta Stack Overflow Em um script de shell: os comandos echo shell são executados (esta não é apenas uma solução específica do Ubuntu).

O que você precisa fazer é usar o comando set para ativar o detalhado ou o xtrace.

set -o

vai lhe dar uma lista de quais parâmetros atuais são mudou para on ou off .

set -v

ou a versão longa:

set -o verbose

vai virar detalhado ON .

Eu acho que o que você quer, na verdade, é xtrace. Isso não apenas ecoará todos os comandos executados, mas também expandirá os parâmetros e fornecerá mais feedback. Portanto, se eu fizer algo tolo como digitar 'oi' no terminal, receberei o eco do que digitei, bem como um relatório / rastreio do que o shell fez para tentar executar o comando 'oi' (veja a captura de tela abaixo) ):

Digite a descrição da imagem aqui

Para ativar o xtrace:

set -x

ou:

set -o xtrace

Para desativar esses parâmetros, você (contra-intuitivamente) chama os mesmos comandos, exceto com um símbolo de mais + em vez de um traço ou um símbolo de menos, portanto, por exemplo:

set +v

desativará o verbose da mesma forma:

set +x

desativará o xtrace .


Um guia detalhado sobre opções de shell está no Capítulo 33. Opções, Guia Avançado de Script de Bash .

Benjamin R
fonte
1
Mas como funciona quando o comando está correto? dá alguma saída? diga para o comando whoami >/dev/null.
Usuário registrado
Sim, é claro que sim, ecoa o que você digitou, além de quaisquer parâmetros adicionais envolvidos no comando que foram chamados silenciosamente ao invocar seu comando. Se você quer dizer, ele imprime "SUCESSO", então, infelizmente, não, a resposta de Avinash Raj fará isso.
Benjamin R
@ PeterMortensen, obrigado pelas boas edições sutis da minha resposta.
Benjamin R
13

Para verificar se algum comando funcionou com êxito ou não, você pode verificar o status de retorno , fornecido por $?, do comando anterior com:

echo $?

Um status de retorno 0significa que o comando foi concluído com êxito, enquanto uma saída diferente de zero ( código de erro ) significaria que foram encontrados alguns problemas ou que há um erro e a categoria pode ser conhecida no código de erro. Os códigos de erro do Linux / C são definidos em /usr/include/asm-generic/errno-base.he /usr/include/asm-generic/errno.h.

Também no bash, .bashrcdefine um alias alertque pode ser usado para notificar o status de conclusão. Você precisaria anexar o alias com o comando ou combinação de comandos desta forma:

some_command --some-switch; alert

Você pode anexar a seguinte linha de código ao seu ~/.bashrcarquivo para exibir o status de retorno do último comando executado.

# show the return code of last command executed
PS1='${debian_chroot:+($debian_chroot)}\u@\h(lst ret. $(echo $?) ):\w\$ '

(abra o arquivo ~/.bashrccom o editor de texto de sua escolha e copie a linha acima, cole-a no arquivo e salve. Inicie uma nova instância do terminal e você deverá tê-la em ação. Ou então, pode definir alguma função e usar com PS1como como ilustrado abaixo.)

uma pequena demonstração:

hash@precise(lst ret. 0 ):~$ ls -sh someFileThatsNotThere
ls: cannot access someFileThatsNotThere: No such file or directory
hash@precise(lst ret. 2 ):~$ 
hash@precise(lst ret. 2 ):~$ aCommandThatsNot
aCommandThatsNot: command not found
hash@precise(lst ret. 127 ):~$ 
hash@precise(lst ret. 127 ):~$ echo "you should get a lst ret. 0, I believe the system has echo installed :)"
you should get a lst ret. 0, I believe the system has echo installed :)
hash@precise(lst ret. 0 ):~$
hash@precise(lst ret. 0 ):~$ sudo touch /tmp/someTestFile
[sudo] password for hash: 
hash@precise(lst ret. 1 ):~$
hash@precise(lst ret. 1 ):~$ chown $USER:$USER /tmp/someTestFile 
chown: changing ownership of `/tmp/someTestFile': Operation not permitted

Apenas brincando com PS1:) ..um pouco mais,

function showRetStat {
## line1: initiliazing retStat with the return status of the previous command
retStat=$?
## line2: Left padding the return status with spaces. If you prefer the unpadded one, you can just replace
# $retStatFtd in the lines initializing noErrStr and errStr among other possible ways.
retStatFtd=$(sed -e :a -e 's/^.\{1,2\}$/ &/;ta' <<< $retStat)
## lines3&4: Setting the strings to display for a successful and unsuccessful run of previous command
# which we are going to display with the prompt string. Change the strings to display text of your
# choice like you may set noErrStr="yippie!" , errStr="oopsie!" in place of what they're now.
noErrStr="retStat "$retStatFtd" :: PASS ^_^"
errStr="retStat "$retStatFtd" :: FAIL x_x"
## line5: Applying the logic and display the proper string at the prompt. Space padded number i.e. retStatFtd, here,
# worked in the logic, originally I intended to use this for the display while retStat in the conditional
# check; you could make the function one statement less if you want to.
echo "$([ $retStatFtd = 0 ] && echo "$noErrStr" || echo "$errStr")"
}

## Combining the function showRetStat into the prompt string.
PS1='${debian_chroot:+($debian_chroot)}\u@\h($(showRetStat)):\w\$ '

(você pode modificar a função para torná-la mais sofisticada, algo como o @gronostaj faz em seu post.)

preciso
fonte
2
Eu realmente gosto da sua resposta expandida com exemplos. Tenho certeza de que o OP quer o xtrace, mas pessoalmente acho isso útil para depurar meus próprios programas de linha de comando e para entender melhor os outros.
Benjamin R
1
Eu sugeriria o valor de retorno preenchido à esquerda, para que ele sempre tenha o mesmo comprimento.
o0 '.
+1 para modificar PS1. Este é o uso que eu, com número vermelho em caso de erros, nada extra se último comando foi bem sucedido:\[\033[01;41;37m\]${?#0}\[\033[00;01;36m\] \u@\h:\w\[\033[00m\]\$
Carlos Campderrós
1
@rusty é que não há necessidade de ~/.bashrcarquivo de origem ?
Avinash Raj
2
Sim, modificar o PS1 é útil e muito flexível. Eu mostro um feliz ^_^pelo sucesso e um vermelho x_xpor qualquer outra coisa.
Izkata
5

Você pode alterar seu prompt de comando para exibir um sinal de visto verde quando o comando anterior sair com 0 e X vermelho caso contrário. O Arch Linux Wiki possui um bom código para adicionar ao seu bash.rc:

set_prompt () {
    Last_Command=$? # Must come first!
    Blue='\[\e[01;34m\]'
    White='\[\e[01;37m\]'
    Red='\[\e[01;31m\]'
    Green='\[\e[01;32m\]'
    Reset='\[\e[00m\]'
    FancyX='\342\234\227'
    Checkmark='\342\234\223'

    # Add a bright white exit status for the last command
    #PS1="$White\$? "
    # If it was successful, print a green check mark. Otherwise, print
    # a red X.
    if [[ $Last_Command == 0 ]]; then
        PS1+="$Green$Checkmark "
    else
        PS1+="$Red$FancyX "
    fi
    # If root, just print the host in red. Otherwise, print the current user
    # and host in green.
    if [[ $EUID == 0 ]]; then
        PS1+="$Red\\h "
    else
        PS1+="$Green\\u@\\h "
    fi
    # Print the working directory and prompt marker in blue, and reset
    # the text color to the default.
    PS1+="$Blue\\w \\\$$Reset "
}
PROMPT_COMMAND='set_prompt'

(Desativei o código de erro real porque não gosto dele, se você quiser ver os códigos exatos, basta remover #desta linha #PS1="$White\$? ":)

Veja como fica:

Captura de tela do GUI Terminal

captura de tela tty

gronostaj
fonte
2

Sim , é possível obter feedback para cada comando que você executou no terminal. Ele funciona com base no echo $?qual retorna 0 para uma conclusão bem-sucedida do comando e qualquer outro valor diferente de 0 para falha.

Para obter feedback de êxito ou falha, adicione a linha abaixo ao ~/.bashrcarquivo.

bind 'RETURN: ";if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;\n"' 

E, em seguida, ~/.bashrcarquivo de origem para fazê-lo funcionar.

source ~/.bashrc

Explicação:

Para cada comando que você executou no terminal, esse ;if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;código será automaticamente vinculado a ele.

Exemplo:

$ sudo apt-cache policy firefox;if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;
firefox:
  Installed: 24.0+build1-0ubuntu1
  Candidate: 24.0+build1-0ubuntu1
  Version table:
 *** 24.0+build1-0ubuntu1 0
        500 http://ubuntu.inode.at/ubuntu/ saucy/main amd64 Packages
        100 /var/lib/dpkg/status
SUCCESS

$ suda apt-get update;if [[ $? == 0 ]]; then tput setaf 6 && echo SUCCESS; tput sgr0; else tput setaf 1 && echo FAILURE; tput sgr0; fi;
No command 'suda' found, did you mean:
 Command 'sudo' from package 'sudo-ldap' (universe)
 Command 'sudo' from package 'sudo' (main)
 suda: command not found
FAILURE

insira a descrição da imagem aqui

Avinash Raj
fonte
1
bind 'RETURN: " && echo SUCCESS || echo FAILED \n"'também fará o mesmo, você não precisa verificar [[ $? == 0 ]]explicitamente.
Souravc
No entanto, o padrão C / Linux e o equivalente da gramática inglesa para 'Success' seriam FAILURE.
Benjamin R