本文目录导读:

在脚本中通过SSH远程执行命令,主要有以下几种方式,它们的核心区别在于是否需要交互、是否占用终端以及如何传递密码。
核心方式对比
| 方式 | 核心命令 / 工具 | 是否需要交互 | 密码处理 | 典型场景 |
|---|---|---|---|---|
| 直接命令模式 | ssh user@host command |
否 | 需密钥或expect | 执行单条或简单命令 |
| 本地脚本管道 | cat script.sh \| ssh user@host |
否 | 需密钥或expect | 执行较复杂的脚本逻辑 |
| 远程执行文件 | scp + ssh 组合 |
否 | 需密钥或expect | 依赖本地文件或需要持久化脚本 |
| 交互式自动化 | expect / sshpass |
是 | 明文或自动输入 | 环境不支持密钥,必须密码登录 |
| 高级工具封装 | Ansible, Fabric, Paramiko | 否 | 多种方式 | 大批量、复杂编排、需要幂等性 |
直接命令模式(最常用)
直接在 ssh 命令后面加上要执行的命令,SSH 会执行完毕后自动退出。
# 基础语法 ssh user@host "command1; command2; command3" # 示例:查看远程磁盘空间 ssh root@192.168.1.100 "df -h" # 示例:在远程执行带变量的命令(需注意引号转义) ssh user@host 'echo "Hostname: $(hostname); Date: $(date)"' # 示例:在远程执行需要 sudo 权限的命令 ssh -t user@host "sudo systemctl restart nginx" # -t 参数强制分配伪终端,解决 sudo 可能提示 "no tty present" 的问题
优缺点:
- ✅ 简单直接,无需额外脚本。
- ❌ 复杂逻辑(if/for 循环)写起来繁琐,转义复杂。
本地脚本管道模式(推荐较复杂逻辑)
将本地脚本文件的内容通过管道发送到远程主机的 shell 中执行。
# 本地脚本 local_script.sh
#!/bin/bash
echo "=== System Info ==="
uname -a
echo "=== Disk Usage ==="
df -h
# 通过管道远程执行
cat local_script.sh | ssh user@host bash
# 也可以直接使用 heredoc(无需单独脚本文件)
ssh user@host bash << 'EOF'
for i in {1..5}; do
echo "Iteration $i"
uptime
done
EOF
# 注意:EOF 用单引号括起来表示禁止本地shell解析变量,否则会先被本地替换
优缺点:
- ✅ 适合执行多步、含循环/判断的复杂逻辑。
- ❌ 脚本标准错误和标准输出混合,调试稍微困难(可通过重定向解决)。
远程执行文件模式(依赖本地文件)
先将本地脚本或文件上传到远程主机,再通过 SSH 执行该文件。
# 1. 上传脚本 scp /path/to/script.sh user@host:/tmp/script.sh # 2. 远程执行 ssh user@host "bash /tmp/script.sh" # 3. 清理远程文件(可选) ssh user@host "rm /tmp/script.sh" # 或者合并为一行 scp script.sh user@host:/tmp/script.sh && ssh user@host "bash /tmp/script.sh && rm /tmp/script.sh"
优缺点:
- ✅ 脚本可以依赖本地附件,执行结果可控,适合批量分发。
- ❌ 多了一步上传操作,稍微慢一点。
交互式自动化模式(处理密码登录)
当无法配置 SSH 密钥时,需要自动输入密码。
方式 A:使用 sshpass(最简单)
# 安装:apt install sshpass / yum install sshpass sshpass -p 'your_password' ssh user@host "command" # 注意:密码明文,安全性较低,不推荐生产环境 # 可通过环境变量稍微提高安全性(但仍不完美) export SSHPASS='your_password' sshpass -e ssh user@host "command"
方式 B:使用 expect(最灵活)
#!/usr/bin/expect set timeout 10 spawn ssh user@host expect "password:" send "your_password\r" expect "$ " send "ls -la\r" expect "$ " send "exit\r" expect eof
优缺点:
- ✅ 能解决一切交互式登录问题,特别适合跳板机、二次认证等场景。
- ❌
sshpass密码明文,expect脚本维护成本较高。
高级工具封装模式(批量与编排)
Ansible(无需 agent,SSH 底层)
- name: 远程执行命令
hosts: webservers
tasks:
- name: Check disk usage
shell: df -h
register: result
- debug: var=result.stdout_lines
ansible webservers -m shell -a "df -h"
Fabric(Python 库)
from fabric import Connection
with Connection("user@host") as c:
result = c.run("uname -a", hide=True)
print(result.stdout)
Paramiko(纯 Python SSH 库)
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("host", username="user", password="pass")
stdin, stdout, stderr = client.exec_command("df -h")
print(stdout.read().decode())
client.close()
核心注意事项
- 优先使用 SSH 密钥登录,避免密码明文出现在脚本或日志中。
- 环境变量差异:通过
ssh执行命令时,不会加载.bashrc或.profile,需手动指定或使用source ~/.bashrc。ssh user@host "source ~/.bashrc && command"
- 引号转义:复杂命令建议用单引号包裹整个远程命令,防止本地 shell 先解析。
- 本地变量:
ssh user@host "echo $HOME"(输出本地 HOME) - 远程变量:
ssh user@host 'echo $HOME'(输出远程 HOME)
- 本地变量:
- 标准输入重定向:如果脚本需要通过 STDIN 接收输入,需注意管道和 SSH 的 STDIN 冲突。
- 错误处理:默认 SSH 远程命令返回码仅代表远程命令的退出码,建议在脚本中加上
set -e或检查 。 - 多命令执行顺序:使用 、
&&、 控制逻辑,用 或 分组。
选择建议
| 场景 | 推荐方式 |
|---|---|
| 简单单条命令 | 方式1:直接 ssh user@host "command" |
| 复杂循环/条件逻辑 | 方式2:本地脚本管道 cat script \| ssh ... |
| 需要上传文件后执行 | 方式3:scp + ssh 组合 |
| 无法使用密钥,必须密码 | 方式4:sshpass(低安全)或 expect(高控制) |
| 批量管理大量服务器 | 方式5:Ansible |
| 需要集成到 Python 应用 | 方式5:Paramiko / Fabric |
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播