Đặt subshell trong nền so với đặt lệnh trong nền


7

Tôi có hai tập lệnh bash cố gắng kiểm tra máy chủ đang hoạt động:

Kịch bản 1:

#!/bin/bash 
for ip in {1..254}; do
    ping -c 1 192.168.1.$ip | grep "bytes from" | cut -d" " -f 4 | cut -d ":" -f 1 &
done

Kịch bản 2:

#!/bin/bash 
for ip in {1..254}; do
    host=192.168.1.$ip
    (ping -c 1 $host > /dev/null 
    if [ "$?" = 0 ]
    then 
        echo $host
    fi) &
done

Khi tôi đang kiểm tra một phạm vi lớn, tôi muốn xử lý song song từng lệnh ping. Tuy nhiên, tập lệnh thứ hai của tôi dường như không thử lại các lần thử thất bại do giới hạn tài nguyên. Điều này dẫn đến tập lệnh thứ hai có kết quả không nhất quán trong khi tập lệnh đầu tiên của tôi cho kết quả không đổi mặc dù cả hai lần đều không thực hiện được. Ai đó có thể giải thích điều này với tôi? Ngoài ra có cách nào để thử lại dĩa thất bại?


apt-get install fping: - / (hoặc nmap -sP)
derobert

@derobert Tôi biết nmap hoạt động. Tôi chỉ muốn thử thực hiện quét ping cho thí nghiệm này.
MykelXIII

1
Chà, cách đúng đắn để làm điều này là theo dõi xem có bao nhiêu tiến trình con bạn đã chạy và giữ một số lành mạnh. Khác với việc sử dụng các tiện ích (ví dụ parallel:) để làm điều đó cho bạn, bạn phải theo dõi những đứa trẻ mà bạn đã sinh ra (bạn lấy pid từ đó $!, đợi chúng thoát ra (và tìm ra mã thoát của chúng) từ wait, v.v ... Cá nhân, tôi chuyển sang Perl vào thời điểm này ...
derobert

Câu trả lời:


4

Đã có một câu trả lời đưa ra một đoạn mã được cải tiến cho nhiệm vụ mà các câu hỏi của người đăng ban đầu có liên quan đến, trong khi nó có thể chưa có câu trả lời trực tiếp hơn cho câu hỏi.

Câu hỏi là về sự khác biệt của

  • A) Tạo nền cho "lệnh" trực tiếp, vs.
  • B) Đặt một lớp con vào nền (nghĩa là với một tác vụ tương tự)

Hãy kiểm tra những khác biệt khi chạy 2 bài kiểm tra

# A) Backgrounding a command directly
sleep 2 & ps

đầu ra

[1] 4228
  PID TTY          TIME CMD
 4216 pts/8    00:00:00 sh
 4228 pts/8    00:00:00 sleep

trong khi

# A) backgrounding a subhell (with similar tas)
( sleep 2; ) & ps

xuất ra một cái gì đó như:

[1] 3252
  PID TTY          TIME CMD
 3216 pts/8    00:00:00 sh
 3252 pts/8    00:00:00 sh
 3253 pts/8    00:00:00 ps
 3254 pts/8    00:00:00 sleep

** Kết quả kiểm tra:**

Trong thử nghiệm này (chỉ chạy a sleep 2) phiên bản subshell thực sự khác nhau, vì nó sẽ sử dụng 2 tiến trình con (tức là hai fork()/ exechoạt động và PID) và do đó nhiều hơn so với nền tảng trực tiếp của lệnh.

Trong script 1các câu hỏi tuy nhiên lệnh không phải là một đơn sleep 2snhưng thay vào đó là một pipetrong 4 lệnh, mà nếu chúng ta thử nghiệm bên trong trường hợp thêm

  • C) Tạo nền cho một đường ống với 4 lệnh
# C) Backgrounding a pipe with 4 commands
sleep 2s | sleep 2s | sleep 2s | sleep 2s & ps

mang lại điều này

[2] 3265
  PID TTY          TIME CMD
 3216 pts/8    00:00:00 bash
 3262 pts/8    00:00:00 sleep
 3263 pts/8    00:00:00 sleep
 3264 pts/8    00:00:00 sleep
 3265 pts/8    00:00:00 sleep
 3266 pts/8    00:00:00 ps

và cho thấy rằng thực sự script 1sẽ là một chủng cao hơn nhiều về mặt PIDsfork()s.

Theo ước tính sơ bộ, tập lệnh sẽ sử dụng khoảng 254 * 4 ~ = 1000 PID và do đó thậm chí còn nhiều hơn so script 2với với 254 * 2 ~ = 500 PID. Bất kỳ vấn đề nào xảy ra do sự suy giảm của PID đều có vẻ khó xảy ra vì hầu hết các hộp Linux

$ cat /proc/sys/kernel/pid_max
32768

mang đến cho bạn 32x lần PID cần thiết ngay cả đối với trường hợp script 1và các quá trình / chương trình liên quan (ví dụ sed, ping, vv) cũng dường như khó có thể gây ra những kết quả hay thay đổi.

Như người dùng @derobert đã đề cập, vấn đề thực sự đằng sau sự scriptsthất bại là việc thiếu waitlệnh, có nghĩa là sau khi làm nền các lệnh trong vòng lặp kết thúc tập lệnh và do đó trình bao khiến tất cả các tiến trình con bị chấm dứt.


- đã xóa nội dung--
MykelXIII

@MykelXIII :). tò mò: ý của bạn chính xác hơn là "kịch bản cạn kiệt tài nguyên"? Làm thế nào để bạn đo / kiểm tra đó? Một tài nguyên có thể là việc sử dụng một PID (không có id quá trình không bị ảnh hưởng), bộ nhớ, thời gian chờ đợi, ý của bạn là gì?
nhân

Xin lỗi, tôi đã sai lầm khi hiểu câu trả lời của bạn. Nó có ý nghĩa bây giờ. Kịch bản đầu tiên thực sự sử dụng nhiều tài nguyên hơn. Mặc dù vậy, tôi tò mò, nếu kịch bản đầu tiên của tôi không chờ đợi mà vẫn mang lại kết quả nhất quán, điều đó có nghĩa là do quá trình con hoàn thành nhanh hơn quy trình cha mẹ?
MykelXIII

@MykelXIII Tôi đoán là thế này: Trong cả hai tập lệnh, vì không có gì waitđể đảm bảo không giết chết sớm các quy trình được sinh ra, rõ ràng có một cuộc đua ..... Kết thúc là sau khi tập lệnh đi qua vòng lặp for ... script 1mang lại kết quả tốt hơn, bởi vì (a) mỗi script1vòng lặp sẽ mất nhiều thời gian hơn ( script1: bắt đầu đường ống với 4 tiến trình VS script2: bắt đầu một chuỗi con) cho đến khi công cụ được đưa vào nền. Ngoài ra trong (b) script2ping được điều hành chỉ sau khi subshell đã fork()và do đó chậm nhất là trong script1và phải mất một if , [echolệnh để ....
humanityANDpeace

... để kết thúc, đó là thời gian script2không cung cấp khi vòng lặp kết thúc (xem (a) một cách nhanh chóng)
nhân

2

Điều này sẽ làm những gì bạn đang mong đợi:

#!/bin/bash
function_ping(){
    if ping -c 1 -w 5 $1 &>/dev/null; then 
        echo "UP: $1"
    else
        echo "DOWN $1" 
    fi
}
for ip in {1..254}; do
        function_ping 192.168.1.$ip &  
done
wait 

Lưu nó như là song song, và thực hiện nó.

Nó giúp bạn? Nó có thể được chuyển đổi thành một chức năng lớn, cũng có thể được sử dụng trong một vòng lặp nhanh để bạn có thể sử dụng lập trình trí tưởng tượng của mình với nó.

Lưu ý: Bạn phải sử dụng bash.


Nó hoạt động, tuy nhiên tôi đã xóa & trong câu lệnh ping -c 1 -w 5 $ 1 &. Bạn có thể giải thích tại sao có 2 &? Một trong lời gọi hàm và một trong lệnh gọi ping? Ngoài ra tôi có thể hỏi tại sao các subshells thất bại trong khi đặt các chức năng cho nền không?
MykelXIII

Câu lệnh & in ping đang giúp chuyển hướng đầu ra ping thành / dev / null, điều đó có nghĩa là tất cả đầu ra tiêu chuẩn của lệnh cần phải được chuyển hướng, vì vậy không có gì liên quan đến "&" khác sẽ chạy chức năng trên nền nhưng với ký tự chuyển hướng (>), điều này hoạt động khi ký tự này '&' dựa vào ký tự '>'. Kịch bản của bạn cũng đang hoạt động rất tốt, bạn cần chờ đợi sau khi hoàn thành câu lệnh 'xong' hoặc tập lệnh sẽ không chờ các quá trình nền kết thúc. Đảm bảo rằng bạn sẽ chạy nó từ bash chứ không phải từ sh như 'sh thescript'.
Luciano Andress Martini

Các thông tin quan trọng của câu trả lời là gì? Có phải nó được sử dụng waitnhư để chờ kết thúc các tiến trình con được làm nền, đúng không? Hay là điểm quan trọng của việc sử dụng hàm shell ? Như bài viết trong bình luận của @LucianoAndressMartini có vẻ như là vậy wait, nhưng điều này không thực sự trở nên rõ ràng từ câu trả lời.
nhân

Đó là một câu hỏi cũ, nhưng bạn là con người đúng đắn, tôi đã làm rõ câu hỏi trên bình luận, bởi vì tôi nhận ra rằng kịch bản gốc đang hoạt động, sau khi viết câu trả lời.
Luciano Andress Martini
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.