Bash 如何处理;“未找到命令”;在狂欢节上

Bash 如何处理;“未找到命令”;在狂欢节上,bash,Bash,我有一个脚本来检查我的环境,我想请教您关于如何处理“command not found”错误的建议 echo“…RVM版本:$(RVM-v)” echo“…节点版本:$(节点-v)” echo“…Ruby版本:$(Ruby-v)” echo“…绑定器版本:$(bundle-v)” 回声“…乘客版本:$(乘客-v)” 它显示节点和乘客命令的“未找到命令”: ...RVM Version : rvm 1.29.7 (latest) by Michal Papis deploy_confi

我有一个脚本来检查我的环境,我想请教您关于如何处理“command not found”错误的建议

echo“…RVM版本:$(RVM-v)”
echo“…节点版本:$(节点-v)”
echo“…Ruby版本:$(Ruby-v)”
echo“…绑定器版本:$(bundle-v)”
回声“…乘客版本:$(乘客-v)”
它显示
节点和
乘客
命令的“未找到命令”:

...RVM Version      : rvm 1.29.7 (latest) by Michal Papis
deploy_confirm.sh: line 10: node: command not found
...Node Version     : 
...Ruby Version     : ruby 2.6.0p0 (2018-12-25 revision 66547)
...Bundler Version  : Bundler version 2.0.1
deploy_confirm.sh: line 13: passenger: command not found
...Passenger Version: 
我希望显示“未找到”,而不是显示错误,如下所示:

...RVM Version      : rvm 1.29.7 (latest) by Michal Papis
...Node Version     : Not found
...Ruby Version     : ruby 2.6.0p0 (2018-12-25 revision 66547)
...Bundler Version  : Bundler version 2.0.1
...Passenger Version: Not found

包装器函数是获得定制行为的一种简单方法,特别是在不希望全局更改该行为的情况下

or_not_found() {
  if type "$1" >/dev/null 2>&1; then # if given a valid command
    "$@"                             # run that command with original arguments
  else
    echo "Not found"  # write to stdout so it's captured by the command substitution
  fi
}

echo "...Login Shell User : $USER"  # much more efficient than calling whoami
echo "...RVM Version      : $(or_not_found rvm -v)"
echo "...Node Version     : $(or_not_found node -v)"
echo "...Ruby Version     : $(or_not_found ruby -v)"
echo "...Bundler Version  : $(or_not_found bundle -v)"
echo "...Passenger Version: $(or_not_found passenger -v)"

使用
2>/dev/null
抑制错误消息,并将
|
作为
其他
的缩写<如果命令
a
失败,code>a | | b
将运行
b

echo "...Login Shell User : $(whoami)"
echo "...RVM Version      : $(rvm -v 2>/dev/null || echo 'Not found')"
echo "...Node Version     : $(node -v 2>/dev/null || echo 'Not found')"
echo "...Ruby Version     : $(ruby -v 2>/dev/null || echo 'Not found')"
echo "...Bundler Version  : $(bundle -v 2>/dev/null || echo 'Not found')"
echo "...Passenger Version: $(passenger -v 2>/dev/null || echo 'Not found')"

如果使用bash>=4.0,请在第一行
echo
之前插入此代码:

command_not_found_handle() { echo "not found"; return 127; }
然后在最后一行
echo
后插入此命令,以删除此函数:

unset command_not_found_handle
输出,例如:

...RVM Version : not found ...Node Version : v4.2.6 ...Ruby Version : ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ...Bundler Version : not found ...Passenger Version: not found …RVM版本:未找到 …节点版本:v4.2.6 …Ruby版本:Ruby 2.3.1p112(2016-04-26)[x86_64-linux-gnu] …捆绑程序版本:未找到 …乘客版本:未找到
您可能需要确保
命令\u not\u found\u handle
仍然返回127。@Cyrus,我会对此保持警惕——在OP打印了他们的信息块之后,它会持续很长时间,因此只要它保持定义,就会将未找到的信息添加到stdout而不是stderr。谢谢@chepner和Charles的提示。我更新了我的答案。有趣的是,我以前从未见过,谢谢你的提示。明显的问题是,
command\u not\u found\u handle()
在重新定义之前可能已被定义为其他内容。理想情况下,您应该在定义之前保存它,然后再恢复它,而不是在定义之后取消设置它。@EdMorton:谢谢您的提示。是的,这将是一个必要时可以添加的功能。@TranNghi这将满足您的要求,但是这里的其他命令不会,因为它们会将找不到的命令与不支持给定参数的命令混合使用。使用
cut-v
作为命令尝试其他选项。Charles脚本将正确打印
cut:unknown选项--v请尝试“cut--help”以获取更多信息。
到stderr,而Johns将错误地打印
未找到
。这将为任何实际找到但不支持给定参数的命令打印
未找到
(例如
-v
)或者在调用时出现任何其他问题(无法读取配置文件、无法打开库、检测到某些资源冲突、内存问题、处理器占用问题、权限问题等),并且会隐藏真正的错误消息。确定命令是否可用的方法是使用
type command
,不调用该命令并假设失败意味着该命令不存在。看见