ব্যাকগ্রাউন্ড প্রক্রিয়াটির প্রক্রিয়া আইডি কীভাবে পাবেন?


375

আমি আমার শেল স্ক্রিপ্ট থেকে একটি পটভূমি প্রক্রিয়া শুরু করি এবং আমার স্ক্রিপ্টটি শেষ হয়ে গেলে আমি এই প্রক্রিয়াটি শেষ করতে চাই।

কীভাবে আমার শেল স্ক্রিপ্ট থেকে এই প্রক্রিয়াটির পিআইডি পাবেন? যতদূর আমি দেখতে পাচ্ছি $!চলকটিতে বর্তমান স্ক্রিপ্টের পিআইডি রয়েছে, ব্যাকগ্রাউন্ড প্রক্রিয়াটি নয়।


8
$! সঠিক. আপনি কি নিশ্চিত আপনি বিজি তে স্ক্রিপ্টটি শুরু করছেন? নমুনা করুন।
পিক্সেলবিট

7
হ্যাঁ $! সঠিক. আমি ভৃল ছিলাম.
ভোলাডাইমির বেজুগলি

11
বর্তমান স্ক্রিপ্ট পিআইডি রয়েছে।
এইচবি

উত্তর:


582

আপনি এটি শুরু করার সময় পটভূমি প্রক্রিয়াটির পিআইডি সংরক্ষণ করতে হবে:

foo &
FOO_PID=$!
# do other stuff
kill $FOO_PID

আপনি কাজের নিয়ন্ত্রণ ব্যবহার করতে পারবেন না, কারণ এটি একটি ইন্টারেক্টিভ বৈশিষ্ট্য এবং একটি নিয়ন্ত্রণকারী টার্মিনালের সাথে আবদ্ধ। কোনও স্ক্রিপ্টে অগত্যা কোনও টার্মিনাল সংযুক্ত থাকবে না তাই জব নিয়ন্ত্রণ অবশ্যই পাওয়া যাবে না।


22
যেহেতু $! শেষ পটভূমি প্রক্রিয়াটির পিড প্রদান করে এটি কি সম্ভব যে কোনও কিছু শুরু হয় fooএবং এর মধ্যে হয় $!এবং আমরা সেইটির পরিবর্তে সেইটির পাইড পাই foo?
WiSaGaN

53
@ উইসাগান: না those এই লাইনের মধ্যে কিছুই নেই। সিস্টেমে অন্য কোনও ক্রিয়াকলাপ এটিকে প্রভাবিত করবে না। $! সেই শেলের সর্বশেষ পটভূমি প্রক্রিয়াটির পিআইডি প্রসারিত হবে ।
ক্যামহ

8
... fooএকাধিক পাইপযুক্ত কমান্ড (উদা। tail -f somefile.txt | grep sometext) হয়ে গেলে যা আপনাকে পরাজিত করে । এই জাতীয় ক্ষেত্রে, আপনি যদি অনুসন্ধান করছেন তবে আপনি $!টেল কমান্ডের চেয়ে গ্রেপ কমান্ডের পিআইডি পাবেন । এই উদাহরণে আপনার ব্যবহার করতে jobsবা psপছন্দ করতে হবে ।
জন রিক্স

1
@ জনরিক্স: অগত্যা নয়। আপনি এর grepপিড পাবেন, তবে আপনি যদি এটি হত্যা করেন তবে পাইপটি লেখার চেষ্টা করার সময় লেজ একটি SIGPIPE পাবে। তবে আপনি যে কোনও জটিল প্রক্রিয়া পরিচালনা / নিয়ন্ত্রণে যাওয়ার চেষ্টা করার সাথে সাথে ব্যাশ / শেলটি বেশ বেদনাদায়ক হয়ে ওঠে।
ক্যামহহ

5
আর একটি যোগ্য সমাধানের পরামর্শ দেওয়া হয়েছে (একটি উত্তরের মন্তব্যে) কীভাবে সবেমাত্র শুরু হওয়া প্রক্রিয়াটির প্রশ্রয় পাবেন: ওহ, এবং "অনেলাইনার": /bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &- সিসফল্ট নভেম্বর 24 '10 at 14 : 28
ইম্জ - ইভান জ্যাকারিয়াচেভ

147

আপনি jobs -lএকটি নির্দিষ্ট জবএল পেতে কমান্ডটি ব্যবহার করতে পারেন

^Z
[1]+  Stopped                 guard

my_mac:workspace r$ jobs -l
[1]+ 46841 Suspended: 18           guard

এই ক্ষেত্রে, 46841 হ'ল পিআইডি।

থেকে help jobs:

-l প্রক্রিয়া গ্রুপ আইডি এবং কাজের ডিরেক্টরি ডিরেক্টরি রিপোর্ট।

jobs -p আর একটি অপশন যা কেবল পিআইডি দেখায়।


শেল স্ক্রিপ্টে এটি ব্যবহার করতে, আপনাকে আউটপুট প্রক্রিয়া করতে হবে।
ফিলি

6
@ ফিল কেবলমাত্র পিডগুলি তালিকাবদ্ধ করতে: কাজ-পি। একটি নির্দিষ্ট কাজের পিড তালিকা করতে: কাজের -p% 3। আউটপুট প্রক্রিয়া করার প্রয়োজন নেই।
এরিক অ্যারোনস্টি

1
@ এরিক বিভিন্ন কমান্ড / যুক্তি সহ আপনি আমার মন্তব্যের প্রসঙ্গটি পরিবর্তন করেন change অতিরিক্ত যুক্তি ছাড়াই আউটপুট প্রক্রিয়াজাতকরণের পরামর্শ দেয়। উত্তরের উন্নতির পরামর্শ দিন!
ফিল

$!আপনি শুরু করার ঠিক পর থেকেই পিআইডি সংরক্ষণ করা বেশিরভাগ পরিস্থিতিতে আরও পোর্টেবল এবং আরও সোজা is বর্তমানে গৃহীত উত্তরগুলি সেটাই করে।
ট্রিপলি

jobs -pjobs -lলুবুন্টু 16.4
টিমো

46
  • $$ বর্তমান স্ক্রিপ্ট এর pid হয়
  • $! সর্বশেষ পটভূমি প্রক্রিয়া এর pid হয়

এখানে বাশ সেশনের একটি নমুনা ট্রান্সক্রিপ্ট রয়েছে ( %1যা দেখেছে ব্যাকগ্রাউন্ড প্রক্রিয়ার সাধারণ সংখ্যা বোঝায় jobs):

$ echo $$
3748

$ sleep 100 &
[1] 192

$ echo $!
192

$ kill %1

[1]+  Terminated              sleep 100

প্রতিধ্বনি %1আমার উবুন্টু পটভূমি প্রক্রিয়া ফেরত দেয় না যেহেতু echo $!আছে
টিমো

25

বাশ স্ক্রিপ্টের সমস্ত শিশু প্রক্রিয়া হত্যার একটি আরও সহজ উপায়:

pkill -P $$

-Pপতাকা দিয়ে একই ভাবে কাজ করে pkillএবং pgrep- এটা চাইল্ড প্রসেস পায়, শুধুমাত্র সঙ্গে pkillচাইল্ড প্রসেস নিহত এবং পেতে সঙ্গে pgrepসন্তানের PIDs stdout- এ ছাপা হয়।


খুব সুবিধাজনক! আপনি ব্যাকগ্রাউন্ডে খোলার প্রক্রিয়াগুলি ছেড়ে যাবেন না তা নিশ্চিত করার এটি সেরা উপায়।
Lepe

@ লেপ: বেশ নয় আপনি যদি পিতামহ হন তবে এটি কাজ করবে না: bash -c 'bash -c "sleep 300 &"' & দৌড়ানোর পরে pgrep -P $$কিছুই দেখায় না, কারণ ঘুম আপনার শেলের সরাসরি শিশু হবে না।
পেট্রে

1
@ অ্যালেক্সি পোলনস্কি: এটি হওয়া উচিত: একটি শিশুদের স্কেলের সমস্ত শিশুকে হত্যা করুন, স্ক্রিপ্ট নয়। কারণ $$বর্তমান শেল বোঝায়।
টিমো

পারফরম্যান্স করে bash -c 'bash -c "sleep 300 &"' & ; pgrep -P $$, আমি [1] <pid>. So at least it shows something, but this is probably not the output of স্টাডআউট pgrep`
টিমো

এমনকি প্রক্রিয়াগুলি তাদের পিতামাতার প্রক্রিয়া থেকে বিচ্ছিন্ন করতে পারে। সাধারণ কৌশলটি কাঁটাচামচ কল করা (একটি নাতি তৈরি করা) এবং তারপরে নাতনি কাজ চালিয়ে যাওয়ার সময় কেবল সন্তানের প্রক্রিয়াটি প্রস্থান করতে দিন। (ডেমোনাইজেশন মূলশব্দ) তবে এমনকি যদি শিশু খুব প্যাকিল চালিয়ে যায় তবে -পি নাতি-নাতনিদের সংকেত প্রচার করার পক্ষে যথেষ্ট নয়। পুরো নির্ভরশীল প্রক্রিয়া ট্রি অনুসরণ করার জন্য pstree এর মতো সরঞ্জাম প্রয়োজন। কিন্তু এই তাদের পিতা বা মাতা হিসাবে প্রক্রিয়া থেকে শুরু ডেমন ধরতে হবে না প্রক্রিয়া 1. উদাহরণ:bash -c 'bash -c "sleep 10 & wait $!"' & sleep 0.1; pstree -p $$
পাউলি Nieminen

4

এই আমি কি করেছি। এটি পরীক্ষা করে দেখুন, আশা করি এটি সহায়তা করতে পারে।

#!/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অবশ্যই যথাযথ অনুমতি সহ with

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

2

আপনি pstree ব্যবহার করতে সক্ষম হতে পারে:

pstree -p user

এটি সাধারণত "ব্যবহারকারী" এর জন্য সমস্ত প্রক্রিয়াটির একটি পাঠ্য উপস্থাপনা দেয় এবং -p বিকল্পটি প্রক্রিয়া-আইডি দেয়। এটি নির্ভর করে না যতদূর আমি বুঝতে পারি, প্রক্রিয়াগুলি বর্তমান শেলের মালিকানাধীন হওয়াতে। এটি কাঁটাচামচও দেখায়।


1
শেল স্ক্রিপ্টে এটি ব্যবহার করতে, আপনাকে আউটপুটটি ভারীভাবে প্রক্রিয়া করতে হবে।
ফিলি

1

pgrepআপনাকে প্যারেন্ট প্রসেসের সমস্ত শিশু পিআইডি পেতে পারে get পূর্বে উল্লিখিত হিসাবে $$বর্তমান স্ক্রিপ্টস পিআইডি। সুতরাং, আপনি যদি কোনও স্ক্রিপ্ট চান যা নিজের পরে পরিষ্কার হয়ে যায়, এই কৌশলটি করা উচিত:

trap 'kill $( pgrep -P $$ | tr "\n" " " )' SIGINT SIGTERM EXIT

এটা কি খুব মারবে না?
ফিলি

হ্যাঁ এটি হবে, প্রস্থানটি প্রস্থান করার সময় কিছু পটভূমি বাচ্চাদের বাঁচিয়ে রাখার কথা উল্লেখ করে নি ।
errant.info

trap 'pkill -P $$' SIGING SIGTERM EXITসহজ দেখাচ্ছে, কিন্তু আমি এটি পরীক্ষা করিনি।
পেট্রে

সামঞ্জস্যের জন্য, SIGউপসর্গটি ব্যবহার করবেন না । এটি পসিক্স দ্বারা অনুমোদিত তবে ঠিক একটি এক্সটেনশন হিসাবে যা বাস্তবায়নগুলি সমর্থন করতে পারে : pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html উদাহরণস্বরূপ ড্যাশ শেলটি এটি করে না।
জোশ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.