我有一个用于进行一些环境设置的 bash 脚本,其中一个步骤要求我使用 SSH 隧道进行授权。我的脚本在 gnome 环境中运行良好,但在 kde 环境中运行却遇到了麻烦。
gnome-terminal -- ssh -L <>
在 kde 中,这相当于什么?我试过了konsole --new-tab
,这会打开一个新选项卡,但不执行任何操作,除非我关闭这个新窗口,否则我无法返回到上一个终端。
我也尝试使用xterm
但xterm -e ssh -L
存在同样的问题,如果不关闭此会话,我就无法使用我之前的终端,这样做会导致许可证检查失败。
答案1
分析
您的命令:
gnome-terminal -- ssh -L …
从 shell 或 shell 脚本运行时同步运行。shell 等待它退出后再接受下一个命令。重要的是gnome-terminal
做一些事情来提前退出。
如果gnome-terminal
从内部运行gnome-terminal
(因此环境包含GNOME_TERMINAL_*
变量)则新gnome-terminal
进程将把任务委托给已经运行的进程gnome-terminal
并退出。
如果不是从内部gnome-terminal
创建,则会创建另一个新进程gnome-terminal
来处理任务,而无需与原始终端和脚本建立连接。gnome-terminal
脚本生成的进程将在委派任务后退出。
因此,无论如何都将在非您脚本的子脚本ssh
下运行。您脚本的子脚本将提前退出并允许脚本继续运行。gnome-terminal
使用konsole
或 则xterm
不同。脚本生成的进程本身负责充当 的终端仿真器ssh
,因此脚本只有在您关闭新窗口后才会继续运行。
解决方案
解决方案有以下几种:
使用
gnome-terminal
。您不需要完整的 Gnome 桌面即可使用此程序。我使用 KDE Plasma 并已安装gnome-terminal
进行测试,以便能够回答此类问题。你的脚本将(仍然)依赖于
gnome-terminal
。Spawn
xterm
(或konsole
其他)异步地:xterm -e ssh -L … &
。我想这可能是最简单的解决办法。该xterm
进程将成为您脚本的子进程,但脚本不会等待它。请注意,脚本无法轻易判断是否ssh
已通过身份验证以及端口转发是否有效;但我猜同样的问题也发生在 上gnome-terminal
,因此您的脚本可能考虑到了这一点。您的脚本将依赖于
xterm
(或konsole
或其他)。使用终端多路复用器:
screen
或tmux
。您的脚本将依赖于
screen
或tmux
。这似乎并不比上述替代方案更好,但这些终端多路复用器不与任何桌面环境相关联,即使没有任何桌面它们也可以工作。我提到它们是为了让答案更完整。ssh
无需创建任何附加终端即可运行。见下文。您的脚本将摆脱一个依赖关系。
ssh
无需创建额外终端即可运行
在许多情况下,这种解决方案是最优雅的。它可能对你有好处,也可能没好处。你还没有透露你ssh
在远程端做了什么。如果它只是转发端口(因此你可以使用ssh -N
)或者如果在远程端运行的命令是非交互式的,那么你应该使用ssh -f
:
-f
请求ssh
在命令执行前转至后台。如果ssh
要询问密码或口令,但用户希望在后台执行,则此功能很有用。[…]
即使您ssh
不打算要求输入密码/密码短语,也比您可以在假设隧道有效之前使用它并检查其退出状态-f
更好。ssh … &
-o ExitOnForwardFailure
另外使用-o ControlMaster=yes -o ControlPath=…
(简称),以便您稍后-MS …
可以轻松使用来终止主服务器。在ssh
-O exit
我的这个答案您将找到一个执行此操作的脚本。完美的脚本将终止主连接并在退出前进行清理,即使使用Ctrl+ C(使用trap
)终止也是如此。
另一方面,如果你可以设置好一切,这样ssh
就不会要求任何东西,然后考虑autossh
在后台(autossh … &
)创建一个隧道并不断尝试更新它以防连接中断。请参阅另一个答案。