我运行这些两个命令一直连接到受防火墙保护的 AWS 上的 RDS 实例(因此我通过 EC2 实例建立隧道),如下所示:
命令1:打开隧道(在后台运行)
ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub &
命令2:通过隧道端口连接数据库:
PGPASSWORD=password psql dbname -U user -h ip_address -p port;
这很棒,但我想将这两个放在一个函数中。但我没用:
尝试 1:不使用后台运行:
function db()
{
ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub &
PGPASSWORD=password psql dbname -U user -h ip_address -p port;
}
简单地告诉我这一点:
$proddb
[1] 62924
psql: could not connect to server: Connection refused
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 6666?
尽管初始命令正在后台运行:
ps aux | grep host
(standard input):435:abdullah 62924 0.0 0.0 4315660 5828 s006 S 3:06PM 0:00.03 ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub
如果我立即运行接下来的命令,我就可以正常连接到数据库!
PGPASSWORD=password psql dbname -U user -h ip_address -p port;
user=>
我该如何让它工作?
答案1
运行第二个命令时,第一个命令没有时间建立隧道,因此出现“连接被拒绝”的情况。
不要使用,&
而是使用选项-f
:
-f
要求 ssh 在命令执行前转入后台。如果 ssh 要求输入密码或口令,但用户希望它在后台运行,则此功能很有用。这意味着 -n。在远程站点启动 X11 程序的推荐方法是使用类似 ssh -f host xterm 的命令。
如果 ExitOnForwardFailure 配置选项设置为“yes”,则使用 -f 启动的客户端将等待所有远程端口转发成功建立,然后再将其自身置于后台。
将所有这些放在一起,将函数中的 ssh 行替换为:
ssh -o ExitOnForwardFailure=yes -f -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub
这样,多次运行该函数,就不会留下(多个-1)无用的 ssh 运行。
也可以-N
用短远程睡眠命令来替换。这样,就不会出现需要搜索长时间空闲的 ssh 命令的情况,如果需要终止该命令,则无需搜索。Ssh 仍会等待隧道使用结束,因此短暂的延迟不是问题:
ssh -o ExitOnForwardFailure=yes -f -L port:host:5432 user@$ip -i ~/.ssh/key.pub sleep 15
答案2
@AB 提出的这个解决方案还可用于在 dmz(互联网或边缘端点)和 mz(后端)之间创建“跳转服务器”,并使用 ssh 端口转发隧道连接到后端主机,例如:
(必须使用防火墙命令打开所有相应的端口)
desthost_ip 是正在访问的服务的目标 ip,它应该有与之绑定的响应进程,即 tomcat、webapp 等等。
在 dmz 边缘:
ssh -o ExitOnForwardFailure=yes -f -L localhost_ip:port:desthost_ip:port user@dest_ip -i xyz.key sleep 15
因此,如果 localhost 也有一个公共 IP;假设 desthost 正在运行基于 https 的服务,那么类似这样的操作就可以奏效:
https://public_ip_of_localhost:port
这应该会显示 desthost_ip:port 服务网页。
ssh -o ExitOnForwardFailure=yes -f -L 192.168.1.199:8001:192.168.2.10:8081 [email protected] -i xyz.key sleep 15
和
https://192.168.1.199:8001
或者
https://public_ip_for_192.168.1.199:8001
将打开服务页面192.168.2.10:8081
。