跳转至

Shell 脚本核心速查(Bash)

用途:供 AI 助手快速查阅并编写/调试运维脚本。 版本基线:Ubuntu 26.04 LTS / bash 5.3 / Git 2.56(核对日期 2026-11-11,来源:官网) 更新日期:2026-11-11

1. 脚本骨架(规范模板)

#!/usr/bin/env bash
set -euo pipefail     # e:出错即退 u:未定义变量报错 pipefail:管道任一环节失败即失败
# 用法说明
usage() { echo "Usage: $0 <arg1> <arg2>"; exit 1; }

[ $# -lt 1 ] && usage
ARG1="$1"

log()  { echo "[$(date '+%F %T')] $*"; }   # 简易日志函数
trap 'log "脚本异常退出于第 $LINENO 行"' ERR   # 出错打印行号

执行:chmod +x script.sh && ./script.sh;调试:bash -x script.sh(打印每条命令)。

bash 5.3(2025-05,最新稳定版)值得关注的点:新增在当前 shell 执行上下文中运行的命令替换 (不 fork 子进程、可改变当前 shell 变量)、GLOBSORT 变量控制路径补全排序、read -E 带补全读入。 以上均为增强特性,既有脚本语法(5.x 全系兼容)不受影响。

2. 变量与字符串

NAME="world"
echo "hello $NAME"          # 双引号内展开变量
echo 'hello $NAME'          # 单引号不展开(字面量)
echo "${NAME}!"             # 拼接时用花括号防歧义
DEFAULT="${1:-fallback}"    # 参数缺省值
LENGTH=${#NAME}             # 字符串长度
SUB=${NAME:0:3}             # 截取
UPPER=${NAME^^}             # 转大写(bash4+)
命令替换:NOW=$(date +%F)    # 用 $() 不用反引号

3. 条件判断

# 文件测试
[ -f file ]    # 存在且是文件   [ -d dir ]  存在且是目录
[ -z "$s" ]    # 空字符串       [ -n "$s" ] 非空
[ -x script ]  # 可执行         [ -w f ]    可写

# 字符串 / 数字
[ "$a" = "$b" ]        # 相等(字符串一律加引号)
[ "$n" -gt 10 ]        # -gt -lt -ge -le -eq -ne

# 推荐 [[ ]](更安全,支持正则与 && ||)
if [[ "$str" =~ ^[0-9]+$ ]]; then echo "是数字"; fi
if [[ -f "$file" && "$user" == "root" ]]; then :; fi

# 分支
case "$1" in
  start)  echo start ;;
  stop)   echo stop ;;
  *)      echo "unknown" ;;
esac

4. 循环

for i in 1 2 3; do echo $i; done
for i in {1..10}; do echo $i; done
for f in /var/log/*.log; do wc -l "$f"; done
for ip in 192.168.100.{1..10}; do ping -c1 -W1 $ip & done; wait   # 并发 ping

while read -r line; do echo "$line"; done < file.txt
while true; do date; sleep 5; done            # 守护式轮询(实验用)

5. 函数与返回值

myfunc() {
  local x="$1"            # 局部变量
  echo "$((x * 2))"       # stdout 是返回值的方式之一
  return 0                # return 只表示成功/失败(0-255)
}
result=$(myfunc 21)       # 捕获 stdout
myfunc 21 && echo ok      # 用 exit code 判断

6. 常用文本处理

cat file | grep -v "^#" | grep -v "^$"    # 去掉注释和空行
awk '{print $1, $3}' access.log           # 按列取
awk -F: '$3 >= 1000 {print $1}' /etc/passwd   # 自定义分隔符
sed -i 's/old/new/g' file                 # 原地替换(先不带 i 预览!)
sed -n '10,20p' file                      # 取第 10-20 行
cut -d, -f1,3 data.csv                    # CSV 取列
sort -u file | wc -l                      # 去重计数
sort file | uniq -c | sort -rn | head     # Top N 频次
jq '.items[].metadata.name' a.json        # JSON 处理(apt install jq)
xargs -I{} cp {} /backup/                 # 把上一步结果逐个处理

7. 实用运维脚本片段

# 磁盘告警
df -H | awk 'NR>1 {gsub("%","",$5); if ($5+0 > 85) print $6" 使用率 "$5"%" }'

# 判断服务活着,死了自动拉起
systemctl is-active --quiet nginx || systemctl restart nginx

# 备份并保留最近 7 份
tar -czf /backup/app-$(date +%F).tar.gz /opt/app/data
ls -1t /backup/app-*.tar.gz | tail -n +8 | xargs -r rm -f

# 等待端口可用(部署后健康检查)
until curl -sf http://localhost:8080/health >/dev/null; do sleep 2; done

8. AI 助手操作守则

  • 生成脚本必带 set -euo pipefail 和 #!/usr/bin/env bash。
  • 写入非 ASCII 路径/内容时注意编码(Windows 下用 UTF-8 无 BOM;避免生成 .ps1/.bat 中文脚本,Linux 端一律 .sh)。
  • sed -i 修改文件前先输出替换结果预览,或先备份。
  • rm 相关脚本片段必须带精确路径或 -r 前有明确清单,禁止 rm $VAR/* 这类未判空写法(先 [ -n "$VAR" ])。
  • 脚本执行前 bash -n script.sh 做语法检查,shellcheck 可用时优先跑一遍。
  • 长时间/循环类脚本要留日志输出(重定向到文件),便于事后 tail 排查。