在CYGWIN上,我想要一个BASH脚本:
“关闭部分”让我感到困惑。
目前,我有一个蹩脚的解决方案。在一个shell中,我运行以下命令来创建一个隧道。
# Create the tunnel - this works! It runs forever, until 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)
最后,当我完成时。我关闭了第一个shell窗口以杀死隧道。
我想在一个脚本中执行此操作,例如: #创建隧道 # 做工作 #杀死隧道
如何跟踪隧道过程,所以我知道要杀死哪一个?
答案 0 :(得分:290)
您可以使用ssh'控制套接字'干净利落地完成此操作。要与已经运行的SSH进程通信并获取它的pid,请将其删除等。使用'control socket'(-M代表master,-S代表socket),如下所示:
$ 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.
请注意,my-ctrl-socket将是一个创建的实际文件。
答案 1 :(得分:19)
您可以使用-f选项告诉SSH背景本身,但不会使用$!获取PID。 此外,在使用隧道之前,您可以使用-o ExitOnForwardFailure = yes而不是让脚本在任意时间内休眠,并且在将自身置于后台之前,SSH将等待所有远程端口转发成功建立。您可以grep ps的输出来获取PID。例如,您可以使用
...
ssh -Cfo ExitOnForwardFailure=yes -NL 9999:localhost:5900 $REMOTE_HOST
PID=$(pgrep -f 'NL 9999:')
[ "$PID" ] || exit 1
...
并且非常确定您获得了所需的PID
答案 2 :(得分:18)
ssh
使用&
进入后台,而不是使用命令行标记在另一侧创建一个shell(只是打开隧道)(我看到您已经使用{ {1}})。-N
PID=$!
答案 3 :(得分:4)
我更喜欢为单独的任务启动一个新的shell,我经常使用以下命令组合:
$ sudo bash; exit
或有时:
$ : > sensitive-temporary-data.txt; bash; rm -f sensitive-temporary-data.txt; exit
这些命令创建了一个嵌套的shell,我可以完成所有工作;当我完成后我按下CTRL-D并且父shell清理并退出。您可以轻松地将bash;
放入kill
部分之前的ssh隧道脚本中,这样当您退出嵌套shell时,您的隧道将被关闭:
#!/bin/bash
ssh -nNT ... &
PID=$!
bash
kill $PID
答案 4 :(得分:2)
您可以在结尾处ssh
启动&
,将其置于后台并在执行时获取其ID。然后,当你完成时,你只需要做{id} kill
。
答案 5 :(得分:2)
另一个可能的选择 - 如果你可以安装expect包,你应该能够编写整个脚本。这里有一些很好的例子:http://en.wikipedia.org/wiki/Expect
答案 6 :(得分:-1)
https://github.com/aronpc/remina-ssh-tunnel
#!/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
编辑或创建新的 remmina 服务器连接
架构
~/.ssh/rdp-tunnel.sh ACTION TUNNELNAME LOCAL_PORT:REMOTE_SERVER:REMOTE_PORT TUNNEL_PROXY
姓名 | 描述 |
---|---|
行动 | 开始|停止 |
隧道名称 | "字符串识别套接字" slugify 创建套接字文件到 ~/.ssh/sockets/string-identify-socket.control |
LOCAL_PORT | 如果我们为两个连接使用相同的端口,将会在本地暴露的门会崩溃 |
REMOTE_SERVER | 如果您在将要使用的代理服务器上拥有它,您将访问的服务器的 IP |
REMOTE_PORT | 运行在服务器上的服务端口 |
TUNNEL_PROXY | 您将用作代理的连接,它需要在您的 ~/.ssh/config 中,最好使用访问密钥 |
我使用remmina组名和连接名的组合(% g-% p)作为我的TUNNELNAME(这需要唯一,它会看到套接字名称)
前置命令
~/.ssh/rdp-tunnel.sh start "%g-%p" 63394:192.168.8.176:3389 tunnel-name-1
后命令
~/.ssh/rdp-tunnel.sh stop "%g-%p" 63394:192.168.8.176:3389 tunnel-name-1
你可以而且应该使用这个脚本来访问任何东西,我经常用它来访问没有公共 IP 的系统和服务,这些系统和服务通过 1、2、3、4、5 或更多的 ssh 代理强>
查看更多:
参考: