我制作了这个脚本来自动安装/卸载 git。在测试 git 是否已安装的函数中,我使用该git --version
命令并测试返回代码。
我不喜欢正常发生的 stderr 输出,因为我试图制作一个不错的自定义输出。虽然我已经弄清楚如何仅针对此功能抑制 stderr,但我似乎无法重新激活它。
调用此函数后,我的read
提示消失了。
function CheckGit() {
exec 3>&2 # link file desc 3 w/ stderr
exec 2> /dev/null
SILENT_MODE=$1
if [[ ! $(git --version) ]]; then
if [ SILENT_MODE ]; then
printf "${LT_RED} GIT IS NOT INSTALLED.\n"
fi
continue;
else
if [ SILENT_MODE ]; then
printf "${LT_BLUE} GIT IS CURRENTLY INSTALLED.\n"
fi
continue;
fi
GIT_INSTALLED=$?
#turn back on the stderr notifications
exec 2>&3 3>&- # Restore stdout and close file descriptor #3
}
while true; do
printf "${LT_BLUE} Menu\n"
printf " ***********************************************\n"
printf "${LT_GREEN} a) Check git.\n"
printf "${LT_GREEN} b) (More to be added)\n"
printf "${LT_GREEN} c) ...\n"
printf "${LT_GREEN} d) ...\n"
printf "${LT_GREEN} h) ...\n"
printf "${LT_RED} x) Exit.\n"
printf "\n${NC}"
read -p "Please make a selection: " eotuyx
case $eotuyx in
[Aa]* ) CheckGit true; continue;;
[Bb]* ) ...; continue;;
[Cc]* ) ...; continue;;
[Dd]* ) ...; continue;;
[Hh]* ) ...; continue;;
[XxQq]* ) break;;
* ) -e "\n${NC}" + "Please answer with a, b, c, d, x(or q).";;
esac
done
答案1
重申所给出的建议在评论中:
continue
从函数中删除语句CheckGit
。- 它们没有必要,
- 而且——您可能没有意识到——它们不仅会导致立即返回(从函数)到主循环,还会立即返回到
while true
主循环顶部的语句。因此,作为托马斯指出,你的exec 2>&3 3>&-
语句没有被执行。
一般注意事项:
if [ SILENT_MODE ]
总是正确的,因为莫斯维指出,因为它只是测试字符串是否SILENT_MODE
为非空。你似乎想要if [ "$SILENT_MODE" ]
。- 但你可能在欺骗自己。
if [ "$SILENT_MODE" ]
即使$SILENT_MODE
is也是 truefalse
— 它所做的只是测试字符串是否为非空,因此调用CheckGit false
仍然会导致显示信息。 - 而且,即使您没有欺骗自己,您也可能会欺骗下周必须维护此脚本的人。是的,那个人可能就是你。您明显的逻辑是“如果处于静默模式,则报告额外信息”。这在逻辑上是倒退的;说
if [ "$SILENT_MODE" = false ]
或调用变量会更有意义VERBOSE_MODE
。 $?
是非常短暂的。总是这样的结果最近的命令。 所以,如果你这样做如果 检查是否安装了git;然后 printf "GIT 未安装。\n" 别的 printf "GIT 当前已安装。\n" 菲 GIT_INSTALLED = $?
然后GIT_INSTALLED
获取 的退出状态printf
。您需要GIT_INSTALLED
提前设置。- 您的测试
if [[ ! $(git --version) ]]; then
不是测试“返回代码”(正如您在问题中所说),而是测试是否将git --version
任何内容写入标准输出。这可能就是你想要的。这可能是测试是否git
安装的最佳方法。但检查命令的退出状态可能会更好(通常通常更好)。 - 风格说明:我发现
if
-如果“真实”部分在前,陈述更容易理解then
。else
你的脚本说如果没有安装git 然后 说没有安装 否则(即,如果是不是未安装) 说它已经安装了 菲
双重否定令人困惑。 - 而且,是的;
exec 2> /dev/null
如果您想抑制连续 42 个语句的标准错误,这很方便。如果您只需要影响单个命令,只需将2> /dev/null
(或> /dev/null 2>&1
) 放在该命令上,如下所示莫斯维建议。
答案2
您的命令看起来不错,但逻辑并不能涵盖所有情况。请注意,当您执行 时continue
,描述符不会反转。
还要分析它应该如何工作,以及它实际上是如何工作的:
GIT_INSTALLED=$?
$?
是最后执行的命令的退出代码。使用调试来更仔细地查看这一点 ( set -x
)。
此外,作为初学者,您将从静态测试脚本中受益匪浅shellcheck.net。