SSH 配置实战:让终端和脚本共用同一个服务器名称
同一个服务器快捷命令,在终端里能用,放进脚本却提示 Could not resolve hostname。遇到这种情况,先看快捷命令是怎么定义的,再决定是否需要检查 DNS。
本文适合已经能通过地址、用户名和端口连接 Linux 服务器的读者。下面把一条可用命令整理成可复用的 SSH 配置,先在本地验证,再用它下载远程文件。
方法 1:确认快捷命令实际执行了什么
假设 .zshrc 里有下面这条示例配置:
alias blogbox='ssh -p 22222 deploy@192.0.2.10'
在快捷命令可用的终端里执行:
type blogbox
alias blogbox
再比较下面两条命令:
blogbox
ssh blogbox
对于上面这种普通 alias,第一条会展开为保存的 SSH 命令。第二条里的 blogbox 是传给 SSH 的参数。单独定义一个 shell alias,并不会创建 SSH 主机配置或 DNS 记录。
还要注意启动文件的差异:zsh 会在交互式 shell 中读取 .zshrc,不能指望非交互执行时也加载其中的别名。具体规则见 zsh 启动文件文档。
可以直接检查定义,不必加载整个文件:
grep -n 'blogbox' ~/.zshrc
部署脚本不应依赖加载交互式 shell 的全部设置。把连接信息放进 SSH 客户端配置,后续调用会更直接。
准备工作:检查客户端
在本地电脑执行:
ssh -V
man ssh
man ssh_config
Debian 或 Ubuntu 如果没有客户端,可以安装:
sudo apt update
sudo apt install openssh-client
下文用 192.0.2.10、deploy 和端口 22222 演示。请根据你已经能连接成功的命令,替换为实际地址、远程账户和 SSH 端口。示例 IP 不是可供登录的演示服务器。
方法 2:创建可复用的主机配置
先准备本地配置文件,下面的命令不会清空已有内容:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/config
chmod 600 ~/.ssh/config
cp -p ~/.ssh/config ~/.ssh/config.backup.$(date +%Y%m%d%H%M%S)
用编辑器打开 ~/.ssh/config,把下面这段放在文件靠前的位置,排在 Host * 这类宽泛配置之前。如果已经有 Host blogbox,直接修改原来的块,不要重复添加。
Host blogbox
HostName 192.0.2.10
User deploy
Port 22222
Host 是命令里使用的名称,另外三项分别指定目标地址、账户和端口。SSH 的大多数配置项采用首先获得的值,因此具体主机配置应该放在通用默认值之前。详见 OpenSSH 配置手册。
如果原来的可用命令指定了私钥,可以在同一个块中增加实际的本地私钥路径:
IdentityFile ~/.ssh/id_ed25519_blog
IdentitiesOnly yes
这两行是可选的。只有该私钥存在,而且对应公钥已获远程账户授权时,才添加它们。IdentitiesOnly 用来限制认证时提供的身份,不会替你把公钥安装到服务器。详见 IdentityFile 和 IdentitiesOnly。
验证:先检查配置,再连接服务器
打印 SSH 解析后的配置:
ssh -G blogbox | awk '$1 ~ /^(hostname|user|port)$/ { print }'
使用上面的示例配置,应该看到以下值,顺序可能不同:
user deploy
hostname 192.0.2.10
port 22222
ssh -G 会计算配置并退出,不会建立 SSH 会话。它能帮助检查参数,但不能证明目标可达或认证一定成功。详见 SSH 命令手册。
替换为实际连接信息后,再测试远程执行:
ssh blogbox 'hostname; whoami; pwd'
输出应包含服务器名称、远程账户和初始工作目录。首次连接时,先通过服务器提供商或其他可信渠道核对主机指纹,再接受提示。
然后从非交互式 shell 调用:
sh -c 'ssh blogbox "hostname"'
此时已经不需要 blogbox 这个 shell alias。但执行命令的本地用户,仍然必须能够读取 SSH 配置,并拥有所需的认证材料。
让文件传输和脚本共用同一个名称
假设 Hugo 项目位于 /home/wwwroot/example.com,可以先执行只读检查:
ssh blogbox 'cd /home/wwwroot/example.com && pwd && ls content'
请把项目路径改成服务器上的实际目录。下面把配置文件下载到新建的临时目录:
download_dir=$(mktemp -d)
scp blogbox:/home/wwwroot/example.com/hugo.toml "$download_dir/hugo.toml"
ls -l "$download_dir/hugo.toml"
SCP 也会使用 SSH 主机配置。不使用主机配置时,对应的传输命令需要用大写 -P 指定端口:
scp -P 22222 deploy@192.0.2.10:/home/wwwroot/example.com/hugo.toml "$download_dir/hugo.toml"
不要改成小写 -p:SCP 用它保留文件时间和权限模式。详见 SCP 手册。
如果要执行无人值守的只读检查,先确认交互登录成功,再准备公钥认证;私钥需要 agent 解锁时,也应提前准备好。然后执行:
ssh -o BatchMode=yes -o ConnectTimeout=10 blogbox \
'cd /home/wwwroot/example.com && test -r hugo.toml && printf "project readable\n"'
BatchMode 会禁用认证交互,缺少凭据时直接失败,而不是等待输入密码。ConnectTimeout 限制连接建立阶段的等待时间,不是远程命令的执行时限。详见 OpenSSH 参数说明。
常见问题
1. 仍然提示 Could not resolve hostname
重新运行 ssh -G 检查。如果输出还是 hostname blogbox,检查 Host 名称拼写,以及实际执行 SSH 的本地账户。也可以显式指定配置文件:
ssh -F ~/.ssh/config -G blogbox
CI runner 或另一个操作系统用户有自己的主目录和配置,需要在对应环境里准备主机配置和凭据。
2. 使用了意料之外的账户或端口
带行号查看配置:
nl -ba ~/.ssh/config
检查是否有重复的 Host blogbox,或前面已经匹配的默认设置,也要留意被 Include 引入的文件。把具体主机配置移到冲突的默认值之前,再运行 ssh -G blogbox。同时检查调用命令是否自行指定了用户名或端口。
3. 提示 Permission denied (publickey)
观察一次实际连接的调试输出:
ssh -v blogbox 'true'
重点看选择的用户名和提供的公钥。如果配置了前面的可选私钥,检查文件及权限:
ls -l ~/.ssh/id_ed25519_blog
chmod 600 ~/.ssh/id_ed25519_blog
私钥存在但仍被拒绝时,确认对应公钥已获服务器上该账户的授权。主机配置正确,并不等于自动获得登录权限。
4. 连接被拒绝或超时
如果解析后的地址和端口正确,再检查服务器 SSH 监听、防火墙和网络路径。可以带调试信息重试:
ssh -v -o ConnectTimeout=10 blogbox 'true'
服务在指定地址和端口不可达时,修改 shell alias 无法解决问题。
总结
从一条已经可用的 SSH 命令开始,把连接参数整理到一个 Host 配置块,再通过 ssh -G 核对结果。之后登录、SCP 和脚本都可以复用这个名称;无人值守执行前,仍要单独验证认证是否就绪。
如果还想整理连接服务器后运行的项目命令,可以继续阅读 just 项目命令管理教程。
- 原文作者:春江暮客
- 原文链接:https://www.bobobk.com/ssh-config-alias-workflow.html
- 版权声明:本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。