Estou escrevendo um script de shell e preciso verificar se um aplicativo de terminal foi instalado. Eu quero usar um comando TRY / CATCH para fazer isso, a menos que exista uma maneira mais limpa.
bash
shell
error-handling
Lee Probert
fonte
fonte
help test
pode ajudá-lo a encontrar a solução para o seu problema.trap
comandoRespostas:
Não.
O Bash não possui tantos luxos quanto se pode encontrar em muitas linguagens de programação.
Não há
try/catch
na festança; no entanto, pode-se obter um comportamento semelhante usando&&
ou||
.Usando
||
:se
command1
falhar, serácommand2
executado da seguinte maneiraDa mesma forma, usando
&&
,command2
será executado secommand1
for bem-sucedidoA aproximação mais próxima de
try/catch
é a seguinteTambém o bash contém alguns mecanismos de tratamento de erros, bem como
para seu script se algum comando simples falhar.
E também porque não
if...else
. É seu melhor amigo.fonte
#save your output
não falhe, ou o bloco "catch" ainda será executado.if...else
construção. Isso implica que os comandos bash são resolvidos como "verdade" se executados com êxito e "falsificados" se falharem?set -e
não é necessariamente a melhor maneira de fazer as coisas; aqui estão alguns contra-argumentos / casos especiais: mywiki.wooledge.org/BashFAQ/105Com base em algumas respostas que encontrei aqui, criei para mim um pequeno arquivo auxiliar para os meus projetos:
trycatch.sh
Aqui está um exemplo de como ele fica em uso:
fonte
||
apóscatch
e antes do{}
bloco? Eu teria pensado que fosse um&&
if False or run_if_failed()
significa que o curto-circuito OR tentou a primeira declaração que não retornou verdadeira e agora está passando para a próxima declaração.&&
não funcionaria porque a primeira declaração (try
) produziu false, o que significa que acatch
declaração não é necessária pela regra da tautologiafalse&any equals false
. Somente um não-curto-circuito E / OU executaria ambos.Desenvolvi uma implementação try & catch quase perfeita no bash, que permite escrever código como:
Você pode até aninhar os blocos try-catch dentro de si!
O código faz parte do meu boilerplate / framework do bash . Além disso, amplia a idéia de tentar e capturar coisas como manipulação de erros com backtrace e exceções (além de outros recursos interessantes).
Aqui está o código responsável apenas pelo try & catch:
Sinta-se livre para usar, usar e contribuir - é no GitHub .
fonte
my_output=$(try { code...; } catch { code...; })
Você pode usar
trap
:try { block A } catch { block B } finally { block C }
traduz para:
fonte
-E
flag Eu acho que, assim que as propaga armadilha para funçõesExistem muitas soluções semelhantes que provavelmente funcionam. Abaixo está uma maneira simples e prática de realizar try / catch, com explicação nos comentários.
fonte
bash
não interrompe a execução em execução no caso de algo detectar um estado de erro (a menos que você defina o-e
sinalizador). Linguagens de programação que oferecemtry/catch
fazem isso para inibir um "resgate" devido a essa situação especial (portanto, normalmente chamada de "exceção").Em
bash
vez disso, apenas o comando em questão será encerrado com um código de saída maior que 0, indicando esse estado de erro. Você pode verificar isso, é claro, mas como não há resgate automático de nada, uma tentativa / captura não faz sentido. Apenas falta esse contexto.No entanto, você pode simular um resgate usando subcascas que podem terminar em um ponto que você decide:
Em vez disso
some_condition
com um,if
você também pode apenas tentar um comando e, caso falhe (tenha um código de saída maior que 0), salve:Infelizmente, usando esta técnica, você está restrito a 255 códigos de saída diferentes (1..255) e nenhum objeto de exceção decente pode ser usado.
Se você precisar de mais informações para transmitir sua exceção simulada, poderá usar o stdout dos subshells, mas isso é um pouco complicado e talvez outra pergunta ;-)
Usando o
-e
sinalizador mencionado acima para o shell, você pode remover essaexit
declaração explícita :fonte
Como todo mundo diz, o bash não possui uma sintaxe apropriada de try / catch suportada pelo idioma. Você pode iniciar o bash com o
-e
argumento ou usarset -e
dentro do script para interromper todo o processo do bash se algum comando tiver um código de saída diferente de zero. (Você também podeset +e
permitir temporariamente comandos com falha.)Portanto, uma técnica para simular um bloco try / catch é iniciar um subprocesso para fazer o trabalho com
-e
enabled. Em seguida, no processo principal, verifique o código de retorno do subprocesso.O Bash suporta sequências heredoc, assim você não precisa escrever dois arquivos separados para lidar com isso. No exemplo abaixo, o heredoc TRY será executado em uma instância do bash separada, com
-e
enabled, para que o subprocesso falhe se algum comando retornar um código de saída diferente de zero. Então, de volta ao processo principal, podemos verificar o código de retorno para manipular um bloco catch.Não é um bloco de tentativa / captura suportado pelo idioma, mas pode causar uma coceira semelhante para você.
fonte
Você pode fazer:
fonte
E você tem armadilhas http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html que não são iguais, mas outra técnica que você pode usar para esse fim
fonte
Uma coisa muito simples que eu uso:
fonte
||
está()
, ele funcionaria em um subshell e sairia, sem causar a saída do shell principal. Use o{ }
agrupamento.Abaixo está uma cópia completa do script simplificado usado em minha outra resposta . Além da verificação de erro adicional, existe um alias que permite ao usuário alterar o nome de um alias existente. A sintaxe é fornecida abaixo. Se o
new_alias
parâmetro for omitido, o alias será removido.O script completo é fornecido abaixo.
fonte
Abaixo está um exemplo de um script que implementa
try/catch/finally
no bash.Os scripts de exemplo começam criando um fifo anônimo, que é usado para passar mensagens de string de um
command exception
outhrow
para o final dotry
bloco mais próximo . Aqui, as mensagens são removidas do fifo e colocadas em uma variável de matriz. O estado é retornado atravésreturn
eexit
comandos e colocados em uma variável diferente. Para inserir umcatch
bloco, esse status não deve ser zero. Outros requisitos para inserir umcatch
bloco são passados como parâmetros. Se o final de umcatch
bloco for atingido, o status será definido como zero. Se o final dofinally
bloco for atingido e o status ainda for diferente de zero, uma execução implícita contendo as mensagens e o status será executada. O script requer a chamada da funçãotrycatchfinally
que contém um manipulador de exceções sem tratamento.A sintaxe para o
trycatchfinally
comando é fornecida abaixo.A
-c
opção adiciona a pilha de chamadas às mensagens de exceção.A
-d
opção habilita a saída de depuração.A
-e
opção ativa exceções de comando.A
-h
opção permite que o usuário substitua seu próprio manipulador de exceção de comando.A
-k
opção adiciona a pilha de chamadas à saída de depuração.A
-o
opção substitui o arquivo de saída padrão que é/dev/fd/2
.A
-u
opção permite que o usuário substitua seu próprio manipulador de exceções sem tratamento.A
-v
opção permite ao usuário transmitir valores através do uso da substituição de comando.O
fifo
é o nome do arquivo fifo.A função
function
é chamadatrycatchfinally
como um subprocesso.A sintaxe para o
catch
comando é fornecida abaixo.As opções são definidas abaixo. O valor para a primeira lista é o status. Valores subseqüentes são as mensagens. Se houver mais mensagens do que listas, as mensagens restantes serão ignoradas.
-e
significa[[ $value == "$string" ]]
(o valor precisa corresponder a pelo menos uma cadeia de caracteres na lista)-n
significa[[ $value != "$string" ]]
(o valor não pode corresponder a nenhuma das cadeias da lista)-o
significa[[ $value != $pattern ]]
(o valor não pode corresponder a nenhum dos padrões da lista)-p
significa[[ $value == $pattern ]]
(o valor tem para corresponder a pelo menos um padrão na lista)-r
significa[[ $value =~ $regex ]]
(o valor deve corresponder a pelo menos uma expressão regular estendida na lista)-t
significa[[ ! $value =~ $regex ]]
(o valor não pode corresponder a nenhuma das expressões regulares estendidas na lista)O
try/catch/finally
script é dado abaixo. Para simplificar o script para esta resposta, a maior parte da verificação de erros foi removida. Isso reduziu o tamanho em 64%. Uma cópia completa desse script pode ser encontrada na minha outra resposta .Abaixo está um exemplo, que assume que o script acima está armazenado no arquivo nomeado
simple
. Omakefifo
arquivo contém o script descrito nesta resposta . Supõe-se que o arquivo nomeado4444kkkkk
não exista, causando uma exceção. A mensagem de erro emitida pelols 4444kkkkk
comando é automaticamente suprimida até dentro docatch
bloco apropriado .O script acima foi testado usando
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. A saída, da execução deste script, é mostrada abaixo.Outro exemplo que usa a
throw
pode ser criado substituindo a funçãoMyFunction3
pelo script mostrado abaixo.A sintaxe para o
throw
comando é fornecida abaixo. Se nenhum parâmetro estiver presente, o status e as mensagens armazenadas nas variáveis serão usados.A saída, da execução do script modificado, é mostrada abaixo.
fonte