我正在尝试编写基于输入的 bash 脚本,该脚本将触发相应的应用程序构建脚本。如果输入是“all”,那么所有应用程序都会被调用。我在这里面临问题,如果输入为“all”,则只有 app_1 和 app_2 被调用。可能是什么问题,
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "app_1" ]
then
echo "BUILD_STAGE APP_1 build started"
fi
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "app_2" ]
then
echo "BUILD_STAGE APP_2 build started"
fi
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "app_3" ]
then
echo "BUILD_STAGE APP_3 build started"
fi
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "app_4" ]
then
echo "BUILD_STAGE APP_4 build started"
fi
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "app_5" ]
then
echo "BUILD_STAGE APP_5 build started"
fi
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "app_6" ]
then
echo "BUILD_STAGE APP_6 build started"
fi
答案1
您在此处提供的示例代码不会发生这种情况。想必这些echo
s 只是您正在执行的更复杂任务的占位符,我的猜测是任务实际上app_2
改变了 的值$_BUILD_MODE
。
在这里,你可以这样做:
case $_BUILD_MODE in
(all | app_1) task for app_1 ;;&
(all | app_2) task for app_2 ;;&
(all | app_3) task for app_3 ;;&
...
esac
这将使它更短、更整洁,并且还避免了这个特定问题,因为$_BUILD_MODE
在开始时只取消引用一次。
;;&
上面是 bash 特定的。在 zsh 和 mksh 中,等效语法是 with ;|
。 zsh、mksh 和 bash 支持;;
(来自 Bourne shell,也是唯一的标准 shell)和;&
(来自 Korn shell)。
app_2
调用exit
或或 的任务也可能exec some-other-command
遇到致命错误或 shell 进程被终止。解决这个问题的方法是通过将子 shell 包装在(...)
.
bash -o xtrace
尝试使用(与 相同)运行脚本,bash -x
看看会发生什么。
1 例如,如果内置程序写入损坏的管道,则通过 SIGPIPE;如果超出某些资源限制,则通过 SIGXCPU...
答案2
并不是真正关于你在问什么,但是当你在那里重复一些代码时,这种 if 链看起来很尴尬,即使它只是在[ "${_BUILD_MODE}" = "all" ]
这里。
相反,我将任务放入例如函数中,并用它们的名称创建一个数组(未经测试):
app_1() {
echo "BUILD_STAGE APP_1 build... "
}
app_2() {
echo "BUILD_STAGE APP_2 build... "
}
tasks=(app_1 app_2)
for task in "${tasks[@]}"; do
if [ "${_BUILD_MODE}" = "all" ] || [ "${_BUILD_MODE}" = "$task" ]; then
"$task"
fi
done
请注意,函数名称必须与此处使用的任务名称相同_BUILD_MODE
。
在这里,如果您需要更改任务的运行方式,例如将它们包装在子 shell 中,例如斯蒂芬建议,或者添加一些打印输出来分隔它们,您可以在循环中的一个位置执行此操作。