春江暮客

春江暮客的个人学习分享网站

SSH 配置实战:让终端和脚本共用同一个服务器名称

2026-09-17 技术
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.10deploy 和端口 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 项目命令管理教程

友情链接

其它