Evite ejecutar el script si una variable no está definida

18

Tengo un script que se parece a:

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

Sin embargo, el usuario debe proporcionar una llamada variable BATCHNUM y de lo contrario necesito forzar que este script deje de ejecutarse. Sería mejor si pudiera forzar que el script que llama a este script se detenga también (o incluso el script # 1 que llama al script # 2 que llama a este script).

usuario40780
fuente

Respuestas:

28

La forma más rápida es probablemente agregar estas dos líneas al inicio del script:

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

La primera línea establece la nounsetopción en el shell que ejecuta el script, que se cancela si intenta expandir una variable no establecida; el segundo se expande $BATCHNUMen el contexto de un no-op, para activar el aborto antes de hacer cualquier otra cosa.

Si desea un mensaje de error más útil, podría escribir:

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

O similar.

Tom Hunt
fuente
18

Aquí desea verificar que BATCHNUMesté configurado y no sea nulo.

El shell POSIX proporciona una expansión de parámetros para este trabajo. Simplemente agregue esta línea antes de usar BATCHNUM:

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

o mejor establecer el valor predeterminado para BATCHNUMsi el usuario no proporcionó uno:

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

Esto funcionará en bash y en un POSIX sh. Prefiero no diferenciar entre variables vacías y variables indefinidas (es decir, no me gusta set -u, pero solo soy yo).

PSkocik
fuente
2

Las líneas

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

Verifique si está vacío $BATCHNUM. Con$PPID usted puede hacer el daño que quiera a sus padres ( kill $PPID). Para asesinar a tu abuelo, debes obtener la identificación del proceso por otros medios, como mirar los datos /proc/$PPID.

Sin embargo, si su padre muere, le envía una señal ( SIGHUP), por lo que debe atraparlo antes de comenzar a matar a alguien:

trap '' SIGHUP

Actualización: si crees que tienes que matar a tus padres, lo estás haciendo mal. Simplemente devuelva un código de salida significativo. El script principal debe verificar el código de retorno del script llamado y reaccionar en consecuencia.

Thomas Erker
fuente
1
un poco brutal .... :)
user40780
1

Para probar si BATCHNUMestá definido y salir si no lo está:

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

Si también desea rechazar el caso donde BATCHNUMestá vacío, use en ${BATCHNUM:+a}lugar de ${BATCHNUM+a}. Para obtener información sobre la ${VARIABLE+TEXT_IF_NULL}construcción de expansión de parámetros, consulte, por ejemplo, el manual de bash .

No mates el proceso padre. No sabes cuál es el proceso principal. Si algún script que llama a este necesita abortar si este script aborta, haga que verifique el estado de salida de este script. Por ejemplo, en el guión n. ° 2:

script3 || exit $?

o use set -epara abortar el script si algún comando devuelve un estado de falla (distinto de cero).

Gilles 'SO- deja de ser malvado'
fuente