Evite executar o script se uma variável não estiver definida

17

Eu tenho um script parecido com:

c=0
for f in */*; do
cp -v "$f" "/myhome/CE$(printf '%0*d' 2 $BATCHNUM)-new-stuctures_extracted/test-$(printf '%0*d' 5 $c)"
c=$((c=c+1))
done

No entanto, o usuário deve fornecer uma chamada variável BATCHNUM e, caso contrário, preciso forçar a interrupção da execução desse script. Seria melhor se eu pudesse forçar o script que chama esse script a parar também (ou mesmo o script # 1 que chama o script # 2 que chama esse script).

user40780
fonte

Respostas:

28

A maneira mais rápida é provavelmente adicionar essas duas linhas ao início do script:

set -u # or set -o nounset
: "$BATCHNUM"

A primeira linha define a nounsetopção no shell executando o script, que é interrompido se você tentar expandir uma variável não definida; o segundo se expande $BATCHNUMno contexto de uma não operação, para acionar o aborto antes de fazer qualquer outra coisa.

Se você quiser uma mensagem de erro mais útil, escreva:

if [[ -z "$BATCHNUM" ]]; then
    echo "Must provide BATCHNUM in environment" 1>&2
    exit 1
fi

Ou similar.

Tom Hunt
fonte
17

Aqui você deseja verificar se BATCHNUMestá definido e não nulo.

O shell POSIX fornece uma expansão de parâmetro para este trabalho. Basta adicionar esta linha antes de usar BATCHNUM:

: "${BATCHNUM:?Variable not set or empty}"

ou melhor, para definir o valor padrão BATCHNUMse o usuário não fornecer um:

: "${BATCHNUM:=3}"
cuonglm
fonte
4
[ -n "$BATCHNUM" ] || { kill "$PPID"; exit 1; }
#Unless $BATCHNUM is defined and unempty, ask parent process to exit and exit w/ 1

Isso funcionará no bash e em um POSIX sh. Prefiro não diferenciar entre variáveis ​​vazias e variáveis ​​indefinidas (ou seja, não gosto set -u, mas sou apenas eu).

PSkocik
fonte
2

As linhas

if [ -z "$BATCHNUM" ]; then
    exit 2;
fi

verifique se está vazio $BATCHNUM. Com $PPIDvocê, você pode fazer qualquer dano que desejar aos seus pais ( kill $PPID). Para assassinar seu avô, você precisa obter a identificação do processo por outros meios, como ver os dados /proc/$PPID.

No entanto, se seu pai morre, ele envia um sinal ( SIGHUP) para você, então você deve prendê-lo antes de começar a matar alguém:

trap '' SIGHUP

Atualização: Se você acha que precisa matar seus pais, está fazendo errado. Basta retornar um código de saída completo. O script pai deve verificar o código de retorno do script chamado e reagir de acordo.

Thomas Erker
fonte
1
um pouco brutal .... :)
user40780
1

Para testar se BATCHNUMestá definido e sair se não estiver:

if [ -n "${BATCHNUM-a}" ]; then
  echo >&2 "Fatal error: BATCHNUM not set"
  exit 2
fi

Se você também deseja rejeitar o caso em que BATCHNUMestá vazio, use em ${BATCHNUM:+a}vez de ${BATCHNUM+a}. Para obter informações sobre a ${VARIABLE+TEXT_IF_NULL}construção de expansão de parâmetros, consulte, por exemplo, o manual do bash .

Não mate o processo pai. Você não sabe qual é o processo pai. Se algum script que chama este precisar abortar se esse script for interrompido, verifique o status de saída desse script. Por exemplo, no script # 2:

script3 || exit $?

ou use set -epara interromper o script se algum comando retornar um status de falha (diferente de zero).

Gilles 'SO- parar de ser mau'
fonte