Na Cygwin chcę, aby skrypt Bash:
- Utwórz tunel SSH do zdalnego serwera.
- Wykonaj prace lokalnie, korzystając z tunelu.
- Następnie zamknij tunel.
Część z zamknięciem wprawia mnie w zakłopotanie.
Obecnie mam kiepskie rozwiązanie. W jednej powłoce uruchamiam następujące, aby utworzyć tunel:
# Create the tunnel - this works! It runs forever, until the shell is quit.
ssh -nNT -L 50000:localhost:3306 [email protected]
Następnie w innym oknie powłoki wykonuję swoją pracę:
# Do some MySQL stuff over local port 50000 (which goes to remote port 3306)
Wreszcie, kiedy skończę, zamykam pierwsze okno powłoki, aby zabić tunel.
Chciałbym to wszystko zrobić w jednym skrypcie, takim jak:
# Create tunnel
# Do work
# Kill tunnel
Jak mogę śledzić proces tunelowania, żeby wiedzieć, który zabić?
Odpowiedzi:
Możesz to zrobić czysto za pomocą gniazda sterującego ssh. Aby porozmawiać z już działającym procesem SSH i uzyskać jego pid, zabij go itp. Użyj 'gniazda sterującego' (-M dla mastera i -S dla gniazda) w następujący sposób:
$ ssh -M -S my-ctrl-socket -fnNT -L 50000:localhost:3306 [email protected] $ ssh -S my-ctrl-socket -O check [email protected] Master running (pid=3517) $ ssh -S my-ctrl-socket -O exit [email protected] Exit request sent.
Zauważ, że my-ctrl-socket będzie rzeczywistym plikiem, który jest tworzony.
Mam tę informację od bardzo RTFM odpowiedzi na liście mailingowej OpenSSH .
źródło
Operation not permitted
na środowisko ciągłej integracji drone.io:muxserver_listen: link mux listener ssh-ctrl-socket.wsASkszgSBlK7kqD => ssh-ctrl-socket: Operation not permitted
my-ctrl-socket
plikiem po uruchomieniu? Kiedy znajduję sięls -la
w bieżącym folderze, nie widzę już pliku.while [ ! -e $ctrl_socket ]; do sleep 0.1; done
open failed: administratively prohibited: open failed
i nie sądzę, żeby otwierało tunelMożesz nakazać SSH, aby działało w tle za pomocą opcji -f, ale nie otrzymasz PID z $ !. Ponadto zamiast spać przez dowolną ilość czasu przed użyciem tunelu przez skrypt, możesz użyć -o ExitOnForwardFailure = yes z -f, a SSH będzie czekało na pomyślne ustanowienie wszystkich zdalnych portów przed umieszczeniem się w tle. Możesz grepować wyjście ps, aby uzyskać PID. Na przykład możesz użyć
... ssh -Cfo ExitOnForwardFailure=yes -NL 9999:localhost:5900 $REMOTE_HOST PID=$(pgrep -f 'NL 9999:') [ "$PID" ] || exit 1 ...
i upewnij się, że otrzymujesz pożądany PID
źródło
ssh
aby przejść do tła&
i nie tworzyć powłoki po drugiej stronie (po prostu otwórz tunel) z flagą wiersza poleceń (widzę, że już to zrobiłeś-N
).PID=$!
kill $PID
EDYCJA: Naprawiono $? do $! i dodał &
źródło
trap 'kill $PID' 1 2 15
obejmie wiele przypadków awarii skryptu.trap "kill $PID"
, ponieważ bash interpoluje zmienne tylko w podwójnych cudzysłowachPID
zmienna została później przedefiniowana. Zmienna jest rozwijana, gdytrap
wywoływana jest funkcja wbudowana (podejście OP) lub gdy sygnał został przechwycony (twoje podejście); oba podejścia dają ten sam rezultat.Wolę uruchamiać nową powłokę do oddzielnych zadań i często używam następującej kombinacji poleceń:
$ sudo bash; exit
lub czasami:
$ : > sensitive-temporary-data.txt; bash; rm -f sensitive-temporary-data.txt; exit
Te polecenia tworzą zagnieżdżoną powłokę, w której mogę wykonywać całą swoją pracę; kiedy skończę, wciskam CTRL-D, a powłoka rodzica czyści się i również wychodzi. Możesz łatwo wrzucić
bash;
do skryptu tunelu ssh tuż przedkill
częścią, aby po wylogowaniu się z zagnieżdżonej powłoki Twój tunel został zamknięty:#!/bin/bash ssh -nNT ... & PID=$! bash kill $PID
źródło
Możesz uruchomić
ssh
z&
zakończeniem a, aby umieścić go w tle i pobrać jego identyfikator podczas wykonywania. Następnie musisz po prostu zrobićkill
z tego identyfikatora, kiedy skończysz.źródło
Kolejna potencjalna opcja - jeśli możesz zainstalować pakiet oczekujący, powinieneś być w stanie napisać skrypt. Oto kilka dobrych przykładów: http://en.wikipedia.org/wiki/Expect
źródło