如何在本地重新定义'command_not_found_handle'?

Tom*_*che 2 bash function error-handling command-not-found

我想让一个特定的 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----------------------------
Run Code Online (Sandbox Code Playgroud)

...并使其可执行,然后运行它,我得到

# ----------------------------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-------------------------
Run Code Online (Sandbox Code Playgroud)

相反,我只想让这个脚本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---------------------------
Run Code Online (Sandbox Code Playgroud)

我可以 通过编辑foo.sh而不触及.bashrc或任何其他当前安装的文件来提供此行为吗?如果是这样,如何?如果没有,为什么不呢?

les*_*ana 6

要在错误后立即退出脚本,请使用以下命令运行脚本bash -e /tmp/foo.sh或将此行放在脚本的开头:set -e.

-e或者errexit告诉 bash 在发生“错误”时立即退出脚本。请注意,这errexit比这要复杂一些,并且它并不总是按照您的预期进行。阅读本文了解更多信息:http : //mywiki.wooledge.org/BashFAQ/105(“为什么设置 -e(或设置 -o errexit,或陷阱 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
Run Code Online (Sandbox Code Playgroud)

如果您在 bash 脚本中执行此操作并执行该脚本,而不是sourcing,则command_not_found_handle只会在 bash 脚本中未定义。的状态command_not_found_handle在交互shell会留在它执行该脚本前任何状态。

阅读更多信息:https : //superuser.com/questions/176783/what-is-the-difference-between-executing-a-bash-script-vs-sourcing-it

由于您正在使用,eval请同时阅读:http : //mywiki.wooledge.org/BashFAQ/048(“Eval 命令和安全问题”)

  • `x` hack 只适用于 **非常** 旧的 shell,并且由于问题被标记为 [tag:bash],你可以只使用 `[[ $(type -t command_not_found_handle) == function ]]`。 (3认同)