# 遍历列表
for fruit in apple banana cherry; do
echo "水果: $fruit"
done
# C风格for
for ((i=1; i<=10; i++)); do
echo "第 $i 次"
done
# 遍历文件
for file in /var/log/*.log; do
[[ -f "$file" ]] && echo "$file: $(wc -l < "$file")行"
done
# 遍历数组
servers=("web1" "web2" "db1")
for s in "${servers[@]}"; do
ping -c 1 -W 1 "$s" &>/dev/null && echo "$s ✅" || echo "$s ❌"
done
# while循环
count=0
while [[ $count -lt 10 ]]; do
echo "count=$count"
((count++))
done
# 读取文件
while IFS= read -r line; do
echo "行: $line"
done < /etc/hosts
# 无限循环
while true; do
echo "运行中... $(date)"
sleep 5
done
# until(条件为假时执行)
until [[ -f /tmp/done ]]; do
sleep 1
done
echo "完成!"
# break跳出循环
for i in $(seq 1 100); do
[[ $i -eq 5 ]] && break
echo "$i"
done
# continue跳过本次
for i in $(seq 1 10); do
[[ $((i % 2)) -eq 0 ]] && continue
echo "奇数: $i"
done
# break N跳出N层
for i in 1 2 3; do
for j in a b c; do
[[ "$i$j" == "2b" ]] && break 2
done
done
# 定义与调用
greet() {
local name="$1"
echo "你好, $name!"
}
greet "张三"
# 返回值(退出码)
is_root() { [[ $EUID -eq 0 ]]; }
is_root && echo "root" || echo "非root"
# 数值返回(0-255)
check_port() {
ss -tlnp | grep -q ":$1 " && return 0 || return 1
}
check_port 80 && echo "80开放" || echo "80未开放"
GLOBAL="全局"
my_func() {
local local_var="局部" # local关键字
local GLOBAL="覆盖" # 局部覆盖全局
echo "函数内: GLOBAL=$GLOBAL"
}
my_func
echo "函数外: GLOBAL=$GLOBAL" # 全局(未被修改)
# lib/utils.sh
log() {
local level="$1"; shift
echo "[$(date '+%H:%M:%S')] [$level] $*"
}
info() { log "INFO" "$@"; }
warn() { log "WARN" "$@"; }
error() { log "ERROR" "$@" >&2; }
confirm() {
read -p "$1 [y/N] " ans
[[ "$ans" =~ ^[Yy]$ ]]
}
retry() {
local max="$1"; shift
local n=1
while [[ $n -le $max ]]; do
eval "$@" && return 0
warn "尝试 $n/$max 失败"
((n++)); sleep 2
done
error "重试$max次仍失败"; return 1
}
# 使用: source lib/utils.sh
#!/bin/bash
set -euo pipefail
check_ssh() {
ssh -o ConnectTimeout=5 -o BatchMode=yes "$1" "echo OK" &>/dev/null
}
SERVERS=("web1" "web2" "db1" "cache1")
echo "===== 服务器检查 ====="
for s in "${SERVERS[@]}"; do
if check_ssh "$s"; then
echo "$s: ✅ SSH可达"
ssh "$s" "uptime; free -h | grep Mem; df -h /" 2>/dev/null
else
echo "$s: ❌ SSH不可达"
fi
done
#!/bin/bash
# backup-lib.sh
backup_file() {
local src="$1" dst="${2:-/backup}"
local ts=$(date +%Y%m%d_%H%M%S)
[[ ! -f "$src" ]] && return 1
cp "$src" "$dst/${ts}_$(basename "$src")"
}
rotate_backups() {
local dir="$1" keep="${2:-7}"
ls -t "$dir" | tail -n +"$((keep+1))" | while read f; do rm "$dir/$f"; done
}✅ 掌握for/while/until
✅ 学会break/continue
✅ 掌握函数定义与参数
✅ 理解变量作用域
✅ 学会编写函数库
# select创建交互菜单
PS3="请选择操作: "
select opt in "启动" "停止" "重启" "状态" "退出"; do
case $opt in
启动) systemctl start myapp ;;
停止) systemctl stop myapp ;;
重启) systemctl restart myapp ;;
状态) systemctl status myapp ;;
退出) break ;;
*) echo "无效选择" ;;
esac
done
# 后台并行
for host in web1 web2 web3; do
ssh "$host" "uptime" &
done
wait # 等待所有后台任务完成
# 限制并发数
MAX_PARALLEL=5
count=0
for host in $(cat hosts.txt); do
ssh "$host" "command" &
((count++))
[[ $count -ge $MAX_PARALLEL ]] && wait -n && ((count--))
done
wait
# 使用xargs并行
cat hosts.txt | xargs -P 5 -I {} ssh {} "uptime"
# 捕获信号
cleanup() {
echo "\n正在清理..."
rm -f "$TMPFILE"
exit 0
}
trap cleanup SIGINT SIGTERM
TMPFILE=$(mktemp)
echo "按Ctrl+C停止"
while true; do
echo "运行中..."
sleep 1
done
| 书名 | 作者 | 重点 |
|---|---|---|
| Linux命令行与Shell脚本编程大全 | Blum | Shell脚本全面覆盖 |
| UNIX/Linux系统管理技术手册 | Nemeth | 系统管理圣经 |
| Ansible: Up and Running | Lintner | Ansible实战 |
| 鸟哥的Linux私房菜 | 鸟哥 | 中文经典入门 |
| 认证 | 机构 | 级别 |
|---|---|---|
| LFCS | Linux Foundation | 基础系统管理 |
| LFCE | Linux Foundation | 高级系统工程师 |
| RHCSA | Red Hat | Red Hat管理员 |
| RHCE | Red Hat | Red Hat工程师 |
| CKA/CKAD | CNCF | Kubernetes管理员/开发者 |
# 文本处理速查
grep -E 'pattern' file # 扩展正则搜索
sed -i 's/old/new/g' file # 替换
awk '{print $1}' file # 提取列
sort | uniq -c | sort -rn # 频次统计
cut -d: -f1 file # 切列
tr 'A-Z' 'a-z' # 转小写
# 系统管理速查
systemctl status/start/stop/restart service
journalctl -u service -f # 跟踪日志
df -h / du -sh * # 磁盘使用
ps aux --sort=-%mem # 内存排序
ss -tlnp # 监听端口
iptables -L -n # 防火墙规则
crontab -e # 编辑定时任务
useradd -m -s /bin/bash user # 创建用户
# 网络诊断速查
ip addr / ip route # 网络配置
ping / traceroute # 连通测试
dig / nslookup # DNS查询
curl -I url # HTTP头检查
nc -zv host port # 端口测试
tcpdump -i eth0 port 80 # 抓包
$ for i in 1 2 3; do echo "第${i}次"; done
第1次 第2次 第3次
$ seq 1 5 | while read n; do echo "数字: $n"; done
数字: 1 数字: 2 数字: 3 数字: 4 数字: 5
#!/bin/bash
# wait-for-service.sh - 等待服务就绪
HOST="$1"; PORT="$2"; TIMEOUT=60
elapsed=0
while [[ $elapsed -lt $TIMEOUT ]]; do
if nc -z "$HOST" "$PORT" 2>/dev/null; then
echo "✅ $HOST:$PORT 已就绪 (${elapsed}s)"
exit 0
fi
echo "等待 $HOST:$PORT... (${elapsed}s)"
sleep 2; ((elapsed+=2))
done
echo "❌ 超时: $HOST:$PORT 未就绪" >&2; exit 1
# retry-with-backoff.sh - 指数退避重试
retry_backoff() {
local cmd="$1"; shift
local max="$1"; shift
local wait=1
for ((i=1; i<=max; i++)); do
if eval "$cmd"; then
return 0
fi
echo "重试 $i/$max, 等待${wait}s..."
sleep "$wait"
wait=$((wait * 2))
[[ $wait -gt 60 ]] && wait=60
done
return 1
}
#!/bin/bash
# wait-for-service.sh - 等待服务就绪
HOST="$1"; PORT="$2"; TIMEOUT=60; elapsed=0
while [[ $elapsed -lt $TIMEOUT ]]; do
nc -z "$HOST" "$PORT" 2>/dev/null && echo "Ready (${elapsed}s)" && exit 0
sleep 2; ((elapsed+=2))
done
echo "Timeout" >&2; exit 1
# retry_backoff - 指数退避
retry_backoff() {
local cmd="$1" max="$2" wait=1
for ((i=1; i<=max; i++)); do
eval "$cmd" && return 0
sleep "$wait"; wait=$((wait * 2))
[[ $wait -gt 60 ]] && wait=60
done
return 1
}
在实际生产环境中,循环优化与函数式编程是系统管理员必须深入掌握的核心能力。本节将探讨常见场景、最佳实践和避坑指南。
开发环境和生产环境的差异是脚本出错的常见原因。建议:
优化策略:
改善方法:
#!/bin/bash
# 循环优化与函数式编程最佳实践模板
set -euo pipefail
# 1. 参数校验
[[ $# -lt 1 ]] && echo "Usage: $0 <arg>" >&2 && exit 1
# 2. 环境检查
require_cmd() {
command -v "$1" >/dev/null || { echo "需要: $1" >&2; exit 1; }
}
# 3. 清理机制
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
# 4. 日志记录
log() { echo "[$(date +%T)] $*"; }
err() { log "ERROR: $*" >&2; exit 1; }
# 5. 主逻辑
main() {
log "开始处理: $1"
# 业务逻辑
log "处理完成"
}
main "$@"