用于设置临时SSH隧道的Bash脚本
在Cygwin上,我需要一个Bash脚本:用于设置临时SSH隧道的Bash脚本,bash,ssh,Bash,Ssh,在Cygwin上,我需要一个Bash脚本: 创建到远程服务器的SSH隧道 在使用隧道的地方做一些工作 然后关闭隧道 关机部分让我感到困惑 目前,我有一个蹩脚的解决方案。在一个shell中,我运行以下命令来创建隧道: # Create the tunnel - this works! It runs forever, until the shell is quit. ssh -nNT -L 50000:localhost:3306 jm@sampledomain.com 然后,在另一个shell
# Create the tunnel - this works! It runs forever, until the shell is quit.
ssh -nNT -L 50000:localhost:3306 jm@sampledomain.com
然后,在另一个shell窗口中,我执行我的工作:
# Do some MySQL stuff over local port 50000 (which goes to remote port 3306)
最后,当我完成时,我关闭第一个外壳窗口以杀死隧道
我想在一个脚本中完成这一切,如:
# Create tunnel
# Do work
# Kill tunnel
如何跟踪隧道进程,以便知道要杀死哪一个?您可以启动
ssh
,最后使用&
a,将其放在后台,并在执行时获取其id。然后你只需在完成后对该id执行一个杀死。
- 您可以告诉
ssh
使用&
进入后台,而不使用命令行标志在另一侧创建shell(只需打开隧道)(我看到您已经使用-N
完成了此操作)
- 使用
PID=$保存PID代码>
- 做你的事
kill$PID
编辑:固定$?到美元!并添加了&我更喜欢为单独的任务启动一个新的shell,并且我经常使用以下命令组合:
$ sudo bash; exit
或者有时:
$ : > sensitive-temporary-data.txt; bash; rm -f sensitive-temporary-data.txt; exit
这些命令创建一个嵌套的shell,我可以在其中完成所有工作;完成后,我按CTRL-D键,父shell也会清理并退出。您可以轻松地抛出bash在kill
部分之前,将code>写入ssh隧道脚本中,这样当您从嵌套shell中注销时,隧道将关闭:
#!/bin/bash
ssh -nNT ... &
PID=$!
bash
kill $PID
您可以告诉SSH使用-f选项将其自身设置为后台,但使用$!,将无法获得PID!。
另外,在使用隧道之前,您可以使用-f和-o ExitOnForwardFailure=yes,而不是让脚本睡眠任意时间,SSH将等待所有远程端口转发成功建立,然后再将其置于后台。您可以对ps的输出进行grep以获得PID。例如,您可以使用
...
ssh -Cfo ExitOnForwardFailure=yes -N -L 9999:localhost:5900 $REMOTE_HOST
PID=$(pgrep -f 'N -L 9999:')
[ "$PID" ] || exit 1
...
并且要确保获得了所需的PID,您可以使用ssh“控制套接字”干净地完成这项工作。要与已经运行的SSH进程对话并获取其pid,请杀死它,等等。使用“控制套接字”(-M表示主进程,-s表示套接字),如下所示:
$ ssh -M -S my-ctrl-socket -fnNT -L 50000:localhost:3306 jm@sampledomain.com
$ ssh -S my-ctrl-socket -O check jm@sampledomain.com
Master running (pid=3517)
$ ssh -S my-ctrl-socket -O exit jm@sampledomain.com
Exit request sent.
请注意,我的ctrl套接字将是实际创建的文件
我从中获得此信息。
用法示例
编辑或创建新的remmina服务器连接
模式
~/.ssh/rdp-tunnel.sh操作隧道名称本地\u端口:远程\u服务器:远程\u端口隧道\u代理
名称
描述
行动
开始|停止
隧道名称
“string-identify-socket”slugify将套接字文件创建到~/.ssh/sockets/string-identify-socket.control中
本地\u端口
如果我们在两个连接中使用同一端口,将暴露在局部的门将崩溃
远程_服务器
如果在将要使用的代理服务器上有服务器,则要访问的服务器的ip
远程\u端口
在服务器上运行的服务端口
隧道代理
要用作代理的连接,它需要位于~/.ssh/config中,最好使用访问密钥
如果我的脚本在到达KILL之前的某个地方死掉,我必须小心处理。@jm:trap'KILL$PID'1 2 15
将涵盖许多脚本失败的情况。为了可靠地工作,我必须在创建隧道之后,但在使用它之前“睡眠”一点。@NormanRamsey我想你的意思是trap'KILL$PID”
,因为bash只会在双引号内插入变量strings@JuanCaicedo只有在以后重新定义PID
变量时,这种区别才是重要的。当调用陷阱
内置时(OP的方法),或者当捕捉到信号时(您的方法),变量会展开;这两种方法在这里产生相同的结果。非常有趣。这样可以更好地处理“陷阱”问题。我得试试。这是我迄今为止在这个话题上看到的最好的答案。非常感谢,它应该是被接受的。我用它连接到我的Vagrant VM并运行FlywayDB更新脚本。显然,控制套接字并不适用于任何地方。例如,我在drone.io持续集成环境上获得了不允许操作
:muxserver\u listen:link mux listener ssh-ctrl-socket.wsaskszgszgsblk7kqd=>ssh-ctrl-socket:Operation not allowed
,那么运行后我的ctrl-socket
文件会发生什么情况?当我在当前文件夹中执行ls-la
操作时,我再也看不到该文件。如果在脚本中使用它,则需要等待控制套接字几秒钟才能可用。我的解决方案:while[!-e$ctrl\u socket];睡眠0.1;完成了
绝妙的东西,比我在网上找到的其他东西都优雅得多。ThanksI编写了一个脚本,可以帮助执行ssh隧道,您可以在以下位置查看它:如果使用符号(&),请注意。这是一个丑陋的方法,因为你必须确定为自己建立的实际联系。它可能导致执行更多的代码,而不是等待完全建立实际连接。此外,如果脚本中断,连接不会自动终止。你可能没有意识到,但这是一种天才。我正在寻找跟踪SSH隧道PID的方法,结果几乎使用了systemd服务脚本。不再是了:我可以使用隧道名称grep我需要的SSH进程。不知何故,我完全没有想到这个想法。谢谢!虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-谢谢,我设法放了readme.md,我不知道我有
#!/usr/bin/env sh
scriptname="$(basename $0)"
actionname="$1"
tunnelname=$(echo "$2" | iconv -t ascii//TRANSLIT | sed -E 's/[^a-zA-Z0-9-]+/-/g' | sed -E 's/^-+|-+$//g' | tr A-Z a-z)
remotedata="$3"
tunnelssh="$4"
if [ $# -lt 4 ]
then
echo "Usage: $scriptname start | stop LOCAL_PORT:RDP_IP:RDP_PORT SSH_NODE_IP"
exit
fi
case "$actionname" in
start)
echo "Starting tunnel to $tunnelssh"
ssh -M -S ~/.ssh/sockets/$tunnelname.control -fnNT -L $remotedata $tunnelssh
ssh -S ~/.ssh/sockets/$tunnelname.control -O check $tunnelssh
;;
stop)
echo "Stopping tunnel to $tunnelssh"
ssh -S ~/.ssh/sockets/$tunnelname.control -O exit $tunnelssh
;;
*)
echo "Did not understand your argument, please use start|stop"
;;
esac