ทำไมฉันถึงได้รับสถานะการออกที่แตกต่างกันสำหรับ ps | grep ในสคริปต์หรือไม่


11

ฉันใช้สคริปต์ด้านล่าง:

#!/bin/bash

ps ax  | grep -q [v]arnish
if [ $? -eq 0 ];then
        echo varnish is running...
        exit 0
else
        echo "Critical : varnish is not running "
        exit 2
fi

ผลลัพธ์เป็นเหมือน ::

[root@server ~]# sh -x check_varnish_pro.sh
+ ps ax
+ grep -q '[v]arnish'
+ '[' 0 -eq 0 ']'
+ echo varnish is running...
varnish is running...
+ exit 0

เมื่อฉันทำงานเหมือนกันในบรรทัดคำสั่งฉันได้รับสถานะการออกเป็น 1:

[root@server ~]# ps ax  | grep -q [v]arnish; echo $?
1

กรณีเป็นเช่นวานิชไม่ได้ติดตั้งในเซิร์ฟเวอร์ สคริปต์นี้ทำงานได้ดีในเซิร์ฟเวอร์ที่ติดตั้งวานิช

ทำไมสถานะการออกที่แตกต่างกันเมื่อทำงานโดยใช้สคริปต์และบรรทัดคำสั่ง จะปรับปรุงสคริปต์นี้อย่างไร?


ใช้ระบบการควบคุมกระบวนการจริงไม่ใช่แฮ็คชนิดนี้ ระบบปฏิบัติการของคุณจะมีวิธีการในตัวเพื่อให้แน่ใจว่า daemons ของคุณที่คุณต้องการจะถูกรีสตาร์ทโดยอัตโนมัติเมื่อเกิดความล้มเหลวไม่ว่าจะเป็นคนธรรมดา daemontools, systemd, launchd หรือหนึ่งในหลาย ๆ ทางเลือกอื่น ๆ พวกเขาทั้งหมดจะแข็งแกร่งและมีความสามารถมากกว่าแฮกเกอร์รีดแบบนี้
Charles Duffy

คำตอบ:


10

เมื่อคุณเรียกใช้สคริปต์ชื่อcheck_varnish_pro.shการทดสอบ

ps ax  | grep -q [v]arnish

สำเร็จเพราะมีสคริปต์ชื่อcheck_วานิช_proทำงานอยู่


14

โดยทั่วไปเป็นความคิดที่ดีที่จะลองใช้วิธีที่ง่าย ๆpsและgrepลองพิจารณาว่ากระบวนการที่กำหนดกำลังทำงานอยู่หรือไม่

คุณจะดีกว่ามากในการใช้pgrepสิ่งนี้:

if pgrep "varnish" >/dev/null; then
  echo "Varnish in running"
else
  echo "Varnish is not running"
fi

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

การติดตั้งpgrepยังช่วยให้คุณเข้าถึงpkillซึ่งอนุญาตให้คุณส่งสัญญาณกระบวนการตามชื่อของพวกเขา

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

บน Linux คุณมีsystemctl( systemctl is-active --quiet varnishจะคืนค่า 0 ถ้ามันทำงานอยู่ 3 อย่าง) บน OpenBSD ที่คุณมีrcctlเป็นต้น


ตอนนี้ถึงสคริปต์ของคุณ:

ps axในสคริปต์ของคุณคุณแยกขาออกจาก ผลลัพธ์นี้จะมีชื่อของสคริปต์เองซึ่งเห็นได้ชัดว่ามีสตริงcheck_varnish_pro.sh varnishสิ่งนี้จะทำให้คุณคิดบวก คุณจะเห็นสิ่งนี้ถ้าคุณเรียกใช้โดยไม่มีการ-qตั้งค่าสถานะสำหรับgrepในขณะทดสอบ

#!/bin/bash
ps ax | grep '[v]arnish'

ใช้มัน

$ ./check_varnish_pro.sh
31004 p1  SN+     0:00.04 /bin/bash ./check_varnish_pro.sh

ปัญหาอื่นคือแม้ว่าคุณพยายาม "ซ่อน" grepกระบวนการจากการตรวจพบด้วยgrepตัวเองโดยใช้[v]ในรูปแบบ วิธีการนั้นจะล้มเหลวหากคุณเรียกใช้สคริปต์หรือบรรทัดคำสั่งในไดเรกทอรีที่มีชื่อไฟล์หรือไดเรกทอรีvarnishอยู่ (ในกรณีนี้คุณจะได้รับผลบวกปลอมอีกครั้ง) นี่เป็นเพราะรูปแบบไม่ได้ถูกยกมาแล้วและเชลล์จะแสดงชื่อไฟล์ให้กลมกลืนไปกับมัน

ดู:

bash-4.4$ set -x
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep '[v]arnish'
bash-4.4$ touch varnish
+ touch varnish
bash-4.4$ ps ax | grep [v]arnish
+ ps ax
+ grep varnish
91829 p2  SN+p    0:00.02 grep varnish

การปรากฏตัวของไฟล์varnishจะทำให้เปลือกแทนที่[v]arnishด้วยชื่อไฟล์varnishและคุณจะได้รับผลกระทบในรูปแบบในตารางกระบวนการ ( grepกระบวนการ)


4
เพราะทุกอย่างเป็นไฟล์ "ใน linux land"
zee

@ z_- ไม่แน่ใจว่าเชื่อมต่ออย่างไร แต่สิ่งนี้ยังคงเป็นจริงแม้ใน non-Linux Unices
Kusalananda

4
ไม่เพียง แต่กระบวนการ grep เท่านั้น สคริปต์ที่ถูกตั้งชื่อcheck_varnish_pro.shนั้นก็เป็นปัจจัยเช่นกัน
TNW

@TNW ฉันไม่ได้เห็นในตอนแรก แต่คุณพูดถูก ฉันจะเพิ่มสิ่งต่อไปนี้
Kusalananda

3

@AlexP อธิบายอย่างชัดเจนว่าเกิดอะไรขึ้นจริง ๆ แต่ความคิดของ @ Kusalananda ในการใช้pgrep/ pkillสำหรับกระบวนการที่สำคัญนั้นเป็นสิ่งที่ไม่ควรทำ โซลูชันที่ดีกว่ารวมถึง:

  • ถามบริการว่ากำลังทำงานอยู่หรือไม่ systemctl status varnishdควรดูแลสิ่งนั้นในการติดตั้ง * ระวัง
  • หากในสถานการณ์ที่โชคร้ายคุณไม่มีบริการคุณสามารถเปลี่ยนสคริปต์เริ่มต้นเพื่อรายงานปัญหาได้ทันทีที่กระบวนการออก:

    varnish || true
    some_command_to_send_an_alert_that_the_service_has_died
    
  • อีกวิธีหนึ่งคือการเปลี่ยนสคริปต์ที่เริ่มต้นบริการเพื่อบันทึก PID ที่แล้วตรวจสอบรัฐเป็นระยะ ๆ kill -0 "$pid"ด้วย

ฉันเห็นด้วยฉันเพิ่งพูดถึงประเด็นการเขียนสคริปต์ของปัญหา โปรดทราบว่าsystemctlเกือบจะมีเฉพาะใน Linux (AFAIK) เท่านั้นและไม่ได้อยู่ในระบบเหมือนยูนิกซ์ที่ทันสมัยทั้งหมด
Kusalananda

คำถามเดิมมีแท็ก "linux"; ฉันไม่แน่ใจว่าทำไมถูกลบโดย @muru
l0b0

ขอบคุณ l0b0 ฉันมีสองคำถาม "ทำไม" และ "วิธีการปรับปรุง" @ คำตอบของ AlexP แก้ไขคำถามแรกของฉันและคำตอบของคุณคือทางออกที่ดีกว่าสำหรับคำถามที่สอง แต่ Kusalananda อธิบายสิ่งต่าง ๆ ที่เกี่ยวข้องกับเรื่องนี้ซึ่งฉันคิดว่าจะเป็นประโยชน์สำหรับผู้ที่มีปัญหาคล้ายกัน ดังนั้นฉันจึงสับสนตอนนี้ที่จะยอมรับว่าเป็นคำตอบ
prado

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