Como posso imprimir e sair do bash se um operador backtick falhar?

3

Eu tenho getinfo.sh , que imprime informações ou existe com o código 1.

Eu quero armazenar o resultado deste script em uma variável bash, caso contrário, imprima uma mensagem de erro e saia.

Se eu executar este

#!/bin/bash
X='getinfo.sh' || echo "failed" && exit 1

então o script sai mesmo quando getinfo.sh for bem-sucedido (nesse caso, ele não imprime nada.

Por outro lado

X='getinfo.sh' || (echo "failed" && exit 1)

que faz sentido para mim, vindo de linguagens tipo C, mas isso não não sai do script, pois os parênteses criam um novo shell interno, e é o shell interno que é removido , a casca externa continua correndo.

Como posso armazenar a saída de getinfo.sh e imprimir e sair se isso falhar?

    
por spraff 12.09.2016 / 14:54

4 respostas

3

(...) não é (principalmente) para os comandos grupo , mas para iniciar uma sub-rede. Portanto, o exit em (echo failed && exit 1) só sai da sub-rede.

Para agrupar comandos sem executá-los em um subshell, você usaria { ...; } :

X='getinfo.sh' || {
  echo >&2 "failed"
  exit 1
}

Embora aqui, eu prefiro usar:

if ! x=$(getinfo.sh); then
  echo >&2 failed
  exit 1
fi

Observe também que echo failed && exit 1 pode falhar ao sair se echo falhar, o que pode acontecer quando o stdout for um arquivo em um sistema de arquivos completo ou se um tubo quebrado for ignorado pelo SIGPIPE ou se o stdout tiver sido fechado ou um limite de tamanho de arquivo foi atingido com SIGXFSZ ignorado ...

    
por 12.09.2016 / 15:15
2

Você pode usar chaves para agrupar comandos sem criar uma sub-rede.

X=$(getinfo.sh) || { echo "failed" && exit 1; }

Na seção Comandos de agrupamento no manual de Bash

{ list; }

Placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created. The semicolon (or newline) following list is required.

Observação: os backticks estão sendo preteridos para a substituição de comandos. Por isso, usei a mais moderna sintaxe $() .

    
por 12.09.2016 / 15:13
1

Como você está definindo o valor de uma variável, por que não verificar o valor da variável e sair se for inadequado?

X='getinfo.sh'

[ -z "$X" ] && echo "failed" && exit 1

Isso pressupõe que getinfo.sh retornaria vazio na falha (se X for zero, saia), mas você pode modificar a verificação com base no que getinfo retorna na falha. Ou, mais apropriadamente, verifique se X contém o tipo de dados que você está procurando.

    
por 12.09.2016 / 15:08
0

A maneira mais fácil é adicionar -e ao seu shebang:

#!/bin/bash -e

Isso significa que o script será interrompido no primeiro erro. Como você usa backtick, se houver alguma mensagem de erro, você provavelmente a verá na sua stdout de qualquer maneira.

Se você realmente quiser usar seu método de eco e saída, eu escreveria uma função separada que seria chamada, que sempre imprime alguma mensagem de erro e sai imediatamente. Procure como escrever funções bash (elas são realmente fáceis).

    
por 12.09.2016 / 15:02

Tags