سؤال

أبدأ عملية خلفية من البرنامج النصي 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top