SSH khiến vòng lặp while dừng lại


30

Cuối cùng tôi cũng đã giải quyết được một vấn đề mà tôi đã phải vật lộn trong vài tuần. Tôi sử dụng SSH với "khóa được ủy quyền" để chạy các lệnh từ xa. Tất cả đều ổn trừ khi tôi làm điều đó trong một vòng lặp while. Vòng lặp chấm dứt sau khi hoàn thành bất kỳ lần lặp nào với lệnh ssh.

Trong một thời gian dài, tôi nghĩ rằng đây là một loại kỳ lạ ksh, nhưng bây giờ tôi phát hiện ra bash thực tế hành xử giống hệt nhau.

Một chương trình mẫu nhỏ để tái tạo vấn đề. Điều này được chắt lọc từ một triển khai lớn hơn trong đó có các ảnh chụp nhanh và sao chép chúng giữa các nút trong một cụm.

#!/bin/bash

set -x

IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool

ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG    " > /tmp/actionlist

#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
   echo ${RMT_FILESYSTEM}@${MARKER}
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?
done

(Lưu ý có một ký tự TAB trong biểu thức tìm kiếm grep theo định nghĩa hành vi của danh sách zfs tùy chọn "-H".)

Mẫu của tôi có một số hệ thống tệp ZFS cho thư mục gốc trong đó tất cả các "vùng" có hệ thống tệp gốc của chúng trên tập dữ liệu có tên tương tự

POOL / khu vực / app1zone
POOL / khu vực / nhóm2 / app2zone

v.v.

Vòng lặp ở trên sẽ tạo một ảnh chụp nhanh cho mỗi bộ dữ liệu được chọn, nhưng thay vào đó, nó chỉ hoạt động trên cái đầu tiên và sau đó thoát.

Chương trình tìm thấy số lượng bộ dữ liệu phù hợp có thể dễ dàng xác nhận bằng cách kiểm tra tệp "/ tmp / actionlist" sau khi tập lệnh tồn tại.

Nếu lệnh ssh được thay thế bằng, ví dụ, lệnh echo, thì vòng lặp lặp qua tất cả các dòng đầu vào. Hoặc yêu thích của tôi - thêm "echo" vào lệnh vi phạm.

Nếu tôi sử dụng một vòng lặp for thay thế thì nó cũng hoạt động, nhưng do kích thước tiềm năng của danh sách các bộ dữ liệu, điều này có thể gây ra vấn đề với độ dài dòng lệnh mở rộng tối đa.

Bây giờ tôi chắc chắn 99,999% rằng chỉ những vòng lặp có lệnh ssh trong đó mới gây ra sự cố cho tôi!

Lưu ý rằng việc lặp lại trong đó lệnh ssh chạy, hoàn thành! Như thể dữ liệu được đưa vào vòng lặp while bị mất đột ngột ... Nếu một vài dòng đầu vào đầu tiên không thực hiện lệnh ssh, thì vòng lặp sẽ tiếp tục cho đến khi nó thực sự chạy lệnh SSH.

Trên máy tính xách tay của tôi, nơi tôi đang thử nghiệm, tôi có hai máy ảo Solaris 10 chỉ có khoảng hai hoặc ba bộ dữ liệu mẫu, nhưng điều tương tự đang xảy ra trên các hệ thống SPARC lớn, nơi điều này có nghĩa là sẽ hoạt động và có nhiều bộ dữ liệu.


7
SSH có thể đang đọc từ đầu vào tiêu chuẩn, ăn hết của bạn actionlist. Hãy thử chuyển hướng đầu vào tiêu chuẩn của ssh sang/dev/null
BatchyX

Tôi sẽ cố gắng làm điều đó. Tôi muốn thêm rằng việc đặt ssh vào một trình bao bọc không giúp ích gì ....
Johan

Bạn nói đúng. Làm sao tôi không thấy điều đó!?
Johan

@BatchyX Tôi nghĩ rằng nhận xét của bạn đủ điều kiện là một câu trả lời.
một CVn

Tôi đồng ý tôi muốn "chấp nhận" câu trả lời vì vậy nếu @BatchyX có thể đăng lại nó như vậy tôi sẽ làm như vậy.
Johan

Câu trả lời:


43

SSH có thể đang đọc từ đầu vào tiêu chuẩn, ăn hết danh sách hành động của bạn. Cố gắng chuyển hướng đầu vào tiêu chuẩn của ssh sang / dev / null:

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null

Theo nguyên tắc chung, khi chạy các lệnh có thể can thiệp vào đầu vào tiêu chuẩn theo while readvòng lặp kiểu, tôi muốn bọc toàn bộ thân vòng lặp thành dấu ngoặc:

cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
    echo ${RMT_FILESYSTEM}@${MARKER}
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done

3
Nhân đôi tuyệt vời cho lần đầu tiên việc sử dụng cụ thể của các dấu ngoặc nhọn ... mà tôi có trong 20 năm viết kịch bản chưa bao giờ gặp phải (ít nhất là tôi không thể nhớ được.) Và cho suy luận uuoc. FWIW (và để tự bảo vệ mình) Đôi khi tôi tạo một ngoại lệ và thêm các tuyên bố mèo dư thừa để dễ đọc! Tôi thích diễn đàn này vì tôi đột nhiên học lại những điều mới! Cụ thể tôi thích thêm các chuyển hướng vào đầu dòng như trường hợp này, nhưng trên các diễn đàn dường như gây nhầm lẫn vấn đề, khiến tôi nhận được ít phản hồi hữu ích hơn!
Johan

Tôi đã cố gắng tìm ra sự khác biệt giữa {...} và (...) trang ksh man nói {...} là những từ khóa đặc biệt chỉ được nhận ra khi bắt đầu một dòng lệnh. Nhưng có một sự khác biệt khác ... ( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )khác với niềng răng xoăn. Ý tôi là về mặt đầu ra được sản xuất, không phải về thực tế là nẹp xoăn đóng phải nằm trên một dòng mới ...
Johan

5
Ngoài ra, ssh của OpenSSH có -ntùy chọn làm cho nó (có hiệu quả) mở lại stdin của nó từ / dev / null.
Chris Johnsen

Bất kỳ cách giải quyết để sử dụng sudovới lệnh bên trong vòng lặp?
bonh

Tôi đã từng sử dụng -n từ khi còn nhỏ và đến một lúc nào đó đã mất thói quen .... và bây giờ tôi lại biết tại sao tôi lại làm như vậy, sau một thời gian dành cho việc đào bới ...
Florian Heigl
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.