Các for
vòng lặp là tốt ở đây. Nhưng lưu ý rằng điều này là do tệp chứa tên máy, không chứa bất kỳ ký tự khoảng trắng hoặc ký tự toàn cầu nào. for x in $(cat file); do …
không hoạt động để lặp lại các dòng file
nói chung, vì trước tiên, shell sẽ tách đầu ra khỏi lệnh ở cat file
bất cứ nơi nào có khoảng trắng, và sau đó coi mỗi từ là một mẫu hình cầu nên \[?*
được mở rộng thêm. Bạn có thể làm cho for x in $(cat file)
an toàn nếu bạn làm việc trên nó:
set -f
IFS='
'
for x in $(cat file); do …
Đọc liên quan: Vòng qua các tập tin có khoảng trắng trong tên? ; Làm thế nào tôi có thể đọc từng dòng từ một biến trong bash? ; Tại sao được while IFS= read
sử dụng thường xuyên, thay vì IFS=; while read..
? Lưu ý rằng khi sử dụng while read
, cú pháp an toàn để đọc các dòng là while IFS= read -r line; do …
.
Bây giờ hãy chuyển sang những gì sai với while read
nỗ lực của bạn . Chuyển hướng từ tệp danh sách máy chủ áp dụng cho toàn bộ vòng lặp. Vì vậy, khi ssh
chạy, đầu vào tiêu chuẩn của nó đến từ tập tin đó. Máy khách ssh không thể biết khi nào ứng dụng từ xa có thể muốn đọc từ đầu vào tiêu chuẩn của nó. Vì vậy, ngay khi máy khách ssh nhận thấy một số đầu vào, nó sẽ gửi đầu vào đó đến phía từ xa. Sau đó, máy chủ ssh đã sẵn sàng cung cấp đầu vào đó cho lệnh từ xa, nếu nó muốn. Trong trường hợp của bạn, lệnh từ xa không bao giờ đọc bất kỳ đầu vào nào, vì vậy dữ liệu cuối cùng bị loại bỏ, nhưng phía khách hàng không biết gì về điều đó. Nỗ lực của bạn với echo
công việc vì echo
không bao giờ đọc bất kỳ đầu vào nào, nó chỉ để lại đầu vào tiêu chuẩn của nó.
Có một vài cách bạn có thể tránh điều này. Bạn có thể yêu cầu ssh không đọc từ đầu vào tiêu chuẩn, với -n
tùy chọn.
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
Các -n
tùy chọn trong thực tế nói ssh
để chuyển hướng đầu vào của nó từ /dev/null
. Bạn có thể làm điều đó ở cấp độ shell và nó sẽ hoạt động với bất kỳ lệnh nào.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Một phương pháp hấp dẫn để tránh đầu vào của ssh đến từ tệp là đặt chuyển hướng vào read
lệnh : while read server </home/kenny/list_of_servers.txt; do …
. Điều này sẽ không hoạt động, bởi vì nó làm cho tệp được mở lại mỗi lần read
lệnh được thực thi (vì vậy nó sẽ đọc dòng đầu tiên của tệp nhiều lần). Chuyển hướng cần phải ở trên toàn bộ vòng lặp while để tệp được mở một lần trong suốt thời gian của vòng lặp.
Giải pháp chung là cung cấp đầu vào cho vòng lặp trên một bộ mô tả tệp khác với đầu vào tiêu chuẩn. Shell có cấu trúc để nhập và xuất phà từ số mô tả này sang số khác. Ở đây, chúng tôi mở tệp trên bộ mô tả tệp 3 và chuyển hướng read
đầu vào tiêu chuẩn của lệnh từ bộ mô tả tệp 3. Máy khách ssh bỏ qua các bộ mô tả không chuẩn, vì vậy tất cả đều ổn.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
Trong bash, read
lệnh có một tùy chọn cụ thể để đọc từ một bộ mô tả tệp khác, vì vậy bạn có thể viết read -u3 server
.
Đọc liên quan: Mô tả tập tin & kịch bản shell ; Khi nào bạn sẽ sử dụng một mô tả tập tin bổ sung?