chờ mạng trong tập lệnh bash


9

Tôi đang chạy một tập lệnh dựa trên mạng đang hoạt động và chia sẻ mạng được gắn kết. Kịch bản chạy khi đăng nhập (xảy ra tự động sau khi khởi động). Vấn đề là vào thời điểm tập lệnh chạy, tôi thường chưa có địa chỉ IP (DHCP). Hiện tại tôi chỉ ngủ kịch bản trong 15 giây, nhưng tôi hoàn toàn không thích cách tiếp cận này, vì tôi muốn có thể nói với người dùng nếu có gì đó không đúng.

Kế hoạch của tôi là gì, là vòng lặp trong khi tôi chưa có địa chỉ IP và tiếp tục khi tôi làm. Điều quan trọng, nó phải hết thời gian sau một thời gian. Những gì tôi đã đưa ra là if [ ifconfig | grep "192.168.100" ];nhưng những gì xảy ra là grepconsume ];và không thích nó. Sau đó, bash cũng buồn bã, bởi vì nó không thể tìm thấy ];grep nào đã ăn. Và sau đó tôi thậm chí còn không thực hiện được thời gian chờ.

Ai đó đề nghị giữ một biến và ngủ, giả sử, một giây trong mỗi lần lặp và tăng biến này mỗi lần. Đây là kịch bản hoàn chỉnh (không hoạt động) của tôi (Tôi khá mới đối với kịch bản bash):

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
    echo "no nework"
    if "$x" -gt 200; then
        #Time out here
        exit 1
    x=$((x+1))
    sleep .1
    fi
done

#continue with rest of script...

Bất kỳ con trỏ đi đúng hướng sẽ được đánh giá rất cao!


1
Nếu init của bạn là systemd, hãy viết một tệp dịch vụ chờ network-online.target...
jasonwryan

không cần chuyển hướng grepđầu ra /dev/null. Sử dụng -qtùy chọn thay thế. Và tôi cũng không nên grepping ifconfig là một ý tưởng tốt. Tại sao không sử dụng pingthay thế?
vội vàng

pingcó thể thất bại tùy thuộc vào mạng trong câu hỏi. Tốt hơn hết là chỉ kiểm tra cấu hình đang chạy của hệ thống.
Bratchley

Câu trả lời:


8

Cú pháp Shell

Bạn dường như bị nhầm lẫn về điều kiện trong các kịch bản shell. Mỗi lệnh shell có trạng thái thoát, là một số nguyên nằm trong khoảng từ 0 đến 255, với 0 có nghĩa là thành công và bất kỳ giá trị nào khác có nghĩa là thất bại. Các câu lệnh như ifwhilemong đợi các toán hạng boolean kiểm tra trạng thái thoát của lệnh và coi 0 (thành công) là đúng và bất kỳ giá trị nào khác (thất bại) là sai.

Ví dụ, greplệnh trả về 0 nếu mẫu được tìm thấy và 1 nếu mẫu không được tìm thấy. Vì thế

while ifconfig | grep "192.168.100." > /dev/null; do 

lặp lại vòng lặp miễn là mẫu 192.168.100.được tìm thấy trong đầu ra của ifconfig. Lưu ý rằng mẫu 192.168.100.khớp với các chuỗi như 192x168 1007, bởi vì .trong biểu thức chính quy khớp với bất kỳ ký tự nào; để tìm kiếm một chuỗi ký tự, chuyển tùy chọn -Fđến grep. Để đảo ngược điều kiện, đặt !ở phía trước.

while ! ifconfig | grep -F "192.168.100." > /dev/null; do 

Hơn nữa trong tập lệnh, bạn muốn so sánh giá trị của một biến với một số. Bạn sử dụng -gttoán tử, là một phần của cú pháp của các biểu thức điều kiện được hiểu bởi testlệnh. Các testlệnh trả về 0 nếu biểu thức điều kiện là đúng và 1 nếu biểu thức điều kiện là sai.

if test "$x" -gt 200; then

Nó là thông lệ để sử dụng tên thay thế [cho testlệnh. Tên này hy vọng lệnh kết thúc với tham số ]. Hai cách viết lệnh này hoàn toàn tương đương.

if [ "$x" -gt 200 ]; then

Bash cũng cung cấp một cách thứ ba để viết lệnh này, với cú pháp đặc biệt [[ … ]]. Cú pháp đặc biệt này có thể hỗ trợ nhiều toán tử hơn [, vì [là một lệnh thông thường tuân theo các quy tắc phân tích cú pháp thông thường, trong khi [[ … ]]là một phần của cú pháp shell.

Một lần nữa, hãy nhớ rằng [là cho biểu thức điều kiện , đó là một cú pháp với những hoạt động như -n, -gt, ... [không có nghĩa là “giá trị boolean”: (? Trạng thái thoát = 0) bất kỳ lệnh có giá trị boolean.

Phát hiện mạng đang hoạt động

Cách của bạn để phát hiện ra rằng mạng không hoạt động. Cụ thể, lưu ý rằng tập lệnh của bạn sẽ được kích hoạt ngay khi bất kỳ giao diện mạng nào có được địa chỉ IP trong phạm vi được chỉ định. Đặc biệt, rất có thể DNS sẽ không hoạt động vào thời điểm đó, chứ đừng nói đến bất kỳ chia sẻ mạng nào được gắn kết.

Bạn có thực sự cần phải chạy các lệnh này khi ai đó đăng nhập không? Dễ dàng hơn để tạo một lệnh chạy tự động khi mạng được đưa lên. Cách để làm điều đó phụ thuộc vào phân phối của bạn và liệu bạn có sử dụng NetworkManager hay không.

Nếu bạn cần chạy các lệnh này như một phần của tập lệnh đăng nhập, thì hãy kiểm tra tài nguyên mà bạn thực sự cần chứ không phải cho sự hiện diện của địa chỉ IP. Ví dụ: nếu bạn muốn kiểm tra xem có /net/somenode/somedirđược gắn hay không, hãy sử dụng

while ! grep -q /net/somenode/somedir </proc/mounts; do
  sleep 1
done

Nếu bạn có người mới bắt đầu hoặc systemd

sau đó bạn có thể sử dụng nó Ví dụ: với Upstart , đánh dấu công việc của bạn là start on net-device-up eth0(thay thế eth0bằng tên của giao diện cung cấp kết nối mạng mong muốn). Với Systemd, xem Nguyên nhân một tập lệnh để thực thi sau khi mạng đã bắt đầu?


Tôi đoán là /net/nên /proc/net?
sebix

@sebix Không, tại sao vậy? Tôi không nói về cấu hình mạng của Linux. Tôi đang đưa ra một ví dụ về điểm gắn kết cho hệ thống tệp từ xa, /netlà một vị trí phổ biến cho các điểm gắn kết đó.
Gilles 'SO- đừng trở nên xấu xa'

Ok, vì vậy bạn yêu cầu một ổ đĩa mạng gắn kết. Liệu một giải pháp chung chung hơn cũng tồn tại?
sebix

@sebix Một giải pháp để làm gì? Yêu cầu ổ đĩa mạng được gắn kết là một ví dụ về mục tiêu, không phải là ví dụ về giải pháp.
Gilles 'SO- đừng trở nên xấu xa'

1

Chỉ cần đếm đầu ra của ip add showVí dụ:

root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
    inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
    inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2

Sau đó, bạn có thể chỉ cần phân nhánh trên số lượng dòng trả về là phù hợp. Có lẽ bạn chỉ cần kiểm tra xem nó có bằng không không, và nếu vậy, hãy ngủ và lặp lại vòng lặp.

Mã chưa được kiểm tra để minh họa:

while [ 1 ]; do

  if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
     break
  fi

  sleep 1

done

1

Ping sẽ trả về 0 phản hồi nếu ít nhất một lần thử thành công. Bạn có thể cân nhắc ping máy chủ mà bạn đang kết nối cho đến khi thành công.

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.