임시 SSH 터널을 설정하기위한 Bash 스크립트


132

Cygwin에서 Bash 스크립트는 다음과 같습니다.

  1. 원격 서버에 대한 SSH 터널을 작성하십시오.
  2. 터널을 사용하는 로컬 작업을 수행하십시오.
  3. 그런 다음 터널을 종료하십시오.

셧다운 부분이 당황했습니다.

현재 저는 절름발이 해결책이 있습니다. 하나의 쉘에서 다음을 실행하여 터널을 만듭니다.

# Create the tunnel - this works! It runs forever, until the shell is quit.
ssh -nNT -L 50000:localhost:3306 jm@sampledomain.com

그런 다음 다른 쉘 창에서 작업을 수행합니다.

# Do some MySQL stuff over local port 50000 (which goes to remote port 3306)

마지막으로, 완료되면 터널을 종료하기 위해 첫 번째 셸 창을 닫습니다.

이 모든 것을 하나의 스크립트로 수행하고 싶습니다.

# Create tunnel
# Do work
# Kill tunnel

터널 프로세스를 추적하려면 어떻게해야합니까?


ssh 터널링에 도움이되는 스크립트를 작성했습니다. github.com/gdbtek/ssh-tunneling.git
Nam Nguyen

답변:


324

ssh 'control socket'을 사용하여 깨끗하게 할 수 있습니다. 이미 실행중인 SSH 프로세스와 대화하고 pid를 얻으려면 etc로 종료하십시오. 다음과 같이 '제어 소켓'(마스터의 경우 -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. 

my-ctrl-socket은 생성 된 실제 파일입니다.

OpenSSH 메일 링리스트의 RTFM 응답 에서이 정보를 얻었습니다 .


6
이것이 지금까지 내가 본 주제에서 가장 좋은 답변입니다. 대단히 감사합니다. 받아 들여 져야합니다. 이를 사용하여 Vagrant VM에 연결하고 FlywayDB 업데이트 스크립트를 실행합니다.
Christian

2
분명히 제어 소켓은 모든 곳에서 작동하지 않습니다. 예를 들어, 저는 Operation not permitteddrone.io 연속 통합 환경을 사용합니다.muxserver_listen: link mux listener ssh-ctrl-socket.wsASkszgSBlK7kqD => ssh-ctrl-socket: Operation not permitted
Mikko Ohtamaa

my-ctrl-socket이것이 실행 된 후 파일 은 어떻게됩니까 ? ls -la현재 폴더에서 할 때 더 이상 파일을 볼 수 없습니다.
sachinruk

2
스크립트에서 사용하는 경우 몇 초 동안 제어 소켓을 사용할 수있을 때까지 기다려야합니다. 내 솔루션 :while [ ! -e $ctrl_socket ]; do sleep 0.1; done
Adam Wallner

이 작업을 수행 할 때 open failed: administratively prohibited: open failed터널이 열리고 있다고 생각하지 않습니다.
Andy Ray

21

-f 옵션을 사용하여 SSH 자체를 백그라운드로 지정할 수 있지만 $!로 PID를 얻지 못합니다. 또한 터널을 사용하기 전에 스크립트를 임의의 시간 동안 휴면 상태로 유지하는 대신 -o와 함께 -o ExitOnForwardFailure = yes를 사용하면 SSH는 백그라운드에서 자신을 배치하기 전에 모든 원격 포트 전달이 성공적으로 설정 될 때까지 대기합니다. ps의 출력을 grep하여 PID를 얻을 수 있습니다. 예를 들어

...
ssh -Cfo ExitOnForwardFailure=yes -NL 9999:localhost:5900 $REMOTE_HOST
PID=$(pgrep -f 'NL 9999:')
[ "$PID" ] || exit 1
...

원하는 PID를 얻었는지 확인하십시오.


당신은 그것을 알지 못할 수도 있지만 이것은 일종의 천재입니다. SSH 터널 PID를 추적하는 방법을 찾고 있었고 거의 시스템 서비스 스크립트를 사용했습니다. 더 이상 : 터널 이름을 사용하여 필요한 SSH 프로세스를 grep 할 수 있습니다. 이 아이디어는 어떻게 든 나를 완전히 건너 뛰었습니다. 고마워요!
aexl

19
  • 명령 행 플래그를 사용하여 다른쪽에 쉘을 만들지 말고 (터널을 열면) 이미 ssh배경으로 이동하도록 지시 할 수 있습니다 &(이미 이미 사용했습니다 -N).
  • PID를 저장하십시오 PID=$!
  • 당신의 일을
  • kill $PID

편집 : 고정 $? ~에! &를 추가했습니다.


3
킬에 도달하기 전에 스크립트가 어딘가에서 죽으면 처리해야합니다.
jm.

2
@jm : trap 'kill $PID' 1 2 15많은 스크립트 실패 사례를 다룰 것입니다.
Norman Ramsey

3
이 작업을 안정적으로 수행하려면 터널을 만든 후 약간의 "잠을 자야"하지만 터널을 사용하기 전에해야했습니다.
jm.

난 당신 말은 생각 @NormanRamsey trap "kill $PID"때문에 bash는 것이다 이중 인용 문자열 내에서만 보간 변수
JuanCaicedo

1
@JuanCaicedo PID변수는 나중에 변수를 다시 정의한 경우에만 중요합니다 . 변수는 trap내장 함수가 호출 될 때 (OP의 접근 방식) 또는 신호가 잡힐 때 (접근 방식) 확장됩니다. 두 방법 모두 동일한 결과를 생성합니다.
Witiko

4

별도의 작업을 위해 새 셸을 시작하는 것을 선호하며 종종 다음 명령 조합을 사용합니다.

  $ sudo bash; exit

또는 때로는 :

  $ : > sensitive-temporary-data.txt; bash; rm -f sensitive-temporary-data.txt; exit

이 명령은 모든 작업을 수행 할 수있는 중첩 쉘을 만듭니다. 완료되면 CTRL-D를 누르고 부모 셸이 정리되고 종료됩니다. 중첩 된 쉘에서 로그 아웃 할 때 터널이 닫히도록 파트 bash;바로 전에 ssh 터널 스크립트에 쉽게 넣을 수 있습니다 kill.

#!/bin/bash
ssh -nNT ... &
PID=$!
bash
kill $PID

매우 흥미로운. 이것은 "트랩"문제를 더 잘 처리 할 수 ​​있습니다. 시도해야합니다.
jm.

2

당신은을 시작할 수 ssh&배경에 넣고 할 때 해당 ID를 잡기 위해하는 말. 그런 다음 kill완료되면 해당 ID 를 수행해야합니다 .


앰퍼샌드 ( "&")를 사용하는지 확인하십시오. 자신을 위해 설정된 실제 연결을 결정해야하기 때문에 추악한 방법입니다. 실제 연결이 완전히 완료되기를 기다리지 않는 추가 코드가 실행되도록 할 수 있습니다. 또한 스크립트가 중단되면 연결이 자동으로 종료되지 않습니다.
조나단

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.