告别凌晨3点上线:一个Shell脚本如何拯救了我的发际线

我还记得2019年的那个冬天,那是我们团队最黑暗的一段日子。

那时候,我是个刚升职的技术主管,手下带着4个开发兄弟。为了赶业务进度,我们几乎每周都要发两个版本。那时候的发布流程全靠"人肉":本地打包 Jar 包,用 FTP 传到服务器,手动杀进程,再手动启动,盯着滚动的日志祈祷不要报错。

有一次凌晨3点,眼皮打架的我,在生产环境误删了一个配置文件。虽然只花了15分钟恢复,但这15分钟里,我的心跳大概有一百八。也就是在那个吃着已经凉透的泡面的深夜,我突然意识到:我们要对抗的不是复杂的业务逻辑,而是对"人肉操作"的盲目自信。

如果你也正身处在一个没有专职运维、资源有限的中小团队,每天在写代码和修服务器之间反复横跳,那么这篇文章就是写给你的。我想和你聊聊,我是如何用最土、但也最管用的 Shell 脚本,把团队从发布的焦虑中解救出来的。

承认吧,“高级工具"有时是甜蜜陷阱

刚开始想做自动化部署时,我也陷入过"工具崇拜"的怪圈。

我看遍了网上的 DevOps 教程,试图在只有几台服务器的环境里搭建一套完整的 Jenkins + Docker + K8s。结果呢?我和团队花了整整两周时间去折腾环境,陷入了无尽的配置地狱。

你的团队规模和业务复杂度,决定了你的工具选择。

对于只有几台机器、且业务架构相对简单的中小团队来说,有时候一把瑞士军刀(Shell)比重型机械(K8s)更趁手。

我做了一个大胆的决定:砍掉所有重型工具,回归最原始的 Shell 脚本。我们的目标很简单——让任何人(哪怕是新来的实习生)都能在3分钟内,安全地完成一次发布。

哪怕是最笨的脚本,也比聪明的人脑可靠

为了落地这个想法,我花了一个周末,写了一个名为 deploy.sh 的脚本。它不通过什么高大上的平台触发,就静静地躺在服务器的 /opt/scripts 目录下。

这个脚本没有什么高深的语法,逻辑非常线性,全是笨功夫:

  1. 备份(Backup): 永远给自己留条后路。
  2. 停止(Stop): 优雅关闭,而不是直接 kill -9
  3. 部署(Deploy): 移动文件,建立软链接。
  4. 启动(Start): 启动服务。
  5. 体检(Health Check): 最关键的一步,脚本替你确认服务是否活过来了。

这其中,最让我和团队受益的,是那个简单的"健康检查"函数。以前我们发布完,得瞪大眼睛盯着日志看半天,生怕漏掉一个 Exception。现在,脚本替我们做这件事。

这里分享一段我用了3年的核心逻辑(去敏版),它很简单,但无数次救了我的命:

# 健康检查函数示例
check_health() {
    echo "正在检查服务状态..."
    for i in {1..10}; do
        # 请求应用的健康检查接口
        http_code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/actuator/health)
        
        if [ "$http_code" == "200" ]; then
            echo -e "\033[32m[SUCCESS] 服务启动成功!HTTP 状态码: $http_code \033[0m"
            return 0
        fi
        
        echo "等待服务启动中... ($i/10)"
        sleep 5
    done
    
    echo -e "\033[31m[ERROR] 服务启动超时或失败,请立即检查日志!\033[0m"
    # 这里甚至可以加上发送钉钉/企微报警的逻辑
    return 1
}

当屏幕上出现那行绿色的 [SUCCESS] 时,那种多巴胺分泌的快乐,比写出一段精妙的代码还要强烈。因为它意味着:今晚可以按时回家了。

脚本之外:建立"不焦虑"的发布文化

有了脚本只是第一步,更重要的是改变习惯。

配图

起初,团队里的老开发老李很抵触,他觉得:“我手动搞了两年也没出大事,敲个脚本命令反而觉得心里没底,不知道它在后台干了啥。”

这很正常,恐惧源于不可控。

为了消除这种顾虑,我做了一件小事:把脚本代码纳入版本管理,并邀请大家一起 Review。

我们在周五下午的例会(我习惯在这个时候买点奶茶,大家心态比较放松)上,逐行讲解脚本的逻辑。当大家看到脚本里把 cp(复制)改成了 rsync(同步),把粗暴的 kill 变成了循环检测 pid 消失时,信任感建立起来了。

后来,老李成了这个脚本的维护主力。有一次,他在脚本里增加了一个"回滚"功能——只需要加一个 -r 参数,就能在一分钟内把服务切回上一个备份版本。

那次改动后的一个月,线上出现了一个严重的空指针异常。当时正好我在高铁上,信号极差。老李在群里淡定地回了一句:“别慌,我执行了回滚。”

配图

那一刻,我知道,我们终于从"发布焦虑症"中毕业了。我们不再依赖某个人的"高超手速”,而是依赖一套固化的、可重复的逻辑。

给你的落地建议

如果你也想开始这段旅程,不需要等到下个季度,也不需要申请什么大笔预算。我也不建议你一上来就去追求所谓完美的 DevOps 流程。

你可以从这三个具体的动作开始:

  1. 标准化路径: 无论你有几台服务器,请确保应用包、日志、配置文件的路径是完全一致的。这是自动化的基石。
  2. 写出你的第一个备份函数: 哪怕现在的发布还是手动的,先写一个脚本专门用来做"发布前备份"。这是你建立信心的第一步。
  3. 把"检查"交给机器: 别再用肉眼看日志来判断服务是否启动了,写一个简单的 curl 脚本来探测接口,它比你疲惫的双眼更诚实。

回头看这几年,那个几百行的 Shell 脚本虽然简陋,甚至有点"土",但它却是我们团队最宝贵的资产之一。它不仅是一个工具,更是一种承诺——它承诺我们在追求技术效率的同时,也能拥有属于自己的生活。

技术是为了让人活得更有尊严,而不是更累,不是吗?


最后,想问问大家:

在你经历过的发布流程中,发生过什么让你"心跳停止"的事故?或者你有什么独门的"偷懒"小技巧?

欢迎在评论区聊聊,哪怕只是吐槽一下,也是一种治愈。