You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于MySQL表数据批量执行bash的ssh与scp命令?

我之前维护过十几台同配置的Web服务器,跟你遇到过一模一样的问题——硬编码命令太蠢,加机器就得改脚本。下面给你几个落地的方案,完美解决从MySQL拉取服务器信息批量执行ssh/scp的需求:

第一步:先把服务器信息规范存入MySQL

首先得建个结构清晰的表,我一般这么设计:

CREATE TABLE servers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    ip VARCHAR(15) NOT NULL UNIQUE,
    username VARCHAR(50) NOT NULL,
    ssh_port INT NOT NULL DEFAULT 22,
    deploy_path VARCHAR(200) NOT NULL -- 可选字段,存远程部署路径,后续更灵活
);

把所有服务器的IP、登录用户、SSH端口都插入表中,以后新增机器直接插表就行,完全不用碰脚本。

方案一:逐条拉取命令,循环执行(最稳妥)

这是我日常用得最多的方式,能精准控制每条命令的执行状态,还能加错误处理。核心思路是让MySQL输出每条完整的ssh/scp命令(单独一行),然后用bash循环逐条执行。

比如批量执行SCP上传应用包的脚本:

#!/bin/bash

# 配置MySQL连接信息
DB_USER="your_db_user"
DB_PASS="your_db_password"
DB_NAME="your_ops_db"
LOCAL_APP_PATH="/local/your_app.tar.gz"

# 从MySQL拉取所有SCP命令,-N参数用于去掉查询结果的表头
mysql -u${DB_USER} -p${DB_PASS} ${DB_NAME} -N -e "
    SELECT CONCAT(
        'scp -P ', ssh_port, 
        ' ${LOCAL_APP_PATH} ', 
        username, '@', ip, ':', deploy_path
    ) AS cmd FROM servers;" | while read cmd; do
        echo "=== 正在执行: $cmd ==="
        # 执行命令并捕获结果
        if $cmd; then
            echo "✅ 执行成功"
        else
            echo "❌ 执行失败,错误码: $?"
            # 可选:失败后记录日志或发送告警
            echo "$(date) - FAIL: $cmd" >> /var/log/deploy_errors.log
        fi
    done

如果是批量执行SSH远程命令(比如重启应用服务),只需把MySQL查询里的CONCAT内容改成对应的SSH命令即可:

SELECT CONCAT(
    'ssh -p ', ssh_port, 
    ' ', username, '@', ip, 
    ' "sudo systemctl restart your_app.service"'
) AS cmd FROM servers;

方案二:生成临时脚本执行(适合简单场景)

如果不需要复杂的错误处理,也可以把所有命令导出成临时shell脚本,直接执行:

#!/bin/bash

DB_USER="your_db_user"
DB_PASS="your_db_password"
DB_NAME="your_ops_db"
LOCAL_APP_PATH="/local/your_app.tar.gz"

# 生成临时执行脚本
mysql -u${DB_USER} -p${DB_PASS} ${DB_NAME} -N -e "
    SELECT CONCAT(
        'scp -P ', ssh_port, 
        ' ${LOCAL_APP_PATH} ', 
        username, '@', ip, ':', deploy_path
    ) AS cmd FROM servers;" > /tmp/batch_deploy.sh

# 给脚本加执行权限并运行
chmod +x /tmp/batch_deploy.sh
echo "=== 开始批量执行 ==="
bash /tmp/batch_deploy.sh
# 执行完成后清理临时文件
rm /tmp/batch_deploy.sh

方案三:并行执行(适合大量服务器)

如果服务器数量多(比如几十台),串行执行效率太低,可以用xargs实现并行执行:

mysql -u${DB_USER} -p${DB_PASS} ${DB_NAME} -N -e "
    SELECT CONCAT(
        'scp -P ', ssh_port, 
        ' ${LOCAL_APP_PATH} ', 
        username, '@', ip, ':', deploy_path
    ) AS cmd FROM servers;" | xargs -I {} -P 8 bash -c "{}"

这里-P 8表示同时启动8个进程并行执行,你可以根据服务器性能调整这个数字。

避坑提醒

  1. 必须配置SSH免密登录:不然每条命令都会弹出密码提示,批量执行直接卡壳。可以用ssh-copy-id把本地公钥批量传到所有服务器。
  2. 特殊字符转义:如果用户名或IP包含特殊字符(比如空格),记得在MySQL的CONCAT里用QUOTE()函数包裹变量,避免bash解析出错:
    SELECT CONCAT(
        'scp -P ', QUOTE(ssh_port), 
        ' ${LOCAL_APP_PATH} ', 
        QUOTE(username), '@', QUOTE(ip), ':', QUOTE(deploy_path)
    ) AS cmd FROM servers;
    
  3. 一定要记日志:批量操作过程中出现问题时,日志是排查的关键,建议把执行结果统一写入日志文件。

内容的提问来源于stack exchange,提问作者Pierre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:23:15