本文目录导读:

- 为什么你还在手动搭建服务?——脚本化的核心价值
- 脚本搭建的三大基础招式
- 实战案例:一键部署Nginx + PHP + MySQL
- 进阶玩法:用Python脚本做健康检查与自动扩容
- 常见问题Q&A(附脚本避坑指南)
- 总结:从“会写脚本”到“脚本化思维”
**
《告别手动敲命令!3个Shell/Python脚本套路,10分钟搭建任意开发环境》
目录导读
- 为什么你还在手动搭建服务?——脚本化的核心价值
- 脚本搭建的三大基础招式(变量、循环、错误捕获)
- 实战案例:一键部署Nginx + PHP + MySQL(完整脚本拆解)
- 进阶玩法:用Python脚本做健康检查与自动扩容
- 常见问题Q&A(附脚本避坑指南)
- 从“会写脚本”到“脚本化思维”
为什么你还在手动搭建服务?——脚本化的核心价值
当你复制粘贴一条条命令时,有没有想过:如果今天要部署5台服务器,你还能淡定吗? 手动操作不仅耗时,还极易出错——少个空格、漏个依赖包,就可能让整个环境崩溃,而脚本化的本质,是把“人肉操作”变成“机器执行”,核心优势有三点:
- 可重复性:同一份脚本,在任意干净机器上跑出完全一致的环境。
- 可追踪性:脚本即文档,后期维护时一眼看穿所有配置逻辑。
- 极速交付:原来1小时的手工配置,脚本10秒完成(还不用喝咖啡提神)。
关键点:脚本不等于“一堆命令的堆砌”,而是带逻辑的编排。
脚本搭建的三大基础招式
在写任何脚本前,先掌握这三个基本动作,能让你少踩80%的坑。
变量化配置
不要写死路径和版本号。
NGINX_VERSION="1.24.0" INSTALL_DIR="/opt/nginx"
这样升级版本时只改一行,而不是全局搜索替换。
循环处理批量任务
假设要给10个用户创建目录并设置权限:
for user in alice bob carol dave eric frank grace henry ivy jack; do mkdir -p /data/$user chmod 700 /data/$user done
错误捕获与回滚
脚本最忌讳“死到半路不吭声”,用 set -e 让脚本在任意命令失败时立即退出,同时用 trap 捕获异常执行清理:
trap 'echo "Error on line $LINENO"; exit 1' ERR
实战案例:一键部署Nginx + PHP + MySQL
下面给出一份可直接运行的完整脚本(CentOS 7/8 + Ubuntu 20.04+ 均适用),请先阅读注释,再执行。
#!/bin/bash
# 一键搭建 LNMP 环境(Nginx + PHP + MySQL)
# 用法:chmod +x lnmp.sh && ./lnmp.sh
set -e # 任何错误即停止
# ========== 1. 全局变量 ==========
DB_ROOT_PASS="YourStrongPass123" # 请务必修改!
PHP_VERSION="7.4"
DOMAIN="localhost"
# ========== 2. 系统更新与依赖 ==========
echo "[1/5] 更新系统包..."
if [[ -f /etc/redhat-release ]]; then
yum update -y && yum install -y epel-release
yum groupinstall -y "Development Tools"
else
apt update -y && apt upgrade -y
apt install -y build-essential
fi
# ========== 3. 安装MySQL ==========
echo "[2/5] 安装MySQL..."
if [[ -f /etc/redhat-release ]]; then
yum install -y mysql-server
systemctl start mysqld && systemctl enable mysqld
# 设置root密码(需先跳过默认密码策略)
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASS}';"
else
apt install -y mysql-server
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '${DB_ROOT_PASS}';"
fi
# ========== 4. 安装PHP及扩展 ==========
echo "[3/5] 安装PHP..."
if [[ -f /etc/redhat-release ]]; then
yum install -y php php-fpm php-mysql php-gd php-mbstring
else
apt install -y php php-fpm php-mysql php-gd php-mbstring
fi
systemctl start php-fpm && systemctl enable php-fpm
# ========== 5. 安装Nginx并配置站点 ==========
echo "[4/5] 安装Nginx..."
if [[ -f /etc/redhat-release ]]; then
yum install -y nginx
else
apt install -y nginx
fi
# 生成简易站点配置(用heredoc一次性写入)
cat > /etc/nginx/conf.d/${DOMAIN}.conf <<EOF
server {
listen 80;
server_name ${DOMAIN};
root /var/www/html;
index index.php index.html index.htm;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php${PHP_VERSION}-fpm.sock;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
}
}
EOF
# 创建测试页面
echo "<?php phpinfo(); ?>" > /var/www/html/index.php
# ========== 6. 启动与验证 ==========
echo "[5/5] 启动服务..."
systemctl restart nginx php-fpm mysql
echo "✅ 全部安装成功!请浏览器访问:http://${DOMAIN}/index.php"
脚本逻辑解读:
- 用
if判断操作系统类型,实现跨平台兼容。 - 用
systemctl统一管理服务(旧系统可改用service)。 - 利用 Heredoc 生成配置文件,避免手动编辑。
- 每完成一步输出提示,方便定位错误。
进阶玩法:用Python脚本做健康检查与自动扩容
Shell能解决“搭环境”,但运维监控还得靠Python,比如这个健康检查脚本,每5分钟检查一次Nginx是否存活,挂了就重启并发送通知:
import requests, subprocess, time, smtplib
def check_health():
try:
r = requests.get("http://localhost", timeout=3)
if r.status_code != 200:
raise Exception("HTTP 500 detected")
except:
subprocess.run(["systemctl", "restart", "nginx"])
send_alert("Nginx restarted at " + time.ctime())
def send_alert(msg):
# 这里填你的邮件/钉钉/微信机器人Webhook
pass
while True:
check_health()
time.sleep(300)
脚本化思维拓展:
- 配合云厂商API,可通过脚本自动购买并配置新ECS实例,实现自动扩容。
- 将脚本放入Git仓库,配合Jenkins/GitLab CI,即可实现“提交代码→自动部署测试环境”的DevOps流水线。
常见问题Q&A(附脚本避坑指南)
Q1:脚本执行到一半报错,如何快速定位问题?
A:用 bash -x ./script.sh 运行脚本,它会打印每一步的实际执行命令和结果,在每个步骤前加 echo 标记(如上述脚本中的 [1/5]),能让你知道卡在第几步。
Q2:如何避免密码明文出现在脚本中?
A:用环境变量或配置文件。
export DB_PASS=$(cat /etc/mysql_secret)
或者使用 ansible-vault 加密整份脚本。
Q3:脚本里可以直接用 rm -rf 吗?
A:绝对不要! 尤其是变量路径时,若变量为空会导致 rm -rf / 的悲剧,建议加上防护:
if [[ "$dir" == "/srv"* ]]; then rm -rf "$dir"; fi
Q4:如何让脚本在服务器重启后自动执行?
A:将脚本写入 /etc/rc.local(需要执行权限),或者用systemd服务管理。
Q5:本地测试OK,但生产环境报错“command not found”?
A:多半是PATH环境变量问题,脚本开头加 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 即可解决。
从“会写脚本”到“脚本化思维”
今天展示的只是冰山一角,真正的牛人,会把“搭建服务”拆解为“定义状态”——先画依赖图,再写幂等脚本,最后用Ansible/SaltStack做批量分发,但万变不离其宗:用变量代替硬编码,用函数封装复用,用条件判断实现容错。
立刻打开你的终端,拿今天这份LNMP脚本试一试,第一次跑通后,你会感受到“一键部署”的快感,从此以后,你不再是一名“敲命令的运维”,而是一名“写脚本的工程师”。
文章结束