4. 配置文件批量修改工具

任务说明

开发一个Python命令行工具,通过SSH连接多台服务器,批量修改指定配置文件中某个参数的值。工具需支持:从文本文件读取服务器列表、指定参数名与新值、自动备份原配置文件、输出每台服务器的执行结果。

环境依赖

需要安装 paramiko(SSH连接库):

pip install paramiko

完整实现


import paramiko
import sys
import os
from datetime import datetime

def read_servers(file_path):
    """读取服务器列表文件,格式: hostname|port|username|password"""
    servers = []
    with open(file_path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if line and not line.startswith('#'):
                parts = line.split('|')
                if len(parts) == 4:
                    servers.append({
                        'host': parts[0].strip(),
                        'port': int(parts[1].strip()),
                        'user': parts[2].strip(),
                        'pwd': parts[3].strip()
                    })
    return servers

def modify_config(server, config_path, param_name, new_value):
    """在单台服务器上修改配置文件参数"""
    result = {'host': server['host'], 'success': False, 'message': ''}
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(server['host'], port=server['port'],
                       username=server['user'], password=server['pwd'],
                       timeout=10)
        # 备份原文件
        backup_cmd = f"cp {config_path} {config_path}.bak_{datetime.now().strftime('%Y%m%d%H%M%S')}"
        stdin, stdout, stderr = client.exec_command(backup_cmd)
        err = stderr.read().decode()
        if err:
            result['message'] = f"备份失败: {err.strip()}"
            return result

        # 使用sed替换参数值(支持key = value或key=value格式)
        sed_cmd = f"sed -i 's/^\\s*{param_name}\\s*=.*/{param_name} = {new_value}/' {config_path}"
        stdin, stdout, stderr = client.exec_command(sed_cmd)
        err = stderr.read().decode()
        if err:
            result['message'] = f"修改失败: {err.strip()}"
            return result

        # 验证修改结果
        grep_cmd = f"grep '^{param_name}\\s*=' {config_path}"
        stdin, stdout, stderr = client.exec_command(grep_cmd)
        output = stdout.read().decode().strip()
        if output:
            result['success'] = True
            result['message'] = f"已修改为: {output}"
        else:
            result['message'] = "修改后未找到该参数,请检查参数名"
        return result
    except Exception as e:
        result['message'] = f"连接或执行错误: {str(e)}"
        return result
    finally:
        client.close()

def main():
    if len(sys.argv) != 5:
        print("用法: python config_batch_modify.py <服务器列表> <配置文件路径> <参数名> <新值>")
        print("示例: python config_batch_modify.py servers.txt /etc/app.conf max_connections 200")
        sys.exit(1)

    server_file = sys.argv[1]
    config_path = sys.argv[2]
    param_name = sys.argv[3]
    new_value = sys.argv[4]

    if not os.path.exists(server_file):
        print(f"错误: 服务器列表文件 {server_file} 不存在")
        sys.exit(1)

    servers = read_servers(server_file)
    if not servers:
        print("错误: 服务器列表为空")
        sys.exit(1)

    print(f"开始批量修改 {len(servers)} 台服务器...")
    success_count = 0
    for server in servers:
        result = modify_config(server, config_path, param_name, new_value)
        status = "✓" if result['success'] else "✗"
        print(f"[{status}] {result['host']}: {result['message']}")
        if result['success']:
            success_count += 1

    print(f"\n完成: 成功 {success_count}/{len(servers)} 台")
    if success_count < len(servers):
        sys.exit(2)

if __name__ == "__main__":
    main()

运行方式

1. 创建服务器列表文件 servers.txt,每行一台服务器,格式为:

192.168.1.10|22|root|password123
192.168.1.11|22|root|password456
# 192.168.1.12|22|root|password789  (以#开头的行为注释,可跳过)

2. 执行批量修改命令:

python config_batch_modify.py servers.txt /etc/myapp.conf max_connections 200

验证方法

程序执行后观察输出:

  • 每台服务器前显示 ✓ 表示修改成功,并回显修改后的参数行内容;显示 ✗ 表示失败及原因。
  • 最终输出“成功 N/M 台”,若全部成功则退出码为0,部分失败退出码为2。
  • 登录任意一台服务器,执行 grep '^max_connections' /etc/myapp.conf 可看到参数值已更新为200。
  • 原配置文件已自动备份为 /etc/myapp.conf.bak_时间戳,可通过 ls /etc/myapp.conf.bak_* 查看。

注意:该工具使用密码认证方式连接服务器,生产环境建议改用SSH密钥认证;sed命令仅匹配行首为参数名的配置项,适用于 key = value 或 key=value 格式的配置文件。