我想让一个特定的 bash 脚本在找不到命令时快速失败,同时全局保留通常友好的 command_not_found 行为。例如,如果我将以下内容保存到/tmp/foo.sh
,...
# ----------------------------start foo.sh----------------------------
THIS_FP="$0"
THIS_FN="$(basename ${THIS_FP})"
THIS_DIR="$(dirname ${THIS_FP})"
function setup {
for CMD in \
'foo' \
; do
echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}"
eval "${CMD}"
done
} # end function setup
function teardown {
for CMD in \
"ls -alt ${THIS_DIR} | head" \
; do
echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}"
eval "${CMD}"
done
} # end function teardown
for CMD in \
'setup' \
'teardown' \
; do
echo -e "\n$ ${THIS_FN}::main loop::${CMD}"
eval "${CMD}"
done
# ------------------------------end foo.sh----------------------------
...并使其可执行,然后运行它,我明白了
# ----------------------------not what I want-------------------------
me@it:~$ /tmp/foo.sh
$ foo.sh::main loop::setup
$ foo.sh::setup::foo
/tmp/foo.sh: line 10: foo: command not found
$ foo.sh::main loop::teardown
$ foo.sh::teardown::ls -alt /tmp | head
total 68840
drwxrwxrwt 22 root root 1600 May 6 18:49 .
-rwxr-xr-x 1 me me 527 May 6 18:49 foo.sh
drwx------ 2 me me 40 May 6 17:54 plugtmp-1
srw------- 1 me me 0 May 6 17:28 tramp.13004aZf
drwx------ 2 me me 4200 May 6 17:22 matecorba-me
drwx------ 2 me me 40 May 6 02:20 plugtmp
-rw------- 1 me me 2034335 May 4 14:21 s_TTRuhW.mp3.part
-rw------- 1 me me 1658381 May 2 12:21 +rM4IttD.mp3.part
-rw-r--r-- 1 me me 86420 May 1 19:22 duplicity_20130501_1917.txt
# ----------------------------not what I want-------------------------
相反,我想做只有这个脚本foo.sh
失败,并在遇到“找不到命令”时立即失败:例如,
# ------------------------------what I want---------------------------
me@it:~$ /tmp/foo.sh
$ foo.sh::main loop::setup
$ foo.sh::setup::foo
/tmp/foo.sh: ERROR: foo: command not found
# Throwing me back to the shell from which I invoked foo.sh,
# *without* changing the usual friendly behavior outside it, e.g.:
me@it:~$ foo
No command 'foo' found, did you mean:
Command 'fio' from package 'fio' (main)
Command 'xoo' from package 'xoo' (main)
Command 'fop' from package 'fop' (main)
Command 'fox' from package 'objcryst-fox' (main)
Command 'zoo' from package 'zoo' (main)
Command 'goo' from package 'goo' (main)
foo: command not found
# ------------------------------what I want---------------------------
我可以通过编辑来提供这种行为吗仅有的 foo.sh
,不接触.bashrc
或任何其他当前安装的文件?如果是这样,怎么办?如果没有,为什么不呢?
答案1
要让脚本在出错后立即退出,请使用以下命令运行脚本bash -e /tmp/foo.sh
或将此行放在脚本的开头:set -e
。
-e
或者errexit
告诉 bash 在发生“错误”时立即退出脚本。请注意,这errexit
比这更复杂一些,并且它并不总是符合您的预期。阅读本文以获取更多信息:http://mywiki.wooledge.org/BashFAQ/105(“为什么 set -e(或 set -o errexit 或 trap ERR)没有达到我的预期?”)
bash 脚本中(通常)未启用“未找到命令”处理功能。这是因为 bash 脚本不读取 bashrc 并且command_not_found_handle
(通常)在某些 bashrc 中定义(在 debian 中是这样/etc/bash.bashrc
)。
如果您确实想确定脚本中禁用了命令未找到处理功能,您可以像这样取消定义该函数:
if [ x"$(type -t command_not_found_handle)" = x"function" ]; then
unset -f command_not_found_handle
fi
如果您在 bash 脚本中执行此操作并且您执行脚本,而不是采购,那么command_not_found_handle
只会在 bash 脚本中未定义。交互式 shell 中的状态command_not_found_handle
将保持在执行脚本之前的任何状态。
既然您正在使用,eval
还请阅读:http://mywiki.wooledge.org/BashFAQ/048(“Eval 命令和安全问题”)