写好运维 Shell 脚本,核心在于:稳定、可维护、可复用、可排错。下面从“原则 → 规范 → 实用技巧 → 常见坑 → 示例”系统讲一下。
一个脚本只做一件事,例如:
避免“万能脚本”(后期维护噩梦)
多次执行结果一致,例如:
[ -d "/data/log" ] || mkdir -p /data/log
#!/usr/bin/env bash
比 #!/bin/sh 更好,功能更强。
set -euo pipefail
含义:
-e:命令失败立即退出-u:使用未定义变量报错-o pipefail:管道中任一命令失败整体失败BASE_DIR="/data/app"
LOG_FILE="${BASE_DIR}/deploy.log"
✅ 建议:
{} 包裹log() {
echo "[$(date '+%F %T')] $*"
}
log "开始部署应用"
日志要包含:
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/data/app"
LOG_FILE="${BASE_DIR}/ops.log"
log() {
echo "[$(date '+%F %T')] $*" | tee -a "$LOG_FILE"
}
check_env() {
command -v docker >/dev/null || {
log "docker 未安装"
exit 1
}
}
main() {
log "脚本开始执行"
check_env
log "环境检查通过"
}
main "$@"
ACTION=${1:-start}
case "$ACTION" in
start) echo "启动" ;;
stop) echo "停止" ;;
*) echo "用法: $0 {start|stop}" ;;
esac
if ! systemctl restart nginx; then
log "nginx 重启失败"
exit 1
fi
trap 'log "脚本异常退出"; exit 1' ERR
LOCK_FILE="/tmp/deploy.lock"
if [ -f "$LOCK_FILE" ]; then
echo "已有实例在运行"
exit 1
fi
touch "$LOCK_FILE"
trap "rm -f $LOCK_FILE" EXIT
for i in {1..5}; do
curl -s localhost:8080 && break
sleep 2
done
❌ 使用 sh script.sh(可能忽略 bash 特性)
❌ 没检查命令是否存在
❌ 变量不加引号(空格直接炸)
❌ 用 rm -rf $DIR/(DIR 为空直接删根)
❌ 脚本里写密码明文
✅ 正确做法:
rm -rf "${DIR:?}/tmp"
init_env()
check_service()
start_service()
source config.env
[ "$(id -u)" -eq 0 ] && echo "不要用 root 执行"
*/5 * * * * /opt/scripts/check_nginx.sh >> /var/log/check.log 2>&1
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/data/backup"
SRC_DIR="/var/www/html"
DATE=$(date +%F)
FILE="backup-${DATE}.tar.gz"
log() {
echo "[$(date '+%F %T')] $*"
}
mkdir -p "$BACKUP_DIR"
log "开始备份 $SRC_DIR"
tar -czf "${BACKUP_DIR}/${FILE}" "$SRC_DIR"
log "备份完成: $FILE"
好的运维 Shell 脚本 = 像写代码一样写脚本,而不只是“敲命令”
如果你愿意,我可以:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。