ข้อผิดพลาดของสคริปต์ทุบตี: คาดว่าจะเป็นจำนวนเต็ม


13

ฉันมีปัญหาค่อนข้างแปลกฉันกำลังเรียกใช้สคริปต์ (Bash) บนเซิร์ฟเวอร์หลายเครื่องและหยุดทำงานกับเซิร์ฟเวอร์ตัวใดตัวหนึ่ง (ใช้งานได้ดีกับเซิร์ฟเวอร์อื่นทั้งหมด)

นี่คือส่วนปัญหาของสคริปต์: (ฉันไม่ได้เขียนด้วยตัวเองเครดิตทั้งหมดไปที่ "รวย") ( http://www.notrainers.org/monitoring-memory-usage-on-linux-with-nagios-) and-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

ข้อความแสดงข้อผิดพลาด:

./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

หากคุณต้องการข้อมูลเพิ่มเติมแจ้งให้เราทราบและฉันจะพยายามจัดส่งให้เร็วที่สุด

ขอบคุณอินพุตทั้งหมด :)

คำตอบ:


5

จากลิงก์ที่คุณระบุฉันเห็นบรรทัดด้านล่าง

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

ตามความคิดเห็นของ @ Graeme ให้เปลี่ยนบรรทัดด้านบนเป็นด้านล่าง

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

ตอนนี้หลังจากเพิ่มบรรทัดข้างบนเราต้องเปลี่ยนผลลัพธ์ของการresultเป็นจำนวนเต็มดังนี้

result1=${result/.*}

ฉันเดาหนึ่งในเครื่องที่เกิดข้อผิดพลาดผลลัพธ์นี้ไม่ใช่จำนวนเต็ม เพียงแปลงผลลัพธ์ของผลลัพธ์เป็นจำนวนเต็มเพื่อให้คุณสามารถจัดการกับกรณีดังกล่าวได้ resultเพิ่มบรรทัดด้านล่างหลังจากที่คุณคำนวณ

result1=${result/.*}

และแทนที่จะresultเปลี่ยนชื่อตัวแปรresult1ภายในifวงและข้อผิดพลาดจะไม่เกิดขึ้น

ฉันสงสัยว่าcut -c -2คุณลักษณะของข้อผิดพลาดส่วนใหญ่เนื่องจากมีการตัดอักขระ 2 ตัวแรกเท่านั้น ถ้าผลลัพธ์มีอักขระเพียงตัวเดียว สมมติว่าถ้าผลลัพธ์คือ1.23456การตัดด้านบนจะส่งผลให้1.เป็นค่าresultที่เห็นได้ชัดว่าเป็นสาเหตุของinteger expectedข้อผิดพลาด

เหตุผลที่มันทำงานได้ดีในเซิร์ฟเวอร์ที่เหลืออยู่เพราะมันไม่ได้พบกับกรณีที่resultตัวแปรมีเพียงตัวเลขหลักเดียว มีความเป็นไปได้สูงที่จะล้มเหลวในเซิร์ฟเวอร์ที่เหลือเช่นกันหากผลลัพธ์เป็นตัวแปรหลักเดียว (อย่างที่ฉันพูดถึงในตัวอย่างด้านบน)


${result%%.*}จะเป็นการขยายที่ถูกต้องเพื่อลบจุดทศนิยมที่นี่ แต่โปรดทราบว่าการที่cut -c -2จะทำให้เกิดปัญหากับตัวเลข 100 หรือมากกว่านั้นจึงปลอดภัยกว่าที่จะปล่อยให้มันสมบูรณ์
แกรม

@ Graeme ฉันพลาดไป ฉันควรจะทำให้มีการเปลี่ยนแปลงในสายที่ :)
Ramesh

6

ด้วยรูปลักษณ์ของสิ่งต่าง ๆresultตัวแปรของคุณจะมีเครื่องหมาย.อยู่หลังจากตัวเลขทำให้ bash ไม่รู้จักเช่นนั้น คุณสามารถทำซ้ำข้อผิดพลาดโดยทำ:

[ 7. -gt 1 ]

หากคุณเพิ่มสคริปต์ลงในคำถามของคุณ | ฉันสามารถแนะนำได้ว่าสิ่งนี้อาจมาจากไหน

ปรับปรุง

ดูสคริปต์เต็มฉันจะแทนที่บรรทัด:

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

ด้วย:

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

ตั้งแต่usedและtotalเป็นจำนวนเต็มและbashคำนวณเลขจำนวนเต็มถึงแม้ว่าการเลื่อนของการคูณจะเท่ากับ 100 ถึงจุดเริ่มต้น หรือถ้าคุณต้องการให้แน่ใจว่าการปัดเศษที่ถูกต้อง ('การหารจำนวนเต็ม' ในการคำนวณจะปัดเศษลงอย่างมีประสิทธิภาพเสมอ):

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

resultนี้จะให้แน่ใจว่าจะไม่มีจุดต่อท้ายใน การใช้วิธีการcutนี้ไม่ใช่ความคิดที่ดีมากเนื่องจากใช้ได้กับผลลัพธ์ในช่วง 10-99 เท่านั้น มันจะล้มเหลวresultจาก 0-9 (เช่นในกรณีของคุณ) และหมายเลขที่สูงกว่า 99

อัปเดต 2

จากความคิดเห็นของ @ Stephane ด้านล่างคุณจะดีกว่าที่จะปัดเศษเมื่อเปรียบเทียบกับเกณฑ์ พิจารณานี้มีอีกข้อผิดพลาดเล็ก ๆ พร้อมด้วยข้อมูลในคำถาม - สังเกตเห็นความไม่สอดคล้องกันระหว่างรถที่ใช้สำหรับการและwarn_level critical_levelการเปรียบเทียบwarn_levelนั้นถูกต้อง แต่critical_levelใช้-le(น้อยกว่าหรือเท่ากับ) แทนที่จะเป็น-lt(น้อยกว่า) พิจารณาว่าเมื่อใดที่resultมีขนาดใหญ่กว่าเล็กน้อยcritical_level- มันจะถูกปัดเศษลงเป็นcritical_levelและไม่เรียกใช้คำเตือนที่สำคัญถึงแม้ว่ามันจะควร (และหากใช้-ltการเปรียบเทียบ)

อาจไม่เป็นปัญหามากนัก แต่นี่คือรหัสที่แก้ไข:

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

การ-geทดสอบซ้ำซ้อนเนื่องจากกรณีเหล่านี้มีนัยในการเข้าถึงelif/ elseดังนั้นจึงถูกลบออก


2
อย่างไรก็ตามในการตรวจสอบกับเกณฑ์ที่คุณไม่ต้องการที่จะรอบขึ้น 49.6 ควรจะยังคงตกลงถ้าเกณฑ์การเตือนคือ 50 ดังนั้นresult=$(( 100 * $used / $total ))ควรจะใช้ได้
Stéphane Chazelas

0

ดังนั้นฉันไม่รู้วิธีการใช้งานawkเป็นอย่างดีเลย แต่ฉันรู้ว่าสิ่งที่เกิดขึ้นในสคริปต์ที่คุณเชื่อมโยงนั้นเป็นเรื่องไร้สาระมากมายและสิ่งต่อไปนี้ควรจะได้ผล ฉันขอโทษฉันไม่สามารถเขียนสิ่งนี้ออกมาได้อย่างสมบูรณ์แบบ แต่เนื่องจากคุณโทรมาแล้วawkสองครั้งดูเหมือนคุณควรใช้สิ่งนี้

_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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.