Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于设置临时SSH隧道的Bash脚本_Bash_Ssh - Fatal编程技术网

用于设置临时SSH隧道的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

在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窗口中,我执行我的工作:

    # 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也会清理并退出。您可以轻松地抛出
    bashkill
    部分之前,将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