วิธีการตรวจสอบว่ากระบวนการทำงานอยู่หรือไม่และใช้เพื่อสร้างเชลล์สคริปต์แบบมีเงื่อนไข


108

ฉันจะทราบได้อย่างไรว่ากระบวนการกำลังทำงานอยู่หรือไม่จากนั้นให้สคริปต์ทุบตีดำเนินการบางอย่างตามเงื่อนไขนั้น

ตัวอย่างเช่น:

  • หากกระบวนการabcทำงานให้ทำเช่นนี้

  • หากไม่ได้ทำงานให้ทำเช่นนั้น


1
รู้สึกว่าเป็นเรื่องสำคัญที่จะต้องทราบว่าวิธีการแก้ปัญหาด้านล่างนี้ไม่ได้คำนึงถึงสถานะของกระบวนการ ความคิดเห็นเกี่ยวกับหนึ่งในคำถามของฉันทำให้ฉันมาที่นี่ แต่คำตอบนั้นทำให้ฉันอยู่ในสถานะที่แตกต่างกันของโปรแกรมเช่นzombieกระบวนการ '(ไม่ใช่สิ่งที่ฉันจะอธิบายว่าเป็นกระบวนการ "กำลังทำงาน") รายการทั้งหมดของสิ่งที่STATค่าคอลัมน์ในผลลัพธ์ของการpsบ่งชี้อยู่ที่นี่สำหรับผู้ที่มีแนวโน้มที่จะเขียนคำตอบที่รองรับสิ่งนี้หรือแก้ไขของตัวเอง
user66001

การสนทนาที่เกี่ยวข้อง: unix.stackexchange.com/questions/74185/…
blong

มีวิธีที่ดีที่สุดในการตรวจสอบกระบวนการ: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

คำตอบ:


166

สคริปต์ทุบตีที่จะทำอะไรแบบนั้นจะมีลักษณะเช่นนี้:

#!/bin/bash

# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern. 

if pgrep -x "gedit" > /dev/null
then
    echo "Running"
else
    echo "Stopped"
fi

สคริปต์นี้เพิ่งตรวจสอบเพื่อดูว่าโปรแกรม "gedit" ทำงานอยู่หรือไม่

หรือคุณสามารถตรวจสอบว่าโปรแกรมไม่ทำงานเช่นนี้หรือไม่:

if ! pgrep -x "gedit" > /dev/null
then
    echo "Stopped"
fi

@DreadPirateShawn คุณบอกฉันได้ไหมว่าทำไมถึงใช้ / dev / null และไม่ใช่แค่ 0 การใช้หมายเลขทำให้วิธีการอ่านง่ายขึ้นอย่างน้อยสำหรับ noob (เช่นฉัน) ไม่มีการเปลี่ยนเส้นทางไม่มีอะไร
Silviu

2
@Silviu huh? Googling /dev/null: "/ dev / null เปลี่ยนเส้นทางออกมาตรฐานคำสั่งไปยังอุปกรณ์ null ซึ่งเป็นอุปกรณ์พิเศษที่เหลือใช้ข้อมูลที่เขียนไปว่า" ... การใช้จะเปลี่ยนเส้นทางออกคำสั่งไปยังไฟล์ที่เรียกว่า0 0ในกรณีนี้ฉันขอแนะนำให้ใช้ความสะดวกสบายมากขึ้น> /dev/null- คุณจะเห็นได้ทุกที่เนื่องจากเป็นวิธีมาตรฐาน / เหมาะสมในการทิ้งเอาต์พุต
DreadPirateShawn

ว้าวขอบคุณฉันใช้มันเป็นสคริปต์ตัวเล็ก ๆ ที่ตรวจสอบว่าโปรแกรมกำลังทำงานก่อนที่มันจะทำงาน (ถึงแม้ว่าฉันจะต้องขยายออกไปเล็กน้อยเนื่องจากความสามารถในการใช้งานของ Google Chrome ไม่มีชื่อเดียวกับคำสั่ง run แต่ชื่อ exec เป็นเพียง chrome)
Cestarian

3
โปรดเพิ่ม-xพารามิเตอร์เพื่อpgrepให้มันกำลังมองหาแอปพลิเคชันที่ถูกต้องมิฉะนั้นจะได้รับการแก้ไขที่ถูกต้องหากพบสตริงเดียวกันภายในชื่อของแอปอื่น ฉันใช้เวลา 1 ชั่วโมงเพื่อหาคำตอบ
Thanos Apostolou

1
เพื่อตรวจสอบว่าโปรแกรมไม่ทำงานหรือไม่! pgrep
Mohammed Noureldin

36

วิธีการแก้ปัญหาใด ๆ ที่ใช้สิ่งที่ชอบps aux | grep abcหรือpgrep abcมีข้อบกพร่อง

ทำไม?

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

ดังนั้นฉันจะทดสอบกระบวนการที่ใช้งานได้อย่างน่าเชื่อถือได้อย่างไร

ขึ้นอยู่กับสิ่งที่คุณต้องการสำหรับการทดสอบ

ฉันต้องการตรวจสอบให้แน่ใจว่าบริการabcกำลังทำงานอยู่และหากไม่เริ่มให้บริการ

นี่คือสิ่งที่ init และ upstart ใช้สำหรับ พวกเขาจะเริ่มบริการและตรวจสอบให้แน่ใจว่า pid ของมันถูกเก็บไว้ใน pidfile ลองเริ่มบริการอีกครั้ง (ผ่าน init หรือ upstart) และจะตรวจสอบ pidfile และเริ่มถ้าไม่ได้อยู่ที่นั่นหรือยกเลิกถ้ามันทำงานอยู่ สิ่งนี้ยังคงไม่น่าเชื่อถือ 100% แต่ใกล้เคียงกับที่คุณได้รับ

ดูฉันจะตรวจสอบได้อย่างไรเพื่อดูว่าเซิร์ฟเวอร์เกมของฉันยังคงทำงานอยู่หรือไม่ ...สำหรับวิธีแก้ปัญหาอื่น ๆ

abcเป็นสคริปต์ของฉัน ฉันต้องตรวจสอบให้แน่ใจว่ามีสคริปต์เดียวของฉันทำงานอยู่

ในกรณีนี้ใช้ lockfile หรือ lockdir เช่น

#!/usr/bin/env bash

if ! mkdir /tmp/abc.lock; then
    printf "Failed to acquire lock.\n" >&2
    exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT  # remove the lockdir on exit

# rest of script ...

ดูBash FAQ 45สำหรับวิธีล็อคอื่น ๆ


3
ในขณะที่นี่เป็นเรื่องจริงทางเทคนิคฉันเคยพบปัญหาเช่นนี้ในชีวิตจริง โปรแกรมส่วนใหญ่จะไม่เปลี่ยนชื่อในลักษณะที่ทำให้สคริปต์แตก ดังนั้นสำหรับสคริปต์แบบง่าย ๆ ที่คล้ายกันpgrepหรือpsเพียงพออย่างสมบูรณ์และวิธีการของคุณดูเหมือนจะเกินความจริง หากคุณกำลังเขียนใบบันทึกเพื่อเผยแพร่ต่อสาธารณชนคุณควรเขียนอย่างปลอดภัยที่สุดเท่าที่จะทำได้
Scott Severance

2
@ScottSeverance โปรแกรมเปลี่ยนชื่อไม่ใช่ปัญหา ที่จะต้องมีการแทรกแซงโดยไม่คำนึงถึง เป็นผู้ใช้รายอื่นที่รันโปรแกรมเดียวกันหรือโปรแกรมอื่นที่มีชื่อคล้ายกันซึ่งจะทำให้สคริปต์รับผลบวกผิด ๆ และทำสิ่งที่ผิด ฉันชอบ "งาน" มากกว่า "ส่วนใหญ่ทำงาน"
geirha

2
ฉันสะกดผิด แต่พวกเราหลายคนใช้ระบบผู้ใช้คนเดียว และในสถานการณ์ของผู้ใช้หลายคนการรวมชื่อผู้ใช้ด้วย
Scott Severance

1
จะทำอย่างไรถ้าสคริปต์ของคุณล้มเหลวระหว่างรันไทม์และตายก่อนที่จะปลดล็อคไฟล์
jp093121

2
@ jp093121 แทร็บ EXIT ถูกทริกเกอร์เมื่อสคริปต์ออก ไม่ว่าจะออกเพราะมันมาถึงจุดสิ้นสุดของสคริปต์คำสั่ง exit หรือรับสัญญาณ (ที่สามารถจัดการได้) rmคำสั่งจะถูกเรียกใช้ ดังนั้นตราบใดที่มันสิ้นสุดลงหลังจากที่ตั้งกับดักไว้ล็อคควรจะหายไป
geirha

18

นี่คือสิ่งที่ฉันใช้:

#!/bin/bash

#check if abc is running
if pgrep abc >/dev/null 2>&1
  then
     # abc is running
  else
     # abc is not running
fi

ในภาษาอังกฤษธรรมดา: ถ้า 'pgrep' ส่งคืนค่า 0 กระบวนการกำลังทำงานมิฉะนั้นจะไม่เป็นเช่นนั้น


การอ่านที่เกี่ยวข้อง:

Bash Scripting :: การเปรียบเทียบสตริง

คู่มือ Ubuntu pgrep


ขอบคุณ! ฉันลองมันด้วยเหมือนกันมันใช้ได้ดีเหมือนกัน :)
Nirmik

pgrepมี "คุณสมบัติ" ขีด จำกัด อักขระ 15 ตัวที่กล่าวถึงก่อนหน้านี้ดังนั้นตัวอย่างเช่นpgrep gnome-power-managerจะล้มเหลว
Thorsen

1
ตรวจสอบให้แน่ใจว่าคุณใช้-xตัวเลือกของ pgrep : "จับคู่เฉพาะกระบวนการที่มีชื่อ (หรือบรรทัดคำสั่งหากระบุ -f) ตรงกับรูปแบบทุกประการ"
Alastair Irvine

5

ฉันมักจะมีpidof -x $(basename $0)สคริปต์ของฉันเพื่อตรวจสอบว่ามันทำงานอยู่แล้ว


2

การคิดตามแนวคิดของ @ rommel-cid คุณสามารถใช้pidofกับ || (||) เพื่อเรียกใช้คำสั่งหากกระบวนการไม่มีอยู่และ && เพื่อเรียกใช้บางอย่างหากกระบวนการนั้นมีอยู่ดังนั้นจึงสร้างเงื่อนไขอย่างรวดเร็วหาก / แล้ว / เงื่อนไขอื่น ตัวอย่างเช่นที่นี่เป็นกระบวนการที่กำลังทำงานอยู่ (เบราว์เซอร์ chrome ของฉันซึ่งมีชื่อกระบวนการคือ "chrome") และการทดสอบหนึ่งกระบวนการที่ไม่มีอยู่ ฉันระงับเอาท์พุทมาตรฐานโดยใช้ 1> / dev / null เพื่อที่จะไม่พิมพ์:

$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
 instead"
it's not running? ok i'll run instead
$

1

ไม่มีการแก้ปัญหา "ง่าย" ทำงานสำหรับฉันเพราะไบนารีที่ฉันต้องการที่จะตรวจสอบไม่ได้ติดตั้งทั้งระบบดังนั้นฉันจะต้องตรวจสอบกับเส้นทางซึ่งจะต้องใช้ps -ef | grepวิธีการ:

app="$_sdir/Logic 1.2.18 (64-bit)/Logic"

app_pid=`ps -ef | grep "$app" | awk '{print $2}'`

if `ps -p $app_pid > /dev/null`; then
    echo "An instance of logic analyzer is appear to be running."
    echo "Not starting another instance."
    exit 5
else
    nohup "$app" &> /dev/null &
fi

0

สิ่งแรกที่อยู่ในใจของฉันสำหรับปัญหาของคุณ:
ps aux | grep -i abcจะแสดงรายละเอียดของกระบวนการถ้ามันทำงาน คุณสามารถจับคู่จำนวนบรรทัดหรือเวลาที่ทำงานและเปรียบเทียบกับศูนย์หรือการจัดการอื่น ๆ เมื่อคุณเรียกใช้คำสั่งข้างต้นมันจะแสดงอย่างน้อยหนึ่งบรรทัดของผลลัพธ์เช่นรายละเอียดเกี่ยวกับกระบวนการที่สร้างโดยคำสั่ง thi grep .. ดังนั้นดูแล
นั่นควรจะเป็นการแฮ็กแบบง่ายๆ วางไว้ในสคริปต์ทุบตีและดูว่ามีประโยชน์หรือไม่


0

การใช้start-stop-daemon:

/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2

มันทำงานได้เหมือนผู้ใช้ปกติ


0

ฉันพบว่าคำตอบที่ยอมรับซึ่งโพสต์โดย @John Vrbanac ไม่ทำงานสำหรับฉันและคำตอบที่โพสต์โดย @geirha ไม่ตอบคำถามดั้งเดิม

โซลูชันของ John Vrbanac ไม่ทำงานเพื่อตรวจสอบว่ากระบวนการ PHP ทำงานอยู่หรือไม่สำหรับฉันฉันใช้งาน CentOS 7

คำตอบของ @ geirha ทำให้แน่ใจว่าอินสแตนซ์ยังไม่ทำงานก่อนที่จะเริ่มต้นใหม่ นี่ไม่ใช่คำถามเดิมคำถามเดิมคือการตรวจสอบว่ากระบวนการทำงานอยู่หรือไม่

นี่คือสิ่งที่ทำงานสำหรับฉัน:

สมมติว่ากระบวนการของฉันมีสตริง "Jane" อยู่ในชื่อกระบวนการ จะพบว่าทำงานหรือไม่ ใช้งานได้กับสคริปต์ BASH และ PHP

ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
    echo "It's running"
else
    echo "It's not running"
fi

1
อาเช่นนี้เป็นเว็บไซต์ถาม - ตอบของ Ubuntu ไม่น่าแปลกใจที่บางคำตอบที่นี่ใช้ไม่ได้กับ CentOS 7 เนื่องจาก Linux อยู่นอกหัวข้อที่นี่ รุ่นอื่น ๆ ของ Linux ได้รับการสนับสนุนที่unix.stackexchange.com
Elder Geek

แม้ว่าผู้เขียนคำตอบจะใช้ CentOS คำตอบนี้ยังคงใช้ได้สำหรับ Ubuntu
Phillip -Zyan K Lee- Stockmann

0
## bash

## function to check if a process is alive and running:

_isRunning() {
    ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}

## example 1: checking if "gedit" is running

if _isRunning gedit; then
    echo "gedit is running"
else
    echo "gedit is not running"
fi

## example 2: start lxpanel if it is not there

if ! _isRunning lxpanel; then
    lxpanel &
fi

## or

_isRunning lxpanel || (lxpanel &)

หมายเหตุ : pgrep -x lxpanelหรือpidof lxpanelยังรายงานที่lxpanelกำลังทำงานแม้ว่าจะหมดอายุ (zombie); ดังนั้นเพื่อให้ได้กระบวนการที่มีชีวิตชีวาและดำเนินอยู่เราจำเป็นต้องใช้psและgrep


-1

ตั้งแต่วันที่ 23 กันยายน 2559 pgrep ต้องมีตัวเลือก "-x" เพื่อให้สคริปต์ของ muru ทำงานได้

#!/bin/bash

if pgrep -x "conky" > /dev/null 2>&1
then
  echo "conky running already"
else
  echo "now starting conky"
  conky
fi
exit 0

ฉันลองและทดสอบสคริปต์ด้านบนในเครื่อง Ubuntu 16.04.1 สนุก!


-1
#!/bin/bash
while [ true ]; do     # Endless loop.
  pid=`pgrep -x ${1}`  # Get a pid.
  if [ -z $pid ]; then # If there is none,
    ${1} &             # Start Param to background.
  else
    sleep 60           # Else wait.
  fi
done

1
ยินดีต้อนรับสู่ถาม Ubuntu! ฉันขอแนะนำให้แก้ไขคำตอบนี้เพื่อขยายด้วยรายละเอียดเฉพาะเกี่ยวกับสิ่งที่ทำ (ดูเพิ่มเติมฉันจะเขียนคำตอบที่ดีได้อย่างไรสำหรับคำแนะนำทั่วไปเกี่ยวกับคำตอบประเภทใดที่ถือว่ามีค่ามากที่สุดใน AskUbuntu)
David Foerster

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