Bash script untuk mengatur terowongan SSH sementara

132

Di Cygwin, saya ingin skrip Bash:

  1. Buat terowongan SSH ke server jauh.
  2. Lakukan beberapa pekerjaan secara lokal yang menggunakan terowongan.
  3. Lalu matikan terowongan.

Bagian shutdown membuat saya bingung.

Saat ini, saya punya solusi lumpuh. Dalam satu shell saya menjalankan yang berikut ini untuk membuat terowongan:

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

Kemudian, di jendela shell lain, saya melakukan pekerjaan saya:

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

Akhirnya, ketika saya selesai, saya menutup jendela shell pertama untuk membunuh terowongan.

Saya ingin melakukan ini semua dalam satu skrip seperti:

# Create tunnel
# Do work
# Kill tunnel

Bagaimana cara melacak proses terowongan, jadi saya tahu yang harus dibunuh?

jm.
sumber
Saya menulis sebuah skrip yang akan membantu untuk melakukan ssh tunneling, Anda dapat memeriksanya di: github.com/gdbtek/ssh-tunneling.git
Nam Nguyen

Jawaban:

324

Anda dapat melakukan ini dengan bersih dengan ssh 'control socket'. Untuk berbicara dengan proses SSH yang sudah berjalan dan mendapatkannya pid, bunuh itu dll. Gunakan 'control socket' (-M untuk master dan -S untuk socket) sebagai berikut:

$ 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. 

Perhatikan bahwa my-ctrl-socket akan menjadi file aktual yang dibuat.

Saya mendapat info ini dari balasan yang sangat RTFM di milis OpenSSH .

Chris McCormick
sumber
6
Ini adalah jawaban terbaik yang saya lihat pada topik sejauh ini. Terima kasih banyak, seharusnya yang diterima. Saya menggunakan ini untuk terhubung ke Vagrant VM saya dan menjalankan skrip pembaruan FlywayDB.
Christian
2
Rupanya soket kontrol tidak berfungsi di mana-mana. Sebagai contoh, saya mendapatkan Operation not permittedlingkungan integrasi berkesinambungan drone.io:muxserver_listen: link mux listener ssh-ctrl-socket.wsASkszgSBlK7kqD => ssh-ctrl-socket: Operation not permitted
Mikko Ohtamaa
Jadi apa yang terjadi pada my-ctrl-socketfile setelah ini dijalankan? Ketika saya melakukannya ls -ladi folder saat ini saya tidak dapat melihat file lagi.
sachinruk
2
Jika Anda menggunakannya dalam skrip, Anda perlu menunggu soket kontrol selama beberapa detik agar tersedia. Solusi saya:while [ ! -e $ctrl_socket ]; do sleep 0.1; done
Adam Wallner
ketika saya melakukan ini saya mendapatkan open failed: administratively prohibited: open faileddan saya tidak berpikir itu membuka terowongan
Andy Ray
21

Anda dapat memberitahu SSH untuk melatarbelakanginya sendiri dengan opsi -f tetapi Anda tidak akan mendapatkan PID dengan $ !. Juga alih-alih membuat skrip Anda tidur dalam jumlah waktu yang sewenang-wenang sebelum Anda menggunakan terowongan, Anda dapat menggunakan -o ExitOnForwardFailure = ya dengan -f dan SSH akan menunggu semua port jarak jauh ke depan berhasil dibuat sebelum menempatkan dirinya di latar belakang. Anda dapat menangkap output ps untuk mendapatkan PID. Misalnya bisa Anda gunakan

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

dan pastikan Anda mendapatkan PID yang diinginkan

Maine Guy
sumber
Anda mungkin tidak menyadarinya, tetapi ini agak jenius. Saya sedang mencari cara untuk melacak PID terowongan SSH dan hampir berakhir menggunakan skrip layanan systemd. Tidak lagi: Saya bisa memahami proses SSH yang saya butuhkan menggunakan nama terowongan. Gagasan ini entah bagaimana sepenuhnya melompati saya. Terima kasih banyak!
aexl
19
  • Anda dapat memberitahu sshuntuk pergi ke latar belakang dengan &dan tidak membuat shell di sisi lain (cukup buka terowongan) dengan bendera command line (saya melihat Anda sudah melakukan ini dengan-N ).
  • Simpan PID dengan PID=$!
  • Kerjakan barangmu
  • kill $PID

EDIT: Fixed $? ke $! dan menambahkan &

Zeiss
sumber
3
Jika skrip saya mati di suatu tempat sebelum sampai ke KILL, saya harus berhati-hati untuk menanganinya.
jm.
2
@ jm: trap 'kill $PID' 1 2 15akan mencakup banyak kasus kegagalan skrip.
Norman Ramsey
3
Agar ini dapat bekerja dengan andal, saya harus "tidur" sedikit SETELAH membuat terowongan, tetapi sebelum menggunakannya.
jm.
@NormanRamsey Saya pikir maksud Anda trap "kill $PID", karena bash hanya akan menginterpolasi variabel di dalam string yang dikutip ganda
JuanCaicedo
1
@JuanCaicedo Perbedaannya hanya penting jika PIDvariabelnya didefinisikan ulang nanti. Variabel diperluas ketika trapbuilt-in disebut (pendekatan OP) atau ketika sinyal ditangkap (pendekatan Anda); kedua pendekatan menghasilkan hasil yang sama di sini.
Witiko
4

Saya lebih suka meluncurkan shell baru untuk tugas yang terpisah dan saya sering menggunakan kombinasi perintah berikut:

  $ sudo bash; exit

atau terkadang:

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

Perintah-perintah ini membuat shell bersarang di mana saya bisa melakukan semua pekerjaan saya; ketika saya selesai saya menekan CTRL-D dan shell induk membersihkan dan keluar juga. Anda dapat dengan mudah melempar bash;ke skrip terowongan ssh Anda tepat sebelum killbagian sehingga ketika Anda keluar dari cangkang bersarang, terowongan Anda akan ditutup:

#!/bin/bash
ssh -nNT ... &
PID=$!
bash
kill $PID
terlalu banyak php
sumber
Sangat menarik. Ini mungkin menangani masalah "jebakan" dengan lebih baik. Harus mencobanya.
jm.
2

Anda bisa meluncurkan sshdengan a &the end, untuk meletakkannya di latar belakang dan ambil id saat melakukannya. Maka Anda hanya perlu melakukan killid itu ketika Anda selesai.

Valentin Rocher
sumber
Waspadai jika menggunakan ampersand ("&"). Ini adalah pendekatan yang jelek karena Anda harus menentukan koneksi yang sebenarnya dibuat untuk diri sendiri. Hal ini dapat menyebabkan kode lebih lanjut dieksekusi yang tidak menunggu koneksi yang sebenarnya akan dibuat sepenuhnya. Selanjutnya koneksi tidak akan terbunuh secara otomatis jika skrip terputus.
Jonathan
2

Opsi potensial lain - jika Anda dapat menginstal paket yang diharapkan, Anda harus dapat menulis semuanya. Beberapa contoh bagus di sini: http://en.wikipedia.org/wiki/Expect

Phil Pelanne
sumber