你已经在终端里敲过几十条命令了。但 DevOps 不是一条一条敲的——是写成脚本,自动跑的。
CI/CD 流水线的每一个步骤、服务器的启动脚本、定时备份任务、健康检查——本质都是 Shell 脚本。这节课让你从「手动敲命令」升级到「写脚本自动执行」。
一个 Shell 脚本就是一个包含一系列命令的文本文件,你给它执行权限,它按顺序跑。
#!/bin/bash
# 这是我的第一个脚本
echo "Hello, DevOps!"
date
whoami
拆解:
#!/bin/bash — Shebang(#!),告诉系统用哪个解释器执行这个脚本# 这是我的第一个脚本 — 注释,`#` 开头就是注释#!/bin/bash vs #!/bin/sh:bash 是 sh 的超集,有更多功能(数组、[[ ]]、更好的语法)。Ubuntu 上 /bin/sh 是 dash(更小更快但功能少)。DevOps 脚本默认用 bash。
在终端里跟着敲。边敲边理解。
#!/bin/bash
APP_NAME="my-app" # 定义变量(等号两边不能有空格!)
VERSION=1.0.0
echo "Deploying $APP_NAME v$VERSION" # $变量名 取值
echo "Path: ${APP_NAME}-${VERSION}" # ${} 避免歧义
# 命令替换:把命令的输出赋给变量
CURRENT_DATE=$(date +%Y-%m-%d)
echo "Today is $CURRENT_DATE"
#!/bin/bash
if [ "$1" == "production" ]; then # $1 = 第一个命令行参数
echo "⚠️ Deploying to PRODUCTION!"
elif [ "$1" == "staging" ]; then
echo "Deploying to staging..."
else
echo "Usage: $0 "
exit 1 # 非 0 = 出错
fi
# 文件/目录判断(DevOps 高频)
if [ -f ".env" ]; then # -f = 文件存在?
echo ".env file found"
fi
if [ -d "/var/log" ]; then # -d = 目录存在?
echo "log directory exists"
fi
| 测试 | 含义 |
|---|---|
[ -f file ] | file 存在且是普通文件 |
[ -d dir ] | dir 存在且是目录 |
[ -z "$var" ] | $var 为空字符串 |
[ -n "$var" ] | $var 非空 |
[ "$a" == "$b" ] | 字符串相等 |
[ $a -eq $b ] | 整数相等 |
#!/bin/bash
# 对列表中的每一项执行操作
SERVICES="nginx docker postgresql"
for svc in $SERVICES; do
echo "Restarting $svc..."
sudo systemctl restart $svc
done
# 或者遍历命令输出
for container in $(docker ps -q); do
echo "Container: $container"
done
#!/bin/bash
# 定义函数
check_service() {
local service_name=$1 # local = 局部变量
if systemctl is-active --quiet "$service_name"; then
echo "✅ $service_name is running"
return 0
else
echo "❌ $service_name is DOWN!"
return 1
fi
}
# 调用函数
check_service "nginx"
check_service "docker"
默认情况下,Shell 脚本遇到错误不会停——它继续执行下一行,特别危险。
#!/bin/bash
set -e # 任何命令返回非 0 就立刻退出
set -u # 使用未定义变量就报错退出
set -o pipefail # 管道中任何一个命令失败,整个管道算失败
# 这三个通常是 DevOps 脚本的前三行(写在 shebang 之后)
# 如果你预期某个命令可能失败,用 || true
grep "maybe-not-there" /etc/hosts || true # 找不到也不退出
# 自定义错误处理
trap 'echo "❌ Script failed on line $LINENO"' ERR
#!/bin/bash
set -euo pipefail
# Script: deploy.sh
# Purpose: Deploy application to target environment
这是一个真实 DevOps 场景:部署之前,检查所有前置条件。
#!/bin/bash
set -euo pipefail
# === Config ===
REQUIRED_SPACE_MB=500
REQUIRED_SERVICES="docker"
# === Colors (optional, makes output pretty) ===
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
echo "=== Pre-deployment Check ==="
# 1. Check disk space
echo -n "Checking disk space... "
AVAILABLE=$(df / --output=avail | tail -1 | tr -d ' ')
AVAILABLE_MB=$((AVAILABLE / 1024))
if [ "$AVAILABLE_MB" -lt "$REQUIRED_SPACE_MB" ]; then
echo -e "${RED}FAIL${NC} (${AVAILABLE_MB}MB < ${REQUIRED_SPACE_MB}MB)"
exit 1
fi
echo -e "${GREEN}OK${NC} (${AVAILABLE_MB}MB)"
# 2. Check required services
for svc in $REQUIRED_SERVICES; do
echo -n "Checking $svc... "
if systemctl is-active --quiet "$svc" 2>/dev/null; then
echo -e "${GREEN}running${NC}"
else
echo -e "${RED}not running${NC}"
exit 1
fi
done
# 3. Check .env file
echo -n "Checking .env... "
if [ -f ".env" ]; then
echo -e "${GREEN}found${NC}"
else
echo -e "${RED}missing${NC}"
exit 1
fi
echo -e "\n${GREEN}✅ All checks passed! Ready to deploy.${NC}"
把这个保存为 pre-deploy-check.sh,加执行权限,你就有了一套标准化部署检查。
任务:写一个脚本 health-check.sh,接受一个服务名作为参数,检查:
systemctl is-active)ss -tlnp | grep 端口号)——用 if 判断# 模板(填空)
#!/bin/bash
set -euo pipefail
SERVICE=$1
if [ -z "____" ]; then
echo "Usage: $0 "
exit 1
fi
# Check service status
if ______ is-active --quiet "$SERVICE"; then
echo "✅ $SERVICE is running"
else
echo "❌ $SERVICE is not running"
exit 1
fi
# Check port (hint: nginx=80, docker=2375)
# Bonus: make port configurable
shellcheck your-script.sh — 安装:sudo apt install shellcheck你已经有了命令行基础、Git 进阶、Shell 脚本三项核心技能。下一课我们进入 DevOps 的第一个「重型武器」:Docker 入门——用容器化你的前端/后端项目,告别「在我机器上能跑」。
shellcheck,它比你自己检查快 10 倍。