Tập lệnh Bash để thiết lập một đường hầm SSH tạm thời


132

Trên Cygwin, tôi muốn một tập lệnh Bash:

  1. Tạo một đường hầm SSH đến một máy chủ từ xa.
  2. Làm một số công việc địa phương sử dụng đường hầm.
  3. Sau đó đóng cửa hầm.

Phần tắt máy làm tôi bối rối.

Hiện tại, tôi có một giải pháp khập khiễng. Trong một shell tôi chạy như sau để tạo một đường hầm:

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

Sau đó, trong một cửa sổ shell khác, tôi thực hiện công việc của mình:

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

Cuối cùng, khi tôi hoàn thành, tôi đóng cửa sổ vỏ đầu tiên để giết đường hầm.

Tôi muốn làm tất cả điều này trong một kịch bản như:

# Create tunnel
# Do work
# Kill tunnel

Làm thế nào để tôi theo dõi quá trình đường hầm, vì vậy tôi biết cái nào để giết?


Tôi đã viết một kịch bản có thể giúp thực hiện ssh đường hầm, bạn có thể kiểm tra nó tại: github.com/gdbtek/ssh-tunneling.git
Nam Nguyen

Câu trả lời:


324

Bạn có thể làm điều này một cách sạch sẽ với một 'ổ cắm điều khiển' ssh. Để nói chuyện với một quy trình SSH đã chạy và lấy nó, hãy tiêu diệt nó, v.v. Sử dụng 'ổ cắm điều khiển' (-M cho chủ và -S cho ổ cắm) như sau:

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

Lưu ý rằng my-ctrl-socket sẽ là một tệp thực sự được tạo.

Tôi đã nhận được thông tin này từ một phản hồi rất RTFM trong danh sách gửi thư OpenSSH .


6
Đây là câu trả lời tốt nhất tôi đã thấy về chủ đề cho đến nay. Cảm ơn bạn rất nhiều, nó nên được chấp nhận. Tôi sử dụng điều này để kết nối với máy ảo Vagrant của mình và chạy tập lệnh cập nhật FlywayDB.
Christian

2
Rõ ràng ổ cắm điều khiển không hoạt động ở mọi nơi. Ví dụ: tôi nhận được Operation not permittedtrên môi trường tích hợp liên tục của drone.io:muxserver_listen: link mux listener ssh-ctrl-socket.wsASkszgSBlK7kqD => ssh-ctrl-socket: Operation not permitted
Mikko Ohtamaa

Vì vậy, những gì xảy ra với các my-ctrl-sockettập tin sau khi điều này được chạy? Khi tôi làm ls -latrong thư mục hiện tại tôi không thể xem tệp nữa.
sachinruk

2
Nếu bạn sử dụng nó trong một tập lệnh, bạn cần đợi ổ cắm điều khiển trong vài giây để sẵn sàng. Giải pháp của tôi:while [ ! -e $ctrl_socket ]; do sleep 0.1; done
Adam Wallner

Khi tôi làm điều này tôi sẽ nhận được open failed: administratively prohibited: open failedvà tôi không nghĩ rằng nó sẽ mở đường hầm
Andy Ray

21

Bạn có thể yêu cầu SSH tự tạo nền với tùy chọn -f nhưng bạn sẽ không nhận được PID với $!. Ngoài ra, thay vì để tập lệnh của bạn ngủ một lượng thời gian tùy ý trước khi bạn sử dụng đường hầm, bạn có thể sử dụng -o ExitOnForwardFailure = yes với -f và SSH sẽ đợi tất cả các cổng từ xa được thiết lập thành công trước khi đặt nó vào nền. Bạn có thể grep đầu ra của ps để có được PID. Ví dụ bạn có thể sử dụng

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

và khá chắc chắn rằng bạn đang nhận được PID mong muốn


Bạn có thể không nhận ra nó, nhưng đây là loại thiên tài. Tôi đã tìm kiếm một cách để theo dõi các PID đường hầm SSH và gần như đã kết thúc bằng cách sử dụng các tập lệnh dịch vụ systemd. Không còn nữa: Tôi có thể grep quá trình SSH tôi cần bằng cách sử dụng tên đường hầm. Ý tưởng này bằng cách nào đó đã hoàn toàn bỏ qua tôi. Cảm ơn rất nhiều!
aexl

19
  • Bạn có thể yêu sshcầu đi vào nền với &và không tạo vỏ ở phía bên kia (chỉ cần mở đường hầm) bằng cờ dòng lệnh (tôi thấy bạn đã làm điều này với -N).
  • Lưu PID với PID=$!
  • Làm công việc của bạn
  • kill $PID

EDIT: Đã sửa $? đến $! và thêm &


3
Nếu kịch bản của tôi chết ở đâu đó trước khi nó bị KILL, tôi phải cẩn thận để xử lý nó.
jm.

2
@jm: trap 'kill $PID' 1 2 15sẽ bao gồm nhiều trường hợp thất bại kịch bản.
Norman Ramsey

3
Để làm việc này một cách đáng tin cậy, tôi đã phải "ngủ" một chút SAU khi tạo đường hầm, nhưng trước khi sử dụng nó.
jm.

@NormanRamsey Tôi nghĩ bạn có ý đó trap "kill $PID", bởi vì bash sẽ chỉ nội suy các biến trong các chuỗi được trích dẫn kép
JuanCaiceso

1
@JuanCaiceso Việc phân biệt sẽ chỉ quan trọng nếu PIDbiến được xác định lại sau này. Biến được mở rộng khi tích traphợp được gọi (phương pháp của OP) hoặc khi tín hiệu đã bị bắt (cách tiếp cận của bạn); cả hai cách tiếp cận đều tạo ra kết quả giống nhau ở đây.
Witiko

4

Tôi thích khởi chạy một shell mới cho các tác vụ riêng biệt và tôi thường sử dụng tổ hợp lệnh sau:

  $ sudo bash; exit

Hoặc đôi khi:

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

Các lệnh này tạo ra một lớp vỏ lồng nhau, nơi tôi có thể thực hiện tất cả công việc của mình; khi tôi kết thúc, tôi nhấn CTRL-D và shell cha cũng dọn sạch và thoát ra. Bạn có thể dễ dàng ném bash;vào tập lệnh đường hầm ssh của mình ngay trước killphần để khi bạn đăng xuất khỏi lớp vỏ lồng nhau, đường hầm của bạn sẽ bị đóng:

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

Rất thú vị. Điều này có thể xử lý vấn đề "bẫy" tốt hơn. Sẽ phải thử nó.
jm.

2

Bạn có thể khởi chạy sshvới một &kết thúc, để đặt nó vào nền và lấy id của nó khi thực hiện. Sau đó, bạn chỉ cần thực hiện một killid đó khi bạn hoàn thành.


Lưu ý nếu sử dụng ký hiệu ("&"). Đó là một cách tiếp cận xấu vì bạn sẽ phải xác định kết nối thực tế được thiết lập cho chính mình. Nó có thể khiến mã tiếp tục được thực thi mà không chờ kết nối thực tế được thiết lập đầy đủ. Hơn nữa, kết nối sẽ không bị hủy tự động nếu tập lệnh bị hỏng.
Jonathan

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.