SSH 命令怎么用:格式、端口、密钥、跳板机与常用参数
SSH 命令的基本格式是 ssh 用户名@主机,例如 ssh [email protected];端口不是 22 时加 -p 端口,指定私钥加 -i 私钥文件,经跳板机加 -J 跳板机,其他配置项用 -o 名称=值 临时设置。经常连的服务器写进 ~/.ssh/config,之后一条 ssh 别名就能连上。
SSH 命令用来从命令行登录远程服务器、在上面执行命令,格式是 ssh [选项] [用户名@]主机 [远程命令]。最常见的写法是 ssh [email protected];服务器的 SSH 端口不是 22 时加 -p,如 ssh -p 22022 [email protected];用指定的私钥登录加 -i ~/.ssh/私钥文件;服务器在内网、要先经过跳板机,用 -J 跳板机;其他任何客户端配置项都能用 -o 名称=值 临时设置。Linux、macOS 和 Windows 10/11 自带的都是 OpenSSH 客户端,本文的命令在三个系统上通用。
ssh 命令格式:用户名、主机和远程命令怎么写
ssh [email protected] # 用户名@主机,最常用
ssh -l root 10.30.5.21 # 用 -l 指定用户名,效果相同
ssh 10.30.5.21 # 不写用户名,默认使用本机当前的登录名
ssh ssh://[email protected]:22022 # URI 写法,端口可以直接写在里面
ssh root@2001:db8::21 # IPv6 地址直接写,不需要方括号
ssh [email protected] 'df -h /' # 主机后面的内容作为远程命令执行,执行完即断开
写法上的几条规则:
- 主机可以是 IP、域名,或 ~/.ssh/config 里定义的别名。 别名的写法见后文的实例。
- 选项写在主机前面。 OpenSSH 也接受紧跟在主机后面的选项,但从主机之后第一个不以
-开头的词起,剩下的内容全部算作远程命令,例如ssh [email protected] uptime -p里的-p是交给 uptime 的参数,不是端口。把选项全部写在主机前面,不容易出错。 - 用户名省略时取本机登录名。 在 Windows 上,你的登录名可能是 Administrator 或一个中文名,服务器上没有这个用户,表现为密码怎么输都不对,所以用户名最好每次都写明。
- 不带远程命令就是交互式登录。 登录后提示符变成服务器的主机名,输入
exit或按Ctrl+D退出。
ssh 命令怎么指定端口
服务器把 SSH 端口从 22 改成别的端口后,连接时必须告诉客户端,三种写法任选:
ssh -p 22022 [email protected] # 最常用
ssh ssh://[email protected]:22022 # URI 写法
ssh -o Port=22022 [email protected] # 用 -o 设置 Port 选项
常见的写错方式和对应的现象:
| 错误写法 | 现象 | 正确写法 |
|---|---|---|
ssh [email protected]:22022 |
Could not resolve hostname 10.30.5.21:22022,冒号和端口被当成了主机名的一部分 |
ssh -p 22022 [email protected] |
ssh -P 22022 [email protected] |
大写 -P 不是端口参数:老版本直接报错并打印用法;新版本把它当作配置标签(Tag),照样去连 22 端口 |
ssh 用小写 -p;scp、sftp 才用大写 -P |
端口写对了但一直等待,最后 Connection timed out |
防火墙或安全组没有放行新端口 | 在本机执行 nc -zv 10.30.5.21 22022 测试端口是否可达,Windows 上用 PowerShell 执行 Test-NetConnection 10.30.5.21 -Port 22022 |
端口写对了但立即 Connection refused |
服务器在,但这个端口上没有 sshd 监听 | 从控制台登录,执行 ss -tlnp,在输出里找 sshd 那一行,看它实际监听的端口 |
端口的取值顺序是:命令行参数优先,其次是 ~/.ssh/config,最后是系统级的 /etc/ssh/ssh_config。命令行里写了 -p,配置文件里同一主机的 Port 就不起作用。rsync 经 SSH 连非标准端口时写成 rsync -e 'ssh -p 22022'。
常用参数与 -o 选项速查
命令行参数
| 参数 | 作用 | 什么时候用 |
|---|---|---|
-p 端口 |
指定服务器的 SSH 端口 | 端口不是 22 |
-l 用户名 |
指定登录用户 | 与 用户名@ 二选一 |
-i 私钥文件 |
用指定的私钥认证 | 私钥不是默认文件名(不加 -i 时 ssh 只自动尝试 ~/.ssh/id_ed25519、id_rsa 等默认名称和 ssh-agent 里的密钥),或用云厂商下发的 .pem 文件;私钥权限要设为 600 |
-J 跳板机 |
先连跳板机,再从它转到目标,多个跳板用逗号分隔 | 目标在内网,只能经跳板机访问 |
-o 名称=值 |
临时设置任意配置项 | 见下一张表 |
-v、-vv、-vvv |
输出调试信息,v 越多越详细 |
连不上、认证失败时排查 |
-t |
强制分配终端 | 远程命令需要交互,如 sudo 要输密码、运行 top |
-n |
不读取本机的标准输入 | 在 while read 循环里批量执行 |
-N |
只建立连接,不执行远程命令 | 单纯做端口转发 |
-f |
认证完成后转到后台 | 与 -N 搭配,让隧道在后台运行 |
-L 本地端口:目标:目标端口 |
本地端口转发 | 经跳板机访问内网的网页、数据库 |
-D 本地端口 |
动态转发,本机变成一个 SOCKS5 代理 | 经跳板机访问整个内网网段 |
-R 远端端口:目标:目标端口 |
远程端口转发 | 让远端能访问到本机这一侧的服务 |
-C |
压缩传输 | 低速链路上传输大量文本输出 |
-4、-6 |
只用 IPv4 或 IPv6 | 域名同时有 A 和 AAAA 记录,想固定走其中一种 |
-F 配置文件 |
使用指定的配置文件 | 测试新配置,或不同项目用不同的配置 |
-G |
不连接,只打印对这个主机最终生效的配置 | 检查配置文件写得对不对 |
-o 常用选项
| 选项 | 作用 | 使用场景 |
|---|---|---|
ConnectTimeout=5 |
建立连接最多等 5 秒 | 批量脚本里跳过不通的机器,不必每台卡很久 |
ServerAliveInterval=30 |
每 30 秒向服务器发一次保活消息 | 经过 NAT 或防火墙时,长时间不操作会被断开 |
ServerAliveCountMax=3 |
连续 3 次没有回应就断开 | 与上一项配合,及时发现连接已经断了 |
StrictHostKeyChecking=accept-new |
首次连接的主机自动接受,已记录的主机密钥变了仍然拒绝 | 批量连新装的机器 |
UserKnownHostsFile=/dev/null |
不读也不写 known_hosts | 救援系统、PXE 装机环境每次启动主机密钥都不同;只在可信的内网里与 StrictHostKeyChecking=no 搭配使用 |
BatchMode=yes |
不弹出任何密码或确认提示,需要输入时直接失败 | 定时任务、脚本 |
PubkeyAuthentication=no |
不尝试密钥,直接走密码认证 | 测试密码登录是否可用 |
IdentitiesOnly=yes |
只提交 -i 或配置里指定的私钥 |
本机密钥太多,报 Too many authentication failures |
HostKeyAlgorithms=+ssh-rsa |
额外允许旧的主机密钥算法 | 连固件较老的交换机、BMC,报 no matching host key type |
LogLevel=ERROR |
不显示警告信息 | 脚本输出里不想出现 Warning 行 |
实例:连接机房里改过端口、只能经跳板机访问的服务器
假设这样一个环境:运维人员只能从公网访问跳板机 jump.example.com,它的 SSH 端口是 2222,登录用户 ops;目标服务器 10.30.5.21 在机房内网,sshd 改到了 22022 端口,用 root 和私钥 ~/.ssh/idc_ed25519 登录。
一条命令连接:
ssh -i ~/.ssh/idc_ed25519 -J [email protected]:2222 -p 22022 [email protected]
这里有两个端口,别写混:跳板机的端口写在 -J 的地址后面(主机:端口),-p 只作用于最后的目标服务器。-J 的原理是先登录跳板机,让它把一条 TCP 连接转到 10.30.5.21:22022,本机再通过这条连接直接与目标服务器完成认证,私钥始终留在本机。注意 -i 和 -p 一样只作用于目标服务器:连跳板机的那一段不会带上 -i,用的是默认文件名的私钥、ssh-agent 里的密钥,或 ~/.ssh/config 里给跳板机写的 IdentityFile。跳板机也只认这把专用私钥时,这条命令会在跳板机一步就认证失败,改用下面的配置文件写法即可。所以本机要能同时通过跳板机和目标服务器的认证,跳板机上也要允许 TCP 转发(sshd 的 AllowTcpForwarding,默认开启);部分商业堡垒机为了审计会关闭转发,这时 -J 不能用。OpenSSH 7.3 之前的老客户端没有 -J,改写成:
ssh -o ProxyCommand="ssh -W %h:%p -p 2222 [email protected]" -p 22022 [email protected]
写进 ~/.ssh/config,以后只敲别名:
Host idc-jump
HostName jump.example.com
Port 2222
User ops
IdentityFile ~/.ssh/idc_ed25519
Host idc-web01
HostName 10.30.5.21
Host idc-* !idc-jump
Port 22022
User root
IdentityFile ~/.ssh/idc_ed25519
ProxyJump idc-jump
之后 ssh idc-web01 就完成了上面那条长命令的全部工作;scp、sftp、rsync 使用这个别名时,也会自动带上端口、用户和跳板设置。再加一台内网服务器,只需要补一个两行的段落,例如 Host idc-web02 加上它的 HostName。
Host idc-* !idc-jump 里的 !idc-jump 不能省:通配的 idc-* 也会匹配到跳板机自己,ProxyJump 就会让跳板机去经过自己连接,形成循环。配置写完,用 -G 检查最终生效的值,不用真的连接:
ssh -G idc-web01 | grep -E '^(hostname|port|user|proxyjump) '
输出应当是 hostname 10.30.5.21、port 22022、user root、proxyjump idc-jump。哪一项不对,就回去看是不是被更靠前的 Host 段先设置了:同一个选项,ssh 只采用第一次匹配到的值。
远程执行命令、批量操作与端口转发
远程执行命令
ssh idc-web01 'uptime; df -h /' # 执行多条命令,用分号隔开
ssh -t idc-web01 'sudo systemctl restart nginx' # sudo 要输入密码,必须加 -t
ssh idc-web01 'bash -s' < check.sh # 把本机的脚本交给远端执行,脚本不用先上传
远程命令用单引号还是双引号,结果不一样:ssh idc-web01 "echo $HOSTNAME" 打印的是本机的主机名,因为双引号里的变量在本机就被展开了;写成单引号,变量才会到远端展开。不加 -t 执行需要输入密码的 sudo,会看到 sudo: a terminal is required to read the password 的报错。
批量操作多台服务器
while read -r h; do
printf '%s ' "$h"
ssh -n -o BatchMode=yes -o ConnectTimeout=5 "$h" 'uptime' || echo "连接失败"
done < hosts.txt
-n 必不可少:ssh 默认会读取标准输入,不加它,第一台机器就把 hosts.txt 剩下的内容全部读走,循环只执行一次。BatchMode=yes 让需要输入密码的机器直接报错跳过,不会卡在提示上,所以批量操作前要先配好密钥登录。
端口转发:不暴露 BMC,也能打开它的网页
服务器的 BMC 管理口通常在单独的管理网里,不对公网开放。需要临时打开某台 BMC 的网页时,经跳板机转发即可:
# 本机 8443 端口转发到 BMC 10.20.0.15 的 443 端口,然后浏览器打开 https://127.0.0.1:8443
ssh -N -L 8443:10.20.0.15:443 idc-jump
# 本机 1080 端口作为 SOCKS5 代理,浏览器设置代理后可以访问整个管理网
ssh -N -D 1080 idc-jump
-L 只转发一个端口,BMC 的网页能打开,但远程控制台、虚拟介质如果用的是其他端口,还要再加对应的 -L;-D 把本机变成代理,浏览器发出的所有连接都经跳板机转出,多个端口一次解决。转发期间终端窗口不要关,用完按 Ctrl+C 断开。
在管理系统里怎么落地
命令行的 ssh 适合运维人员自己用。给租用服务器的客户,或者一个需要多人协作的机房,问题会变成:客户不会配端口和密钥,运维每人一套跳板配置,事后说不清谁在哪台机器上执行过什么命令。在 Toplink DCIM 里,客户登录客户自助端就能管理名下服务器的 SSH 密钥,并在浏览器里直接打开 SSH、VNC 或 RDP 控制台,本机不用装客户端;运维人员通过 IPMI 远程管理发起的每一次远程会话都会自动录像,可以倍速回放、拖动进度,SSH 和 Telnet 会话另外保留命令级日志,事后能查到每条命令是谁执行的。
常见问题
-J 跳板和 -A 代理转发有什么区别?
-J 让跳板机只负责转发 TCP 连接,你的私钥和认证过程都留在本机,跳板机看不到也用不了。-A 把本机的 ssh-agent 转发到远端,远端上拥有 root 权限的人在你连接期间可以借用它登录其他服务器。只是为了穿过跳板机,用 -J 就够了,-A 只在确实需要从远端再发起认证、且信任这台机器时使用。
Windows 自带的 ssh 命令和 Linux 上的一样吗?
Windows 10、11 自带的是移植版 OpenSSH,-p、-i、-J、-L、-D、-o 等用法相同,配置文件在 C:\Users\用户名\.ssh\config。不同之处是不支持 ControlMaster 连接复用;个别版本里 ProxyJump 会报找不到程序,可以改用 ProxyCommand 并写出 ssh.exe 的完整路径。
ssh -v 的输出怎么看?
重点看三处:Connecting to 那一行确认连的地址和端口是否正确;Authentications that can continue 列出服务器允许的认证方式;Offering public key 之后如果没有出现 Server accepts key,说明提交的这把密钥不被接受。还不够清楚时用 -vvv 输出更多细节。