ตรวจพบว่าเครื่องมือกำลังทำงานอยู่แล้ว แต่สำหรับผู้ใช้ปัจจุบันเท่านั้น


8

จนถึงตอนนี้ฉันใช้

pidof -o %PPID -x "my-tool"

ในการตรวจจับ pid ของอินสแตนซ์ที่กำลังทำงานในที่สุดของเครื่องมือของฉัน

ไฟล์นี้เป็นเวอร์ชันย่อของไฟล์ my-tool ซึ่งเป็นสคริปต์ bash ที่สามารถเรียกทำงานได้

#!/bin/bash 

if pidof -o %PPID -x "my-tool"; then
   echo "Already running"
   exit 1
fi

 ... if not running go on 

แต่ตอนนี้ฉันต้องการอนุญาตให้มีอินสแตนซ์เดียวต่อผู้ใช้และหลายต่อเครื่องดังนั้นเราจึงสามารถมีเครื่องมือของฉันได้ 100 รายการในเวลาเดียวกัน แต่เพียง 1 ต่อผู้ใช้

โปรดทราบว่าฉันต้องการทดสอบเพื่อสร้างบางสิ่งบางอย่างเช่นซิงเกิล หากเครื่องมือเริ่มทำงานและมีอินสแตนซ์อื่นกำลังทำงานอยู่มันจะปิดตัวเอง

ในระยะสั้น: ฉันต้องการให้สคริปต์ทุบตีตรวจพบว่าตัวเองกำลังทำงานอยู่สำหรับผู้ใช้ปัจจุบันและในกรณีนี้มันจะต้องออก

ทำอย่างไร ?


คุณไม่ควรใช้pidofมันมีเครื่องมือที่ดีกว่าpgrep
แมว

คำตอบ:


12

ใช้pgrepแทน:

pgrep -cxu $USER -f my-tool

ตัวเลือกที่ใช้คือ:

   -c, --count
          Suppress  normal  output; instead print a count of matching pro
          cesses.  When count does not match anything, e.g. returns  zero,
          the command will return non-zero value.
   -x, --exact
          Only match processes whose names (or command line if -f is spec
          ified) exactly match the pattern.
   -u, --euid euid,...
          Only match processes whose effective user ID is listed.   Either
          the numerical or symbolical value may be used.

$0หากคุณต้องการที่จะใช้ในสคริปต์ทุบตีว่าการตรวจสอบหากมีการทำงานอยู่แล้วคุณสามารถใช้ ขยายตัวนี้ไปยังเส้นทางของสคริปต์ปัจจุบัน (เช่น/home/username/bin/foo.sh) foo.shแต่เราจำเป็นเท่านั้น เพื่อให้ได้ว่าเราสามารถเอาทุกอย่างขึ้นอยู่กับที่ผ่านมา/โดยใช้ทุบตีเครื่องมือสตริงการจัดการ${0##*/} : นี่หมายความว่าเราสามารถทำสิ่งที่ชอบ:

## If there are more than 1 instances of the current script run
## by this user
if [[ $(pgrep -cxu "$USER" "${0##*/}") -gt 1 ]];
then
        echo "Script already running, exiting."
        exit
fi

คุณอาจต้องการใช้ lockfiles สำหรับสิ่งนี้:

## If the lock file exists
if [ -e /tmp/$USER.foo.lock ]; then
    ## Check if the PID in the lockfile is a running instance
    ## of foo.sh to guard against crashed scripts
    if ps $(cat /tmp/$USER.foo.lock) | grep foo.sh >/dev/null; then
        echo "Script foo.sh is already running, exiting"
        exit
    else
        echo "Lockfile contains a stale PID, continuing"
        rm /tmp/$USER.foo.lock 
    fi
fi
## Create the lockfile by printing the script's PID into it
echo $$ > /tmp/$USER.foo.lock

## Rest of the script here

## At the end, delete the lockfile
rm /tmp/$USER.foo.lock

ขอให้เรายังคงอภิปรายนี้ในการแชท
terdon

1
แทนที่จะ touch /tmp/$USER.foo.lockใช้ PID ของกระบวนการecho $$ >/tmp/$USER.foo.lockจากนั้นตรรกะอาจถูกรวมเพื่อทดสอบว่ากระบวนการดังกล่าวมีอยู่จริงหรือไม่
Monty Harder

@ MontyHarder แน่นอนข้อเสนอแนะที่ดีมาก ตอบแก้ไขขอบคุณ
terdon

@terdon มีปัญหากับมือถือลบความคิดเห็นนั้นในวินาทีถัดไป ฉันหมายแทน$(< pidfile) $(cat pidfile)
sdkks

7

คุณสามารถใช้การpgrepค้นหาหากกระบวนการกำลังดำเนินการโดยผู้ใช้ที่ระบุและจากนั้นเริ่มต้นกระบวนการหากไม่ได้ทำงานอยู่แล้วโดยผู้ใช้:

#!/bin/bash
if pgrep -u "$USER" my-tool &>/dev/null; then
    echo 'You already have my-tool running'
else
    /path/to/my_tool
fi

ตัวแปรสภาพแวดล้อม$USERจะถูกขยายไปยังผู้ใช้ที่เข้าสู่ระบบในปัจจุบันเช่นผู้ใช้ที่รันสคริปต์ เนื่องจากเราสนใจเพียงแค่ว่าmy-toolกำลังรันอยู่หรือไม่ดังนั้นการใช้สถานะทางออกโดยตรงกับการifสร้างก็เพียงพอแล้ว

ใช้สคริปต์นี้เป็น wrapper สำหรับการเริ่มต้นmy-toolและทำให้ผู้ใช้ใช้สิ่งนี้เท่านั้นหรือเปลี่ยนชื่อเป็นmy-toolและเปลี่ยนชื่อต้นฉบับmy-toolเป็นอย่างอื่น (และเปลี่ยนชื่อภายในสคริปต์ด้วย)


ฉันไม่สามารถทำเสื้อคลุมประวัติอันยาวนาน ... ฉันจะแยก PID ของกระบวนการปัจจุบันได้อย่างไร
realtebo

@realtebo ummm..exclude PID หมายถึงอะไร
heemayl

2

ลองด้วยตัวอย่างนี้:

#!/bin/bash
MyProcessName=$(ps -p $$ -o args=)
Mypid=$$
AllPids=$(pgrep -fu "$(whoami)" "$MyProcessName")
AllPids=$(tr "\n" ' ' <<<"$AllPids")
Pids=$(sed "s/$Mypid//" <<<"$AllPids")
echo "$$: Instances including itself: $AllPids"
echo "$$: Instances different from itself: $Pids"

มันเป็นสิ่งสำคัญที่จะไม่เขียนpgrep|trเพราะสิ่งนี้จะแยกเป็นชื่อเปลือกเดียวกัน


2

ห่อคำสั่งที่คุณต้องการเรียกใช้ในฝูงเพื่อให้แน่ใจว่ามีการคัดลอกครั้งละหนึ่งรายการเท่านั้น ใช้ lock_file ที่เก็บอยู่ในแผนผังโฮมของผู้ใช้เพื่อให้ผู้ใช้แต่ละคนมีล็อกไฟล์ของตนเอง ตัวอย่างเช่น:

lockfile = "~/lockfile"
(
 if flock -n 200; then
    command
 else
    echo "Could not get lock $lock_file
 fi
) 200>$lock_file

'command' สามารถเป็นคำสั่ง bash หรือสคริปต์ใด ๆ ก็ได้

man flock ให้ตัวอย่างของการใช้งาน


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