如果未定义变量,请避免运行脚本


18

我有一个脚本看起来像:

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

但是,用户必须提供一个调用BATCHNUM的变量,否则我需要强制该脚本停止运行。如果我也可以强制停止调用此脚本的脚本(甚至是调用#2脚本的#1脚本也要停止),那会更好。

Answers:


28

最快的方法可能是将这两行添加到脚本的开头:

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

第一行在nounset运行脚本的外壳程序中设置选项,如果您尝试扩展未设置的变量,该选项将中止;第二个$BATCHNUM在无操作的情况下扩展,以在执行其他操作之前触发中止。

如果您想要更有用的错误消息,可以改写:

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

或类似。


18

您要在此处检查是否BATCHNUM已设置并且不为null。

POSIX shell 为此工作提供了一个参数扩展。只需在使用前添加以下行BATCHNUM

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

BATCHNUM如果用户不提供默认值,则最好设置默认值:

: "${BATCHNUM:=3}"

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

这将适用于bash和POSIX sh。我不想在空变量和未定义变量之间进行区分(即,我不喜欢set -u,但这就是我)。


2

线

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

检查是否为空$BATCHNUM。通过这种方式,$PPID您可以对父母造成任何伤害(kill $PPID)。为了谋杀您的祖父母,您需要通过其他方式获取进程ID,例如查看中的数据/proc/$PPID

但是,如果您的父母去世,它会向您发送信号(SIGHUP),因此您必须先捕获它,然后才能杀死任何人:

trap '' SIGHUP

更新:如果您认为必须杀死父母,那您做错了。只需返回有意义的退出代码即可。父脚本应检查被调用脚本的返回码并做出相应反应。


1
有点残酷.... :)
user40780 2015年

1

要测试是否BATCHNUM已定义,如果未定义则退出:

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

如果您还想拒绝BATCHNUM空的情况,请使用${BATCHNUM:+a}代替${BATCHNUM+a}。有关${VARIABLE+TEXT_IF_NULL}参数扩展构造的信息,请参见例如bash手册

不要杀死父进程。您不知道父进程是什么。如果某些脚本调用此脚本需要中止,如果该脚本中止,则需要中止,请检查该脚本的退出状态。例如在脚本2中:

script3 || exit $?

或用于set -e在任何命令返回失败(非零)状态时中止脚本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.