كيفية التحقق مما إذا كان معرف العملية (PID) موجود
سؤال
في نص باش ، أريد أن أفعل ما يلي (في الكود الزائف):
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
وهذا يوضح لك اسم التطبيق ، فقط الاسم بدون معرف.