bash 'nounset' no sub-shell / child não força o script principal a sair, como contornar isso globalmente?

3

Com este script: tstNounset.sh

#!/bin/bash
set -x 
set -o nounset;set -u

echo 'echo $str'
function FUNC1() { echo $str; };export -f FUNC1;bash -c FUNC1
function FUNC2() { set -u;echo $str; };export -f FUNC2;bash -c FUNC2
echo "A - should not reach here?"
echo $str
echo "B - doesn't reach here."

Eu gostaria de evitar atingir "A", de maneira global, não precisando verificar cada variável para isso.

Também sem usar set -e (já que eu cuido de erros e soluções alternativas, pois muitos também são apenas avisos).

Eu pensei que se houvesse alguma maneira de detectar "variável não vinculada" acontecesse até mesmo do subshell / child, então eu poderia forçar uma saída disso?

Não consegui fazer as coisas funcionarem em Como ter um script bash executando uma ação específica sobre erros do comando _each_? ou Como disparar erro usando o comando Trap também. Eu também encontrei esta pergunta antiga .

    
por Aquarius Power 24.07.2014 / 00:23

2 respostas

3

Subshells

Não há como uma subshell matar o script inteiro. Sob o efeito de set -u , um subshell não tem como dizer ao seu pai “hey, eu quero que você trate isso como um erro fatal”. Isso não faria sentido se set -u estivesse em vigor na sub-camada, mas não em seu pai. Tudo o que a subshell pode fazer é retornar um código de saída diferente de zero. Cabe a você gerenciar esse código de saída no pai, manualmente ou por meio de set -e .

(set -u; …; echo $undefined_variable)
# here $? is nonzero
ret=$?; if [ $ret -ne 0 ]; then exit $ret; fi

Subprocessos

O que você fez aqui não é um subshell: você está lançando outro programa. Esse outro programa é o bash, que é também o interpretador que está executando o script atual, mas é uma coincidência. Não há absolutamente nenhuma razão para que uma configuração em um programa invocado pelo bash faça com que o próprio bash saia.

set +e
bash -c 'do something'
echo "A - should and does reach here"

Isso não é diferente do que se você tivesse escrito perl -e 'use strict; print $barf' - Perl morreria e retornaria um status diferente de zero, mas isso não faz com que o script basque saia (exceto em set -e ). Use set -e se você quiser sair quando um subprocesso retornar um código de retorno diferente de zero.

    
por 24.07.2014 / 03:03
0

Meu script foi mal codificado, mas pode ser corrigido:

Veja os 1º, 2º e 3º comentários:

  • 1º É NECESSÁRIO UM ERRO DE ARMADILHA
  • 2 erros que você cuida não vai ficar preso! não use if ! ... impedirá obter valor de retorno com $?
  • 3 NÃO ECO DIRETAMENTE, use uma variável intermediária para que o erro possa ser cautch

tstNounset.sh:

#!/bin/bash
trap 'ErrorHappened;exit 1' ERR #1st A TRAP ERR IS REQUIRED

set -x 
set -o nounset;set -u

#echo 'echo $str'
nRet=0;if strA="'echo $str'";then : ;else nRet=$?;echo "Err$nRet";fi #2rd errors that you take care wont be trapped! do not use 'if ! ...' will prevent getting return value with $?
echo "0 - should not reach here?"
strA="'echo $str'";echo "$strA" #3nd DO NOT ECHO DIRECTLY, use a intermediary variable so the error can be cautch
echo "1 - should not reach here?"
function FUNC1() { echo $str; };export -f FUNC1;bash -c FUNC1
function FUNC2() { set -u;echo $str; };export -f FUNC2;bash -c FUNC2
echo "A - should not reach here?"
echo $str
echo "B - doesnt reach here."
    
por 25.07.2014 / 06:42