我从这个完全有效的 ssh 命令开始:
$ ssh -fNL 3306:localhost:3306 [email protected]
这个配置让我得到了我所追求的部分简化:
Host tunnel
HostName database.example.com
IdentityFile ~/.ssh/coolio.example.key
LocalForward 3306 localhost:3306
User coolio
我可以用这个命令连接,这要好得多:
$ ssh -f -N tunnel
我现在的问题是如何对其进行参数化,以便我可以执行此操作(或类似操作):
$ ssh -f -N tunnel -p 3306
或者:
$ ssh -f -N tunnel -p 5678
顺便说一句,在我上面的示例中,我故意在两个地方使用相同的端口号。这就是我在这种情况下所需要的。 (但我也想知道如果端口不同,如何对其进行参数化。)
到目前为止我尝试过的:
Host tunnel
HostName database.example.com
IdentityFile ~/.ssh/coolio.example.key
LocalForward %p localhost:%p
User coolio
这给出了错误:
ssh/config 错误的转发规范
参考:
http://nerderati.com/2011/03/simplify-your-life-with-an-ssh-config-file/
答案1
这不是最优雅的方式,但我会这样做:
将原始文件中的端口规范替换为唯一的模式。例如:
LocalForward myport localhost:myport
ssh
来自您的别名.bashrc
:alias ssh='/path/to/ssh_wrapper.pl'
写入文件
/path/to/ssh_wrapper.pl
:#!/usr/bin/perl use strict; use warnings; my $cmdline = join ' ',@ARGV; if($cmdline =~ / -p\s*([0-9]+)\b/ and $cmdline=~ / -N/){ my $port = $1; system("sed 's/myport/$port/g' /etc/ssh/ssh_config > /tmp/ssh_config"); } else{ system("sed 's/LocalForward/#LocalForward/' /etc/ssh/ssh_config > /tmp/ssh_config"); } $cmdline .= ' -F /tmp/ssh_config'; my $pid = fork; $pid ? wait : exec("/usr/bin/ssh $cmdline"); unlink '/tmp/ssh_config';
基本上,这将解析您的
ssh
命令行,如果它找到一个-p
后跟数字端口规范的选项,它将通过用您在命令行上指定的数字端口值替换每个出现的位置来创建一个新ssh_config
选项。之后,它-使用命令行对真实的系统调用。如果它创建了自己的配置文件,它会在命令行中添加一个选项,以确保从新创建的配置文件中读取。最后,父进程让fork 完成,然后删除临时配置文件。/tmp/ssh_config
myport
fork
exec
ssh
-F
ssh
wait
ssh
ssh
免责声明
该代码未经测试。尝试需要您自担风险。首先备份您的配置文件!
编辑
当您不通过提供数字端口时,前面编写的代码将因“错误的端口规范”错误而中断,-p
因此我添加了代码来注释该LocalForward
部分,以防不需要它。我还确保配置文件中的替换不会发生,除非还有一个-N
选项,因为您可能希望指定一个端口-p
而不需要转发(例如ssh
进入使用非标准端口的盒子)。
答案2
我解决这个问题的一个更简单的方法是在我的 .bashrc 中创建一个函数
sshfw () {
ssh -fNL "$1":localhost:"$1" "$2"
}
现在我可以做
sshfw 8890 [email protected]