脚本如何远程执行命令

wen 实用脚本 32

脚本如何安全高效地操控服务器

目录导读

  1. 远程执行命令的核心原理
  2. 主流实现方案深度对比(SSH/Ansible/PowerShell)
  3. 实战案例:用Python脚本一键部署10台服务器
  4. 安全加固的5个致命细节
  5. 常见问题QA(你可能会犯的3个错误)

远程执行命令的本质是什么?

核心疑问:当你敲下命令,代码如何跨越网络触达另一台机器?答案隐藏在网络协议与认证机制的协同中,远程命令执行本质是客户端通过加密通道向服务端发送标准输入/输出流,服务端解释执行后返回结果。

脚本如何远程执行命令

底层技术支撑

  • SSH协议(端口22):最通用的加密通道,支持密钥认证
  • WinRM协议:Windows原生的远程管理方案
  • 反弹Shell:黑客常用的后门技术(不推荐用于正常运维)

关键认知:无论使用HTTP API还是SSH,远程执行都绕不开三个要素——认证、权限隔离、输出捕获。


四大主流方案横向测评

方案1:SSH + 原生脚本(万能钥匙)

适用场景:临时性单机操作
命令示例

ssh user@192.168.1.100 "sudo apt update && sudo apt upgrade -y"

优势:零依赖,Linux/Unix天生支持
坑点:交互式密码输入需用sshpass或密钥对

方案2:Ansible(自动化神器)

无代理架构:依赖SSH + Python3
Playbook示例

- hosts: webservers
  tasks:
    - name: 重启Nginx
      command: systemctl restart nginx

优势:幂等性设计,10台机器一键执行
注意:管控节点需安装Ansible,被控节点只需Python

方案3:SaltStack(事件驱动型)

独特价值:支持实时指令下达(类似人机交互)
适用场景:大规模集群的即时维护
示例

salt '*' cmd.run 'df -h'

方案4:PowerShell Remoting(Windows专属)

核心命令Invoke-Command
示例

$cred = Get-Credential
Invoke-Command -ComputerName WinServer -ScriptBlock { Get-Service } -Credential $cred

注意:需启用WinRM并配置HTTPS


实战:用Python实现跨平台远程执行

需求:监控100台Linux服务器的磁盘使用率,超过80%自动报警

核心代码片段

import paramiko
def remote_exec(host, cmd):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(hostname=host, username='admin', key_filename='~/.ssh/id_rsa')
    stdin, stdout, stderr = client.exec_command(cmd)
    return stdout.read().decode()
# 批量执行
hosts = ['192.168.1.10', '192.168.1.20']
for h in hosts:
    output = remote_exec(h, 'df -h | grep /dev/sda1')
    # 解析output做报警逻辑

关键改进点

  1. 使用paramiko的自动策略避免手动确认主机密钥
  2. 通过get_pty=True解决需要tty的命令(如sudo)
  3. 捕获stderr并设置超时防止僵尸进程

安全加固的五重防线(血泪教训)

问题1:密钥泄露怎么办?

方案:使用SSH证书认证(CA签名),密钥到期自动失效

问题2:如何防命令注入?

错误示范

os.system("ping " + user_input)  # 用户输入; rm -rf /

正确做法:用shlex.quote()转义参数,或用子进程参数列表

问题3:日志审计怎么搞?

方案:在远程脚本中强制写入操作日志echo "$(date) $USER : $CMD" >> /var/log/remote_audit.log

问题4:网络抖动导致重复执行?

方案:在目标机器创建锁文件/tmp/script.lock,执行前检查

问题5:如何限制命令范围?

方案:用sudoers配置白名单,只允许特定命令

user ALL=(root) /usr/bin/apt, /usr/bin/systemctl

高频问题QA(你可能会踩的坑)

Q1 :被控机器没有公网IP怎么办?
A:建立反向隧道:ssh -R 2222:localhost:22 jump-server,然后通过跳板机连接内网机器。

Q2:脚本执行到一半断了,如何恢复?
A:使用screentmux创建后台会话,再用Attach恢复,Python中可以用nohup + 重定向输出

Q3:不同操作系统路径不一致怎么处理?
A:在脚本中先检测系统类型(uname -a),再进行条件分支,推荐用Ansible的ansible_os_family变量。

Q4:企业防火墙阻止SSH端口怎么办?
A:改用HTTPS协议 + WebSocket隧道,或用Cloudflare Tunnel等CDN方案。


总结与行动清单

远程命令执行看似简单,实则涉及网络、安全、系统三大领域的深度耦合。你的最佳路径

  1. 小规模场景:优先用SSH + 密钥对
  2. 中等规模:学习Ansible的Playbook语法
  3. 混合环境:用SaltStack或自研Python框架
  4. 永远别忘:开启审计日志 + 白名单机制

立即行动:在测试环境创建一台虚拟机,尝试用ssh user@test-vm "uptime" 体验远程控制的美妙!(注意:生产环境请先测试脚本兼容性)

抱歉,评论功能暂时关闭!