一、为什么 case 很适合做菜单类脚本¶
原笔记把 case 定位得很清楚:它非常适合“固定选项”的判断场景,例如:
start|stop|restart|status- 菜单编号
1|2|3|4 yes|no
相比一长串 if ... elif ... else,case 在这些场景下更清晰,也更容易维护。
标准格式如下:
case "$choice" in
start)
echo start
;;
stop)
echo stop
;;
restart)
echo restart
;;
*)
echo "错误输入"
;;
esac
二、实战:菜单选择脚本怎么写¶
原笔记给了一个“会所菜单”的练习脚本,本质上就是练 case。
#!/bin/bash
cat <<EOF
##############olding私人高级会所#####################
输入1,选择138套餐) 吃饱套餐
输入2,选择443套餐) 吃饱喝足套餐
输入3,选择888套餐) 吃喝拉撒套餐
输入4,选择1688套餐) 你想干啥就干啥套餐
输入其他内容,退出
EOF
read -p "尊敬的VIP用户,请输入你的选择:" num
case "$num" in
1) echo "138套餐) 吃饱套餐" ;;
2) echo "443套餐) 吃饱喝足套餐" ;;
3) echo "888套餐) 吃喝拉撒套餐" ;;
4) echo "1688套餐) 你想干啥就干啥套餐" ;;
*) echo "选择错误,请充值" ;;
esac
这类脚本虽然偏练习性质,但已经体现了 case 最核心的使用方式。
三、实战:识别 yes/no 这类多写法输入¶
case 还有一个很好用的地方:一个分支可以匹配多个模式。
#!/bin/bash
read -p "input yes or no: " xuan
case "$xuan" in
yes|y|Y|Yes) echo "你输入的是yes" ;;
no|n|N|No) echo "你输入的是no" ;;
*) echo "无法识别输入" ;;
esac
这比在 if 里不停写 -o 更直观。
四、为什么写脚本时要尽量使用函数¶
原笔记对函数的总结可以概括成 3 点:
- 把重复代码抽出来,减少脚本冗余
- 让脚本更模块化
- 出现问题时方便调试和定位
常见定义方式有下面几种:
function show_a() {
echo 1
}
show_b() {
echo 2
}
function show_c {
echo 3
}
实际工作里最常见的是第二种:name() { ... }。
五、函数基础用法和传参方式¶
最基础的函数示例如下:
#!/bin/bash
show() {
echo 1
echo 2
echo 3
echo "上山打老虎"
}
show
函数也支持位置参数,规则和脚本传参类似:
- 函数里的
$1、$2指的是函数参数 - 函数里的
$#是函数参数个数 - 函数里的
$@、$*是函数收到的全部参数 - 函数里的
$0仍然是脚本名,不是函数名
这意味着你完全可以把脚本中的某个步骤做成“可传参函数”。
六、实战:用函数和 case 写服务管理脚本¶
原笔记最典型的综合案例,是给 sersync 写一个服务管理脚本:
#!/bin/bash
choice=$1
sersync_start() {
sersync2 -rdo /app/tools/sersync/conf/confxml.xml
}
sersync_stop() {
sersync_pid=$(ps -ef | grep sersync2 | grep -v grep | awk '{print $2}')
kill $sersync_pid
}
sersync_restart() {
sersync_stop
sersync_start
}
sersync_status() {
sersync_count=$(ps -ef | grep sersync2 | grep -v grep | wc -l)
if [ $sersync_count -eq 0 ]; then
echo "sersync is stopped"
else
sersync_pid=$(ps -ef | grep sersync2 | grep -v grep | awk '{print $2}')
echo "sersync is running ${sersync_pid}"
fi
}
error_msg() {
echo "Usage: $0 {start|stop|restart|status}"
}
case "$choice" in
start) sersync_start ;;
stop) sersync_stop ;;
restart) sersync_restart ;;
status) sersync_status ;;
*) error_msg ;;
esac
这个脚本已经具备了服务管理脚本最关键的骨架:
- 参数入口清晰
- 功能拆分为函数
case负责总调度- 错误输入有统一提示
七、把脚本写成“变量区 + 函数区 + 主流程”¶
综合原笔记内容,最推荐的 Shell 脚本组织方式是:
1、先定义变量。
2、再定义函数。
3、最后写主流程或 case 入口。
也就是类似下面这个结构:
#!/bin/bash
# 1. vars
choice=$1
# 2. functions
start_service() {
echo start
}
stop_service() {
echo stop
}
# 3. main
case "$choice" in
start) start_service ;;
stop) stop_service ;;
*) echo "Usage: $0 {start|stop}" ;;
esac
这种结构对后期维护、排障和扩展都最友好。
八、这篇内容真正要学到什么¶
如果把 case 和函数章节各提炼出一个核心结论,那就是:
- 固定分支选择,优先用
case - 重复逻辑和独立步骤,优先抽成函数
一旦把这两个习惯用到服务管理、巡检和发布脚本里,Shell 自动化脚本的质量就会立刻提升一个层级。