Lỗi script Bash: biểu thức số nguyên dự kiến


13

Tôi đang gặp một vấn đề khá kỳ lạ, tôi đang chạy một tập lệnh (Bash) trên nhiều máy chủ và nó đã ngừng hoạt động trên một trong các máy chủ (hoạt động hoàn toàn tốt trên tất cả các máy chủ khác).

Đây là phần vấn đề của kịch bản: (Tôi không tự viết, tất cả các khoản tín dụng đều chuyển đến "Giàu có") ( http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios- và-nrpe / )

    if [ "$result" -lt "$warn_level" ]; then     #Line 56
    echo "Memory OK. $result% used."
    exit 0;
elif [ "$result" -ge "$warn_level" ] && [ "$result" -le "$critical_level" ]; then  #Line 59
    echo "Memory WARNING. $result% used."
    exit 1;
elif [ "$result" -gt "$critical_level" ]; then   #Line 62
    echo "Memory CRITICAL. $result% used."
    exit 2;
fi

Thông báo lỗi hoàn chỉnh:

./check_memory.sh: Line 56: [: 7.: integer expression expected

./check_memory.sh: Line 59: [: 7.: integer expression expected

./check_memory.sh: Line 62: [: 7.: integer expression expected

Nếu bạn cần thêm thông tin, hãy cho tôi biết và tôi sẽ cố gắng cung cấp nó nhanh nhất có thể.

Đánh giá cao tất cả các đầu vào :)

Câu trả lời:


5

Từ liên kết bạn cung cấp, tôi thấy dòng dưới đây.

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)

Theo nhận xét của @ Graeme, hãy thay đổi dòng trên thành bên dưới.

result=$(echo "$used / $total * 100" |bc -l)

Bây giờ, sau khi thêm dòng trên, chúng ta phải thay đổi đầu ra của resultsố nguyên như bên dưới.

result1=${result/.*}

Tôi đoán ở một trong những máy xảy ra lỗi, đầu ra này không phải là số nguyên. Chỉ cần chuyển đổi đầu ra của kết quả thành số nguyên để bạn có thể xử lý các trường hợp như vậy. Thêm dòng dưới đây sau khi bạn tính toán result.

result1=${result/.*}

Và thay vì thay resultđổi tên biến như result1bên trong các ifvòng lặp, và lỗi sẽ không xảy ra.

Tôi nghi ngờ, các cut -c -2thuộc tính cho lỗi chủ yếu là vì nó chỉ cắt 2 ký tự đầu tiên. Nếu kết quả chỉ có một ký tự thì sao? Giả sử nếu kết quả là 1.23456, việc cắt ở trên sẽ dẫn đến 1.giá trị resultmà rõ ràng là nguyên nhân gây ra integer expectedlỗi.

Lý do nó hoạt động tốt trong các máy chủ còn lại là vì nó không gặp phải trường hợp resultbiến chỉ có một chữ số. Nó cũng có khả năng thất bại ở các máy chủ còn lại nếu kết quả là một biến số có một chữ số (một cái gì đó giống như tôi đã đề cập trong ví dụ trên).


${result%%.*}sẽ là sự mở rộng chính xác để loại bỏ dấu thập phân ở đây. Nhưng lưu ý rằng điều cut -c -2này cũng sẽ gây ra các vấn đề với số lượng từ 100 trở lên, vì vậy sẽ an toàn hơn khi bỏ nó hoàn toàn.
Graeme

@Graeme, tôi đã bỏ lỡ điều đó. Tôi nên đã thực hiện các thay đổi trong dòng đó :)
Ramesh

6

Nhìn vào mọi thứ, resultbiến của bạn có một số .trong đó sau khi làm cho bash không nhận ra nó như vậy. Bạn có thể tái tạo lỗi bằng cách thực hiện:

[ 7. -gt 1 ]

Nếu bạn thêm nhiều tập lệnh vào câu hỏi của mình, tôi có thể đề xuất nơi này có thể đến từ đâu.

Cập nhật

Nhìn vào kịch bản đầy đủ, tôi sẽ chỉ thay thế dòng:

result=$(echo "$used / $total * 100" |bc -l|cut -c -2)

Với:

result=$(( 100 * used / total ))

usedtotallà số nguyên và bashsố học số nguyên, mặc dù lưu ý sự dịch chuyển của phép nhân là 100 so với đầu. Hoặc nếu bạn muốn đảm bảo làm tròn chính xác ('phép chia số nguyên' trong điện toán luôn làm tròn hiệu quả):

result=$( printf '%.0f' $(echo "$used / $total * 100" | bc -l) )

Điều này sẽ đảm bảo rằng không có dấu chấm trong result. Cách tiếp cận sử dụng cutkhông phải là một ý tưởng hay vì nó chỉ có giá trị cho kết quả trong phạm vi 10-99. Nó sẽ thất bại trong khoảng resulttừ 0-9 (như trong trường hợp của bạn) và cả những con số trên 99.

Cập nhật 2

Từ nhận xét của @ Stephane bên dưới , bạn nên làm tròn xuống khi so sánh với các ngưỡng. Xem xét điều này, có một lỗi nhỏ khác với đoạn trích trong câu hỏi - lưu ý sự không thống nhất giữa các so sánh được sử dụng cho warn_levelcritical_level. Các so sánh cho warn_levellà chính xác, nhưng critical_levelsử dụng -le(ít hơn hoặc bằng) thay vì -lt(chỉ ít hơn). Xem xét khi nào resultlớn hơn một chút critical_level- nó sẽ được làm tròn xuống critical_levelvà không kích hoạt cảnh báo quan trọng ngay cả khi nó nên (và sẽ -ltđược sử dụng nếu so sánh được sử dụng).

Có lẽ không có nhiều vấn đề, nhưng đây là mã được sửa:

if [ "$result" -lt "$warn_level" ]; then
  echo "Memory OK. $result% used."
  exit 0;
elif [ "$result" -lt "$critical_level" ]; then
  echo "Memory WARNING. $result% used."
  exit 1;
else
  echo "Memory CRITICAL. $result% used."
  exit 2;
fi

Các -gexét nghiệm cũng không cần thiết vì những trường hợp này được ngụ ý là đạt đến elif/ else, vì vậy đã được gỡ bỏ.


2
Tuy nhiên, để kiểm tra ngưỡng, bạn không muốn làm tròn số . 49.6 vẫn sẽ ổn nếu ngưỡng cảnh báo là 50. Vì vậy, result=$(( 100 * $used / $total ))sẽ ổn thôi.
Stéphane Chazelas

0

Vì vậy, tôi không biết làm thế nào để sử dụng awkrất tốt. Nhưng tôi biết rằng những gì đang diễn ra trong kịch bản mà bạn liên kết là rất nhiều điều vô nghĩa và những thứ như sau sẽ hoạt động. Tôi xin lỗi tôi không thể viết này ra hoàn toàn tốt, nhưng kể từ khi bạn đã gọi awk- hai lần có vẻ như - bạn nên sử dụng một cái gì đó như thế này.

_chkmem() { return $( 
    free -m | grep "buffers/cache"
        awk '{ 
        percent = ( $3 / ( $3 + $4 ) ) * 100     
        warn = '"${warnlevel?No warning level specified!}"' < percent ? WARNING : OK
        crit = '"${critical?No critical level specified!}"' < percent ? CRITICAL : $warn
        print "Mem $crit : $percent% used"
        if ( $crit != OK ) exit 1
    }')
}

_chkmem || exit 1
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.