Skip to content

Shell编程

​ Shell 是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序

1. 基础概览

  • 脚本声明:第一行必须指定解释器。

    bash
    #!/bin/bash
  • 执行方式

    • chmod +x script.sh -> ./script.sh(推荐,需执行权限)
    • bash script.sh(无需权限,直接调用解释器)

2. 变量与常用符号

  • Shell中的变量分为系统变量和用户自定义变量
  • 显示当前Shell中所有变量set
  • 定义变量:等号两边不能有空格

    bash
    name="tomcat"
    path=/usr/local/$name  # 引用变量
    readonly age=18        # 静态变量,不能unset
    #将命令的返回值赋给变量
    A=`date`#反引号,运行里面的命令,并把结果返回赋值给A
    A=$(date)#等价于反引号
  • 撤销变量unset 变量,静态变量不能unset

  • 特殊变量(后端部署脚本常用):

    • $0:当前脚本文件名。
    • $1 - $n:脚本参数(如 ./deploy.sh dev 中的 dev 就是 $1),第10个以上的参数要用大括号包含,如${10}
    • $* :所有参数整体,加双引号时,所有的参数合并成一个单一的字符串,参数之间用空格分隔。如果你输入了三个参数 a, b, c"$*" 的结果是 "a b c"
    • $@ :所有参数,加双引号时,参数被分别对待,即参数列表。如果你输入了三个参数 a, b, c"$@" 的结果是 "a" "b" "c"
    • $#:参数个数。
    • $?上一个命令的退出状态(0 表示成功,非 0 表示失败,排错必备)。
  • 单引号和双引号:单引号原封不动输出,双引号会解析引用变量

  • 定义变量规则、规范

    • 变量名称可以由字母、数字和下划线组成,但是不能以数字开头
    • 等号两侧不能有空格
    • 变量名一般习惯大写,这是一个规范
  • 运算符

    • 基本语法:"$((运算式))"或"$[运算式]"或expr m + n

    • expr运算符之间要有空格,如果想将expr的结果赋给某个变量,使用``

    • \* , / , % 乘 除 取余,注意乘号前面要加转义字符 \

      image-20260302091004163


3. 常用条件判断 [ ]

注意:中括号内侧两边必须有空格。

  • 文件判断
    • -e file:文件是否存在。
    • -d dir:目录是否存在。
    • -f file:是否为普通文件。
  • 字符串判断
    • -z $str:字符串是否为空。
    • "$str1" == "$str2":字符串是否相等。
  • 数值判断(不同于 Java 的 > <):
    • -eq (equal等于), -ne (not equal不等于), -gt (greater than大于), -ge (大于等于), -lt (less than小于), -le (小于等于)。

4. 设置环境变量

  • 基本语法

    1. export 变量名=变量值:将shell变量输出为环境变量

    2. source 配置文件:让修改后的配置信息立即生效

    3. echo $变量名:查询环境变量的值

    注意:Shell多行注释是 :<<! 内容 !,多行注释要另起一行写

5. 流程控制与常用函数

If 判断(判断服务状态)

bash
if [ "$?" -eq 0 ]; then
    echo "Success"
else
    echo "Failed"
fi

Case语句

shell
case $1 in
"1")
echo "周一"
;;
"2")
echo "周二"
;;
"3")
echo "周三"
;;
*)
echo "Other..."
esac

For 循环(批量处理日志/备份)

bash
for file in $(ls /var/log/*.log); do
    echo "正在处理日志: $file"
done

for((初值;循环控制条件;变量变化))
do
程序/代码
done

while

shell
while [ condition ]
do
程序/代码
done

read 读取控制台输入

  • 基本语法:read [选项] [参数]
  • 选项:
    • -p:读取提示符,运行时显示给用户
    • -t:限定等待输入时间

image-20260302094149192

basename和dirname

  • basename用于获取文件名
  • dirname用于获取目录名

自定义函数

  • 语法:

    [ function ] funname[()]
    {
    	Action;
    	[return int;]
    }

    image-20260302094710097


6. 后端三剑客 (Grep / Awk / Sed)

这是后端在 Linux 上的“降维打击”工具:

  • Grep (过滤)

    grep -i "error" app.log(忽略大小写查找错误)。

  • Awk (提取列)

    ps -ef | grep java | awk '{print $2}'(提取 Java 进程的 PID)。

  • Sed (修改文本)

    sed -i 's/8080/9090/g' server.xml(将配置文件中的 8080 替换为 9090)。


7. 实战脚本模板:Java 服务健康检查

你可以直接把这段代码存为 check_java.sh

bash
#!/bin/bash

# 定义要检查的端口
PORT=8080

# 检查端口是否被占用
LISTEN_COUNT=$(netstat -tulnp | grep :$PORT | wc -l)

if [ $LISTEN_COUNT -gt 0 ]; then
    echo "$(date "+%Y-%m-%d %H:%M:%S") [INFO] Tomcat 正在运行在端口 $PORT"
else
    echo "$(date "+%Y-%m-%d %H:%M:%S") [WARN] Tomcat 已停止,尝试重启..."
    /usr/local/tomcat/bin/startup.sh
fi

8. 避坑指南

  1. 空格是灵魂if [ $a -eq $b ] 这里的空格一个都不能少,少了就报错。
  2. 变量引用:建议养成 ${var} 的习惯,避免变量名与周围字符混淆。
  3. 调试模式:写完脚本不敢跑?用 bash -x script.sh 执行,它会打印出每一行命令的执行过程。