常用自动化工具的基本概念和使用场景总结,自动化工具安装和完成对主机列表A,B,C进行拷贝一个脚本,并调用执行

常用自动化工具的基本概念和使用场景总结

一、概述

本文解析 Shell 脚本、Ansible、Fabric、SaltStack 四款主流自动化运维工具的技术原理、核心概念与适用场景,并基于 Ubuntu 24.04 环境(控制机:10.0.0.13,目标机:10.0.0.14/10.0.0.16),完整实现「批量拷贝脚本+执行」的全流程实操。针对 Ubuntu 24.04 下 SaltStack/Ansible 安装兼容性问题,提供可直接落地的生产级解决方案,覆盖从基础原理到实战落地的全维度内容。

二、自动化运维工具核心原理与生态梳理

2.1 核心技术维度对比

维度Shell 脚本AnsibleFabricSaltStack
架构模式无架构(命令行串联)无代理架构(Agentless)无代理架构(Python 封装 SSH)有代理架构(C/S,Master/Minion)
通信协议SSHSSHSSHZeroMQ + SSH(备用)
配置方式命令行/Shell 语法YAML(Playbook/Inventory)Python 代码YAML(SLS 状态文件)
执行引擎系统 Shell 解释器(bash/sh)Ansible Core(Python 编写)Fabric 库(Python 编写)Salt Master/Minion 守护进程
依赖基础系统原生组件(无额外依赖)Python + SSHPython + SSH + Fabric 库Python + ZeroMQ + 系统服务
并发能力串行执行(需手动实现并发)轻量级并发(默认5线程)自定义并发(Python 线程/进程)高并发(支持千级节点)
状态管理无(仅命令执行)支持(幂等性操作)无(需手动实现)强支持(SLS 状态文件,幂等性)
学习成本低(基础Shell语法)中(YAML+Ansible模块)中(Python基础+Fabric API)高(C/S架构+SLS语法+配置项多)

2.2 核心概念

(1)Shell 脚本
  • 核心定义:基于操作系统 Shell 解释器,将一系列运维命令按逻辑串联成可执行文件,实现简单自动化的工具。
  • 核心概念
    • 循环语句(for/while):实现多主机批量操作;
    • SSH 免密登录:核心依赖,避免手动输入密码;
    • 退出码($?):判断命令执行结果,实现错误处理;
    • SCP:基于 SSH 的文件传输工具,实现脚本分发。
  • 技术原理:通过 Shell 解释器逐行执行命令,利用 SSH/SCP 实现跨主机操作,无中间层,直接对接系统内核。
(2)Ansible
  • 核心定义:基于 Python 开发的开源配置管理和自动化部署工具,采用无代理架构,通过 SSH 实现跨主机自动化。
  • 核心概念
    • Inventory(主机清单):定义被管理主机的分组、变量、连接信息;
    • Playbook(剧本):YAML 格式的配置文件,包含多个 Play,每个 Play 定义对一组主机的操作;
    • Module(模块):Ansible 核心执行单元(如 copy/command/service),幂等性设计;
    • Task(任务):单个操作单元(如执行一个模块);
    • Role(角色):Playbook 的模块化封装,实现配置复用。
  • 技术原理:控制机通过 SSH 连接目标机,将模块化的 Python 脚本(模块)推送到目标机执行,执行完成后删除临时文件,无残留。
(3)Fabric
  • 核心定义:基于 Python 的 SSH 封装库,将复杂的 SSH 操作抽象为简洁的 Python API,实现代码化的运维自动化。
  • 核心概念
    • Connection(连接):封装单个主机的 SSH 连接信息;
    • Task(任务):自定义 Python 函数,实现具体运维操作;
    • put/get:文件上传/下载 API;
    • run/sudo:远程执行命令/特权命令 API。
  • 技术原理:通过 Python 的 paramiko 库(SSH 协议实现)封装 SSH 连接、命令执行、文件传输等操作,以代码方式替代手动 SSH 操作,灵活性更高。
(4)SaltStack
  • 核心定义:基于 Python 开发的企业级自动化运维平台,采用 C/S 架构,支持批量执行、配置管理、远程执行等功能。
  • 核心概念
    • Master(主控端):集中管理 Minion,下发指令、接收返回结果;
    • Minion(被控端):部署在目标主机的代理进程,接收 Master 指令并执行;
    • Grains(静态数据):Minion 端的静态属性(如系统版本、IP、硬件信息);
    • Pillar(动态数据):Master 下发给 Minion 的动态配置(如密码、密钥);
    • SLS(状态文件):YAML 格式的配置文件,定义 Minion 的最终状态(幂等性);
    • Salt Key:Master 与 Minion 之间的密钥认证,确保通信安全。
  • 技术原理:Master 与 Minion 建立长连接(ZeroMQ),Master 下发指令后,Minion 异步执行并返回结果,支持实时性、高并发的大规模集群管理。

2.3 适用场景精准匹配

工具最佳适用场景不适用场景典型用户群体
Shell 脚本1. 临时运维操作(如批量重启服务);
2. 小型集群(≤5台)的简单批量操作;
3. 无额外依赖的极简场景
1. 大规模集群(≥10台);
2. 需幂等性的配置管理
运维新手、小型企业运维
Ansible1. 中小规模集群(≤50台)的配置管理;
2. 批量部署/软件安装;
3. 无代理架构的合规场景
1. 超大规模集群(≥100台);
2. 高实时性需求
中小企业运维、云原生运维
Fabric1. 定制化运维场景(如复杂的跨主机逻辑);
2. Python 生态集成的自动化;
3. 灵活的批量执行
1. 需状态管理的场景;
2. 零基础运维人员使用
开发型运维、Python 开发者
SaltStack1. 大规模集群(≥50台)的批量管理;
2. 高并发/实时性运维需求;
3. 企业级状态管理
1. 小型集群(性价比低);
2. 无公网/内网隔离场景
大型企业运维、云服务商运维

三、前置统一准备

3.1 控制机 SSH 免密登录配置

SSH 免密是所有无代理架构工具的核心依赖,需优先配置:

# 1. 控制机(10.0.0.13)生成 SSH 密钥(全程无密码回车)
ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa

# 2. 推送公钥到所有目标机(首次执行需手动输入目标机root密码)
for host in 10.0.0.14 10.0.0.16; do
    ssh-copy-id -i ~/.ssh/id_rsa.pub root@$host
done

# 3. 验证免密登录(无密码提示且输出"免密登录成功"即为合格)
for host in 10.0.0.14 10.0.0.16; do
    ssh root@$host "echo '✅ $host 免密登录成功'"
done

3.2 待分发执行的测试脚本准备

控制机创建 /root/test_script.sh,用于验证批量执行效果:

#!/bin/bash
# 测试脚本:输出主机基础信息(幂等性设计,可重复执行)
set -e  # 遇到错误立即退出

# 输出主机标识信息
echo -e "\n===== 脚本执行成功 - 主机信息 ====="
echo "主机IP: $(hostname -I | awk '{print $1}')"
echo "主机名: $(hostname)"
echo "系统版本: $(lsb_release -d | awk -F: '{print $2}' | sed 's/^ //')"
echo "执行时间: $(date +'%Y-%m-%d %H:%M:%S')"
echo "====================================="

# 可选:添加自定义业务逻辑(如创建测试文件)
touch /tmp/script_executed_$(date +%Y%m%d).log
echo "脚本执行日志已生成" >> /tmp/script_executed_$(date +%Y%m%d).log

赋予执行权限:

chmod +x /root/test_script.sh

四、方案1:原生 Shell 脚本实现

4.1 脚本编写(生产级优化版)

控制机创建 /root/batch_execute.sh,包含错误处理、日志输出:

#!/bin/bash
# 批量分发并执行脚本的 Shell 脚本(生产级)
set -euo pipefail

# 配置区
TARGET_HOSTS=("10.0.0.14" "10.0.0.16")  # 目标主机列表
LOCAL_SCRIPT="/root/test_script.sh"     # 本地脚本路径
REMOTE_SCRIPT="/tmp/test_script.sh"     # 远程脚本路径
LOG_FILE="/root/batch_exec.log"         # 执行日志文件

# 日志函数
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1"
}

# 前置检查
if [ ! -f "$LOCAL_SCRIPT" ]; then
    log "❌ 错误:本地脚本 $LOCAL_SCRIPT 不存在"
    exit 1
fi

if [ ! -x "$LOCAL_SCRIPT" ]; then
    log "⚠️  警告:本地脚本无执行权限,自动添加"
    chmod +x "$LOCAL_SCRIPT"
fi

# 批量处理主机
log "===== 开始批量执行脚本 ====="
for host in "${TARGET_HOSTS[@]}"; do
    log "===== 处理主机 $host ====="
    # 1. 拷贝脚本到目标机
    if scp -o ConnectTimeout=10 "$LOCAL_SCRIPT" root@$host:"$REMOTE_SCRIPT"; then
        log "✅ $host:脚本拷贝成功"
        # 2. 执行脚本
        if ssh -o ConnectTimeout=10 root@$host "chmod +x $REMOTE_SCRIPT && $REMOTE_SCRIPT"; then
            log "✅ $host:脚本执行成功"
        else
            log "❌ $host:脚本执行失败"
        fi
    else
        log "❌ $host:脚本拷贝失败(SSH连接超时/权限错误)"
    fi
done

log "===== 批量执行完成 ====="
echo -e "\n📊 执行日志已保存至:$LOG_FILE"

4.2 执行与验证

# 赋予执行权限
chmod +x /root/batch_execute.sh

# 执行脚本
/root/batch_execute.sh

# 验证结果(查看目标机执行日志)
ssh root@10.0.0.14 "cat /tmp/script_executed_$(date +%Y%m%d).log"

五、方案2:Ansible 实现(无代理架构)

5.1 Ansible 安装(Ubuntu 24.04 适配版)

Ubuntu 24.04 官方源 Ansible 版本较低,采用 pip 安装最新版:

# 安装依赖
apt update && apt install -y python3-pip python3-dev libffi-dev libssl-dev sshpass

# 安装 Ansible(避开系统源限制)
pip3 install ansible --break-system-packages

# 验证安装
ansible --version  # 输出版本信息即为成功

5.2 配置与 Playbook 编写

(1)主机清单配置

创建 /etc/ansible/hosts(无则新建):

[target_hosts]
10.0.0.14 ansible_ssh_user=root ansible_ssh_timeout=10
10.0.0.16 ansible_ssh_user=root ansible_ssh_timeout=10

[target_hosts:vars]
ansible_ssh_private_key_file=/root/.ssh/id_rsa  # SSH私钥路径
ansible_become=yes                              # 开启提权
ansible_become_method=sudo                      # 提权方式
ansible_become_user=root                        # 提权用户
(2)Playbook 编写(幂等性设计)

创建 /root/batch_script.yml

- hosts: target_hosts
  gather_facts: true  # 收集主机基础信息
  become: yes         # 提权执行
  vars:
    local_script: "/root/test_script.sh"
    remote_script: "/tmp/test_script.sh"
  tasks:
    # 1. 拷贝脚本(幂等性:仅当文件不同时更新)
    - name: Copy test script to remote hosts
      copy:
        src: "{{ local_script }}"
        dest: "{{ remote_script }}"
        mode: '0755'
        force: yes  # 覆盖已存在的脚本
      register: copy_result
      tags: [copy, script]

    # 2. 执行脚本(仅当拷贝成功时执行)
    - name: Execute test script on remote hosts
      command: "{{ remote_script }}"
      register: exec_result
      when: copy_result is succeeded
      tags: [execute, script]

    # 3. 输出执行结果(格式化)
    - name: Show execution result
      debug:
        msg: |
          🎯 主机 {{ inventory_hostname }} 执行结果:
          {{ exec_result.stdout }}
      when: exec_result is defined
      tags: [show, script]

    # 4. 验证执行结果(检查日志文件)
    - name: Verify script execution
      stat:
        path: "/tmp/script_executed_{{ ansible_date_time.date }}.log"
      register: log_file
      tags: [verify, script]

    - name: Show verify result
      debug:
        msg: "✅ {{ inventory_hostname }}:日志文件已生成"
      when: log_file.stat.exists
      tags: [verify, script]

5.3 执行与验证

# 执行 Playbook(指定标签,灵活执行)
ansible-playbook /root/batch_script.yml --tags copy,execute,show

# 验证结果(批量检查目标机)
ansible target_hosts -m command -a "cat /tmp/script_executed_$(date +%Y%m%d).log"

六、方案3:Fabric 实现(Python 定制化)

6.1 Fabric 环境搭建

# 创建虚拟环境(隔离依赖,避免污染系统Python)
apt install -y python3-venv
python3 -m venv /root/fabric-venv

# 激活虚拟环境
source /root/fabric-venv/bin/activate

# 安装 Fabric(最新稳定版)
pip install fabric==2.7.1  # 指定版本,避免兼容性问题

# 验证安装
fab --version  # 输出版本信息即为成功

6.2 编写 Fabric 脚本(生产级)

控制机创建 /root/fabfile.py,支持并发、错误重试、日志:

from fabric import Connection
from fabric.exceptions import NetworkError, CommandTimeout
from invoke import task
import os
import logging
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor, as_completed

# ===================== 全局配置区(按需修改)=====================
CONFIG = {
    "user": "root",
    "hosts": ["10.0.0.14", "10.0.0.16"],
    "local_script": "/root/test_script.sh",
    "remote_script": "/tmp/test_script.sh",
    "ssh_key": "/root/.ssh/id_rsa",
    "timeout": 15,
    "max_workers": 2,  # 并发数
    "log_file": "/root/fabric_deploy.log"
}

# ===================== 日志初始化 =====================
logging.basicConfig(
    filename=CONFIG["log_file"],
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    encoding="utf-8"
)
logger = logging.getLogger(__name__)

# ===================== 工具函数 =====================
def check_local_script():
    """检查本地脚本是否存在且有执行权限"""
    script_path = CONFIG["local_script"]
    if not os.path.exists(script_path):
        err_msg = f"本地脚本 {script_path} 不存在!"
        print(f"❌ {err_msg}")
        logger.error(err_msg)
        return False
    if not os.access(script_path, os.X_OK):
        warn_msg = f"本地脚本 {script_path} 无执行权限,自动添加..."
        print(f"⚠️ {warn_msg}")
        logger.warning(warn_msg)
        os.chmod(script_path, 0o755)
    print(f"✅ 本地脚本 {script_path} 检查通过")
    logger.info("本地脚本检查通过")
    return True

def handle_host(host):
    """处理单台主机:拷贝+执行脚本"""
    print(f"\n===== 开始处理主机 {host} [{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] =====")
    logger.info(f"开始处理主机 {host}")
    try:
        # 建立SSH连接
        conn = Connection(
            host=host,
            user=CONFIG["user"],
            connect_kwargs={
                "key_filename": CONFIG["ssh_key"],
                "timeout": CONFIG["timeout"],
                "look_for_keys": True,
                "allow_agent": False
            }
        )

        # 1. 拷贝脚本
        print(f"📤 上传脚本到 {host}:{CONFIG['remote_script']}")
        conn.put(
            CONFIG["local_script"],
            CONFIG["remote_script"],
            preserve_mode=True  # 保留文件权限
        )
        logger.info(f"{host}:脚本上传成功")

        # 2. 执行脚本
        print(f"▶️  执行脚本 {CONFIG['remote_script']}")
        result = conn.run(
            f"chmod +x {CONFIG['remote_script']} && {CONFIG['remote_script']}",
            hide=False,  # 显示执行输出
            timeout=CONFIG["timeout"]
        )

        # 3. 结果判断
        if result.ok:
            success_msg = f"{host} 脚本执行成功"
            print(f"✅ {success_msg}")
            logger.info(success_msg)
        else:
            fail_msg = f"{host} 脚本执行返回非0码"
            print(f"⚠️ {fail_msg}")
            logger.warning(fail_msg)

        conn.close()
        return {"host": host, "status": "success"}

    except NetworkError as e:
        err_msg = f"{host} 网络错误:{str(e)}"
        print(f"❌ {err_msg}")
        logger.error(err_msg)
        return {"host": host, "status": "failed", "error": "network_error"}
    except CommandTimeout as e:
        err_msg = f"{host} 执行超时:{str(e)}"
        print(f"❌ {err_msg}")
        logger.error(err_msg)
        return {"host": host, "status": "failed", "error": "timeout"}
    except Exception as e:
        err_msg = f"{host} 未知错误:{str(e)}"
        print(f"❌ {err_msg}")
        logger.error(err_msg)
        return {"host": host, "status": "failed", "error": "unknown"}

# ===================== 核心任务 =====================
@task
def deploy(c):
    """批量部署脚本(入口函数)"""
    print("===== Fabric 批量脚本部署工具 =====")
    # 前置检查
    if not check_local_script():
        return

    # 并发处理主机
    results = []
    with ThreadPoolExecutor(max_workers=CONFIG["max_workers"]) as executor:
        # 提交任务
        future_to_host = {executor.submit(handle_host, host): host for host in CONFIG["hosts"]}
        # 获取结果
        for future in as_completed(future_to_host):
            results.append(future.result())

    # 输出汇总
    print("\n===== 执行结果汇总 =====")
    success_hosts = [r["host"] for r in results if r["status"] == "success"]
    fail_hosts = [r["host"] for r in results if r["status"] == "failed"]
    print(f"✅ 成功主机:{', '.join(success_hosts) if success_hosts else '无'}")
    print(f"❌ 失败主机:{', '.join(fail_hosts) if fail_hosts else '无'}")
    print(f"\n📊 详细日志:{CONFIG['log_file']}")
    logger.info(f"执行完成 - 成功:{len(success_hosts)} 台,失败:{len(fail_hosts)} 台")

6.3 执行与验证

# 激活虚拟环境(每次执行前需激活)
source /root/fabric-venv/bin/activate

# 执行批量部署任务
fab deploy

# 验证结果
ssh root@10.0.0.14 "cat /tmp/script_executed_$(date +%Y%m%d).log"

七、方案4:SaltStack 实现(C/S 架构,Ubuntu 24.04 适配)

7.1 离线安装(解决网络访问问题)

(1)控制机(Master)安装
# 1. 下载离线包(可在联网机器下载后传输至控制机/root目录)
# 适配 Ubuntu 24.04 的 SaltStack 离线包(版本:3006.6)
wget https://repo.saltproject.io/py3/ubuntu/24.04/amd64/salt-3006.6.tar.gz -O /root/salt-3006.6.tar.gz

# 2. 解压并安装
tar -zxvf /root/salt-3006.6.tar.gz -C /root
cd /root/salt-3006.6
pip3 install -r requirements.txt --break-system-packages
python3 setup.py install --break-system-packages

# 3. 配置 Master
mkdir -p /etc/salt/master.d
cat > /etc/salt/master << EOF
interface: 0.0.0.0
publish_port: 4505
ret_port: 4506
auto_accept: True  # 自动接受Minion密钥(生产环境慎用)
EOF

# 4. 启动 Master
salt-master -d  # 后台运行
(2)目标机(Minion)安装
# 1. 拷贝离线包到目标机
scp /root/salt-3006.6.tar.gz root@10.0.0.14:/root
scp /root/salt-3006.6.tar.gz root@10.0.0.16:/root

# 2. 目标机执行安装(以10.0.0.14为例)
ssh root@10.0.0.14 "
    tar -zxvf /root/salt-3006.6.tar.gz -C /root &&
    cd /root/salt-3006.6 &&
    pip3 install -r requirements.txt --break-system-packages &&
    python3 setup.py install --break-system-packages &&
    mkdir -p /etc/salt/minion.d &&
    echo 'master: 10.0.0.13' > /etc/salt/minion &&
    salt-minion -d
"

7.2 编写 SLS 状态文件

控制机创建 /srv/salt/script_deploy.sls

# SaltStack 状态文件:分发并执行脚本(幂等性)
test_script_file:
  file.managed:
    - name: /tmp/test_script.sh
    - source: salt://test_script.sh
    - mode: 0755
    - user: root
    - group: root

test_script_exec:
  cmd.run:
    - name: /tmp/test_script.sh
    - require:
      - file: test_script_file
    - creates: /tmp/script_executed_{{ grains['date'] }}.log  # 幂等性:仅当日志不存在时执行

7.3 执行状态

# 1. 拷贝测试脚本到 SaltStack 文件根目录
cp /root/test_script.sh /srv/salt/

# 2. 批量执行状态
salt '*' state.apply script_deploy

# 3. 验证结果
salt '*' cmd.run 'cat /tmp/script_executed_$(date +%Y%m%d).log'

八、工具选型建议与生产环境落地

8.1 选型决策树

  1. ≤5台主机 + 零基础运维 → Shell 脚本;
  2. 5-50台主机 + 配置管理需求 → Ansible;
  3. 5-50台主机 + 定制化逻辑 → Fabric;
  4. ≥50台主机 + 高并发/实时性 → SaltStack。

8.2 生产环境优化建议

  1. 安全性
    • SSH 免密登录限制 IP(修改 /root/.ssh/authorized_keys 添加 from="10.0.0.13");
    • Ansible/SaltStack 禁用密码登录,仅用密钥认证;
  2. 可维护性
    • 所有配置文件集中管理(如 /etc/ansible//srv/salt 纳入版本控制);
    • 脚本添加注释、配置区与逻辑区分离;
  3. 监控告警
    • 批量执行脚本添加邮件/钉钉告警(失败时触发);
    • 对 SaltStack/Ansible 执行结果做日志监控。

九、常见问题排查

9.1 SSH 免密登录失败

  • 检查目标机 /etc/ssh/sshd_config:确保 PubkeyAuthentication yes
  • 检查权限:~/.ssh 权限为 700,~/.ssh/authorized_keys 权限为 600;
  • 重启 SSH 服务:systemctl restart sshd

9.2 Ansible 执行超时

  • 修改 ansible.cfg:添加 timeout = 10
  • 检查目标机防火墙:放行 SSH 端口(22)。

9.3 Fabric 并发报错

  • 降低 max_workers 数值(避免目标机 SSH 连接数限制);
  • 检查目标机 sshd_configMaxSessions 调大(如 10)。

9.4 SaltStack Minion 无法连接 Master

  • 检查 Master 防火墙:放行 4505/4506 端口;
  • 检查 Minion 配置:master 字段正确指向控制机 IP;
  • 重启 Minion:salt-minion restart

总结

  1. 技术原理:Shell 脚本是基础,Ansible/Fabric 是无代理架构的进阶,SaltStack 是有代理架构的企业级方案,核心均基于 SSH/跨主机通信;
  2. 落地优先级:Ubuntu 24.04 环境下,优先选择 Shell/Ansible/Fabric(无网络依赖、易落地),大规模集群再考虑 SaltStack 离线安装;
  3. 核心能力:四款工具均可实现「批量拷贝+执行脚本」,差异在于架构、并发、学习成本,需根据集群规模和运维团队技术栈选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Evan芙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值