كيفية التحقق مما إذا كان معرف العملية (PID) موجود

StackOverflow https://stackoverflow.com/questions/3043978

  •  27-09-2019
  •  | 
  •  

سؤال

في نص باش ، أريد أن أفعل ما يلي (في الكود الزائف):

if [ a process exists with $PID ]; then

    kill $PID 

fi

ما هو التعبير المناسب للبيان الشرطي؟

هل كانت مفيدة؟

المحلول

للتحقق من وجود عملية ، استخدم

kill -0 $pid

ولكن كما قال unwind ، إذا كنت ستقتلها على أي حال ، فقط

kill $pid

أو سيكون لديك حالة سباق.

إذا كنت تريد تجاهل إخراج النص من kill وافعل شيئًا بناءً على رمز الخروج ، يمكنك

if ! kill $pid > /dev/null 2>&1; then
    echo "Could not send SIGTERM to process $pid" >&2
fi

نصائح أخرى

أفضل طريقة هي:

if ps -p $PID > /dev/null
then
   echo "$PID is running"
   # Do something knowing the pid exists, i.e. the process with $PID is running
fi

المشكلة مع:

kill -0 $PID

هل سيكون رمز الخروج غير صفري حتى إذا كان PID يعمل ولم يكن لديك إذن لقتله. فمثلا:

kill -0 1

و

kill -0 $non-running-pid

احصل على رمز خروج لا يمكن تمييزه (غير صفري) للمستخدم العادي ، لكن عملية البداية (PID 1) تعمل بالتأكيد.

نقاش

الإجابات التي تناقش ظروف القتل والعرق صحيحة تمامًا إذا كان جسم الاختبار "قتل". جئت أبحث عن الجنرال "كيف تختبر وجود PID في باش".

طريقة /proc مثيرة للاهتمام ، ولكن إلى حد ما تحطم روح تجريد الأوامر "PS" ، أي أنك لا تحتاج إلى البحث عن /proc لأن ماذا لو قرر لينوس استدعاء ملف "exe" شيء آخر؟

if [ -n "$PID" -a -e /proc/$PID ]; then
    echo "process exists"
fi

أو

if [ -n "$(ps -p $PID -o pid=)" ]

في الشكل الأخير ، -o pid= هو تنسيق الإخراج لعرض عمود معرف العملية فقط بدون رأس. اقتباسات من الضروري لمشغل السلسلة غير الفاضذ -n لإعطاء نتيجة صالحة.

ps القيادة مع -p $PID تستطيع فعلها:

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs

لديك طريقتان:

لنبدأ بالبحث عن تطبيق معين في الكمبيوتر المحمول الخاص بي:

[root@pinky:~]# ps fax | grep mozilla
 3358 ?        S      0:00  \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2    S+     0:00              \_ grep mozilla

جميع الأمثلة الآن سوف تبحث عن PID 3358.

أول طريقة: قم بتشغيل "PS aux" و grep لـ PID في العمود الثاني. في هذا المثال ، أبحث عن Firefox ، وبعد ذلك هو pid:

[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358

لذلك سيكون الرمز الخاص بك:

if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
    kill $PID 
fi

الطريق الثاني: فقط ابحث عن شيء ما في /proc/$PID الدليل. أنا أستخدم "exe" في هذا المثال ، ولكن يمكنك استخدام أي شيء آخر.

[root@pinky:~]# ls -l /proc/3358/exe 
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash

لذلك سيكون الرمز الخاص بك:

if [ -f /proc/$PID/exe ]; then
    kill $PID 
fi

راجع للشغل: ما الخطأ في kill -9 $PID || true ?


تعديل:

بعد التفكير في الأمر لبضعة أشهر .. (حوالي 24 ...) الفكرة الأصلية التي أعطيتها هنا هي اختراق لطيف ، ولكن غير محمول للغاية. على الرغم من أنه يعلم بعض تفاصيل التنفيذ لـ Linux ، إلا أنه سيفشل في العمل على Mac أو Solaris أو *BSD. قد يفشل حتى في نواة Linux المستقبلية. من فضلك - استخدام "PS" كما هو موضح في ردود أخرى.

أعتقد أن هذا حل سيء ، يفتح لظروف السباق. ماذا لو ماتت العملية بين الاختبار ودعتك للقتل؟ ثم القتل سيفشل. فلماذا لا تجرب فقط القتل في جميع الحالات ، وتحقق من قيمة الإرجاع لمعرفة كيف سارت الأمور؟

يبدو أنك تريد

wait $PID

التي ستعود متى $pid ينتهي.

وإلا يمكنك استخدام

ps -p $PID

للتحقق مما إذا كانت العملية لا تزال حية (هذا أكثر فعالية من kill -0 $pid لأنه سيعمل حتى لو كنت لا تملك PID).

الكود أدناه يتحقق مما إذا كانت عمليتي تعمل ، إذا كان الأمر كذلك لا شيء.

دعنا نتحقق من الرسائل الجديدة من Amazon SQS كل ساعة فقط وفقط إذا لم تكن العملية قيد التشغيل.

#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
    /usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
    echo "do nothing, just smile =)"
fi
exit $?

أنا هنا أقوم بتخزين PID في ملف يسمى .pid (وهو نوع من مثل /تشغيل /...) وتنفيذ البرنامج النصي فقط إذا لم يتم تنفيذها بالفعل.

#!/bin/bash
if [ -f .pid ]; then
  read pid < .pid
  echo $pid
  ps -p $pid > /dev/null
  r=$?
  if [ $r -eq 0 ]; then
    echo "$pid is currently running, not executing $0 twice, exiting now..."
    exit 1
  fi
fi

echo $$ > .pid

# do things here

rm .pid

ملاحظة: هناك حالة سباق لأنه لا يتحقق من كيفية استدعاء هذا PID. إذا تم إعادة تشغيل النظام وتواجد .pid ولكن يتم استخدامه من خلال تطبيق مختلف ، فقد يؤدي ذلك "عواقب غير متوقعة".

على سبيل المثال في GNU/Linux يمكنك استخدامه:

Pid=$(pidof `process_name`)

if [ $Pid > 0 ]; then

   do something
else

   do something
fi 

أو شيء مثل

Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN

وهذا يوضح لك اسم التطبيق ، فقط الاسم بدون معرف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top