كيفية الحصول على PID من عملية الخلفية؟
-
19-09-2019 - |
سؤال
أبدأ عملية خلفية من البرنامج النصي SHELT الخاص بي، وأود أن أقتل هذه العملية عند انتهاء البرنامج النصي.
كيفية الحصول على PID من هذه العملية من البرنامج النصي SHELT الخاص بي؟ بقدر ما أستطيع أن أرى المتغير $!
يحتوي على PID من البرنامج النصي الحالي، وليس عملية الخلفية.
المحلول
تحتاج إلى حفظ PID من عملية الخلفية في ذلك الوقت الذي تبدأ فيه:
foo &
FOO_PID=$!
# do other stuff
kill $FOO_PID
لا يمكنك استخدام التحكم الوظيفي، حيث أن هذه ميزة تفاعلية مرتبطة بمحطة التحكم. لن يكون لدى البرنامج النصي بالضرورة محطة تعلق على الإطلاق، لذا فإن التحكم في العمل لن يكون بالضرورة متاحا بالضرورة.
نصائح أخرى
يمكنك استعمال ال jobs -l
أمر للوصول إلى جبل معين
^Z
[1]+ Stopped guard
my_mac:workspace r$ jobs -l
[1]+ 46841 Suspended: 18 guard
في هذه الحالة، 46841 هي PID.
من help jobs
:
-l الإبلاغ عن معرف مجموعة العملية ودليل العمل للوظائف.
jobs -p
هو خيار آخر يظهر فقط pids.
$$
هو PID النصي الحالي$!
هي PID عملية الخلفية الأخيرة
إليك نص عينة من جلسة باش (%1
يشير إلى العدد الترتيبي لعملية الخلفية كما يظهر من jobs
):
$ echo $$
3748
$ sleep 100 &
[1] 192
$ echo $!
192
$ kill %1
[1]+ Terminated sleep 100
طريقة أكثر بساطة لقتل جميع العملية الطفل من برنامج نصي باش:
pkill -P $$
ال -P
العلم يعمل بنفس الطريقة مع pkill
و pgrep
- يحصل على عمليات الأطفال، فقط مع pkill
عمليات الطفل تقتل ومع pgrep
يتم طباعة PIDS الطفل إلى Stdout.
هذا ما فعلته. تحقق من ذلك، آمل أن يساعد.
#!/bin/bash
#
# So something to show.
echo "UNO" > UNO.txt
echo "DOS" > DOS.txt
#
# Initialize Pid List
dPidLst=""
#
# Generate background processes
tail -f UNO.txt&
dPidLst="$dPidLst $!"
tail -f DOS.txt&
dPidLst="$dPidLst $!"
#
# Report process IDs
echo PID=$$
echo dPidLst=$dPidLst
#
# Show process on current shell
ps -f
#
# Start killing background processes from list
for dPid in $dPidLst
do
echo killing $dPid. Process is still there.
ps | grep $dPid
kill $dPid
ps | grep $dPid
echo Just ran "'"ps"'" command, $dPid must not show again.
done
ثم فقط تشغيله على النحو التالي: ./bgkill.sh
مع الأذونات المناسبة بالطبع
root@umsstd22 [P]:~# ./bgkill.sh
PID=23757
dPidLst= 23758 23759
UNO
DOS
UID PID PPID C STIME TTY TIME CMD
root 3937 3935 0 11:07 pts/5 00:00:00 -bash
root 23757 3937 0 11:55 pts/5 00:00:00 /bin/bash ./bgkill.sh
root 23758 23757 0 11:55 pts/5 00:00:00 tail -f UNO.txt
root 23759 23757 0 11:55 pts/5 00:00:00 tail -f DOS.txt
root 23760 23757 0 11:55 pts/5 00:00:00 ps -f
killing 23758. Process is still there.
23758 pts/5 00:00:00 tail
./bgkill.sh: line 24: 23758 Terminated tail -f UNO.txt
Just ran 'ps' command, 23758 must not show again.
killing 23759. Process is still there.
23759 pts/5 00:00:00 tail
./bgkill.sh: line 24: 23759 Terminated tail -f DOS.txt
Just ran 'ps' command, 23759 must not show again.
root@umsstd22 [P]:~# ps -f
UID PID PPID C STIME TTY TIME CMD
root 3937 3935 0 11:07 pts/5 00:00:00 -bash
root 24200 3937 0 11:56 pts/5 00:00:00 ps -f
قد تكون أيضا قادرا على استخدام PSTEE:
pstree -p user
يعطي هذا عادة تمثيل نصي لجميع العمليات الخاصة ب "المستخدم" وخيار -p يعطي معرف العملية. لا يعتمد ذلك، بقدر ما أفهم، عند امتلاك العمليات من قبل القشرة الحالية. كما يظهر الشوك.
pgrep
يمكن أن تجعلك جميع الأطفال من عملية الوالدين. كما ذكر آنفا $$
هي PID النصية الحالية. لذلك، إذا كنت تريد برنامج نصي ينظف بعد نفسها، فيجب أن يفعل ذلك الخدعة:
trap 'kill $( pgrep -P $$ | tr "\n" " " )' SIGINT SIGTERM EXIT