2010-07-27 11 views
12

निम्नलिखित सरल उदाहरण पर विचार करें में एक प्रक्रिया का पीआईडी ​​मिलता है। हालांकि, मुझे my_prog के लिए पीआईडी ​​की आवश्यकता है। अगर मैं awk को मारता हूं, my_prog अपने आउटपुट बफर को फ्लश करने के लिए नहीं जानता है और डेटा खो गया है। तो, my_prog के लिए पीआईडी ​​कैसे प्राप्त होगा? ध्यान दें कि ps aux|grep my_prog काम नहीं करेगा क्योंकि कई my_prog जा रहे हैं।कैसे एक पाइप लाइन

नोट: cat से awk '...' बदल गया ताकि मुझे जो चाहिए उसे स्पष्ट करने में सहायता के लिए।

+0

आपको बिल्ली को पाइप करने की आवश्यकता क्यों है? – ghostdog74

+1

मैं वास्तव में बिल्ली को पाइप नहीं करता, यह सिर्फ एक सरलीकृत उदाहरण है। यह वास्तव में एक बदसूरत अजीब लिपि है, लेकिन वे दोनों एक ही तरीके से व्यवहार करते हैं। – User1

+0

आप क्या करने की कोशिश कर रहे हैं?मुझे यकीन है कि एक बेहतर तरीका होना चाहिए। – msw

उत्तर

4

मैं mkfifo का उपयोग करके पाइप को स्पष्ट रूप से नाम देने के साथ इसे हल करने में सक्षम था।

चरण 1: mkfifo capture

चरण 2: भागो इस स्क्रिप्ट

 

my_prog > capture & 
my_pid="$!" #Now, I have the PID for my_prog! 
awk '...' capture > out.csv & 
sleep 10 
kill $my_pid #kill my_prog 
wait #wait for awk to finish. 
 

मैं एक mkfifo होने के प्रबंधन पसंद नहीं है। उम्मीद है कि किसी के पास एक आसान समाधान होगा।

+0

आप ऐसी प्रक्रिया क्यों मार रहे हैं जिसका आउटपुट आप चाहते हैं? – msw

+0

प्रक्रिया एक हार्डवेयर निगरानी कार्यक्रम है जो इसे मारने तक चलेगा। जब प्रक्रिया को मारने का संकेत मिलता है, तो यह अपने बफर को फहराता है। हकीकत में, बैश स्क्रिप्ट मेरे_प्रोग को मार डालेगी जब परीक्षण खत्म हो गया है जिसका उपरोक्त नींद विवरण द्वारा दर्शाया गया है। – User1

2

आपकी टिप्पणी के आधार पर, मैं अभी भी यह नहीं देख सकता कि आप व्यवस्थित फैशन में पूर्ण होने के लिए my_prog क्यों मारना पसंद करेंगे। दस सेकंड एक मल्टीप्रोसेसिंग सिस्टम पर एक सुंदर मनमाना माप है जिससे my_prog सिस्टम लोड के आधार पर आउटपुट की 10k लाइनें या 0 लाइनें उत्पन्न कर सकता है।

आप खोल से अलग करने के बिना कोशिश

my_prog | head -1000 | awk 

कुछ अधिक नियत करने के लिए my_prog के उत्पादन में सीमित करना चाहते हैं। सबसे बुरे मामले में, सिर अपना इनपुट बंद कर देगा और my_prog को एक सिगिप मिलेगा। सबसे अच्छे मामले में, my_prog बदलें ताकि यह आपको इच्छित आउटपुट की मात्रा दे।

अब तक में आप my_prog पर नियंत्रण है के रूप में यह एक वैकल्पिक -s duration तर्क दे:

टिप्पणी के जवाब में जोड़ा।

if (duration_exceeded()) { 
    exit(0); 
} 

जहां बाहर निकलने के बदले में उचित रूप से उत्पादन फ़ाइलें फ्लश: तो फिर अपने मुख्य पाश में कहीं आप विधेय डाल सकते हैं। यदि बेताब है और भविष्यवाणी करने के लिए कोई जगह नहीं है, तो इसे अलार्म (3) का उपयोग करके लागू किया जा सकता है, जिसे मैं जानबूझकर नहीं दिखा रहा हूं क्योंकि यह बुरा है।

आपकी परेशानी का मूल यह है कि my_prog हमेशा के लिए चलता है। यहां सबकुछ उस सीमा के चारों ओर जाने के लिए एक हैक है।

+1

मेरे उत्तर में मेरी टिप्पणी देखें। मुझे लगता है कि मैं मूल प्रश्न पर अधिक जानकारी दे सकता था। उपरोक्त समाधान कुछ के लिए काम कर सकता है, लेकिन यह मामला थोड़ा अलग है। अब तक आपकी सभी मदद के लिए धन्यवाद। मुझे आशा है कि आप मुझे मेरे जवाब से एक आसान समाधान के बारे में बता सकते हैं। – User1

4

अपने आदेश के चारों ओर एक शेल रैपर जोड़ें और पिड को कैप्चर करें। मेरे उदाहरण के लिए मैं iostat का उपयोग करें।

#!/bin/sh 
echo $$ > /tmp/my.pid 
exec iostat 1 

एक्सेक छिद्र को संरक्षित करने वाली नई प्रक्रिया के साथ खोल को प्रतिस्थापित करता है।

test.sh | grep avg 

है कि चलाता है:

$ cat my.pid 
22754 
$ ps -ef | grep iostat 
userid 22754 4058 0 12:33 pts/12 00:00:00 iostat 1 

तो आप कर सकते हैं:

sleep 10 
kill `cat my.pid` 

कि अधिक सुरुचिपूर्ण है?

+0

+1, रैपर। यह वास्तव में यूनिक्स डिजाइन का सार है। – Anders

+0

नहीं, रैपर अनावश्यक रूप से जटिल है। कई अन्य समाधान हैं – yaccz

5

यहां रैपर या अस्थायी फ़ाइलों के बिना समाधान है। यह केवल एक पृष्ठभूमि पाइपलाइन के लिए काम करता है जिसका आउटपुट आपके मामले में, युक्त स्क्रिप्ट के stdout से दूर कब्जा कर लिया जाता है। मान लीजिए आप क्या करना चाहते हैं: केवल बैश ${PIPEPID[n]} प्रदान कर सकता है

cmd1 | cmd2 | cmd3 >pipe_out & 
# do something with PID of cmd2 

हैं !!

PID=$({ cmd1 | { cmd2 0<&4 & echo $! >&3 ; } 4<&0 | cmd3 >pipe_out & } 3>&1 | head -1) 

आवश्यक होने पर आप भी fd 3 (cmd* के लिए) बंद कर सकते हैं और 3>&- और 4<&- क्रमशः 4 एफडी (cmd2 के लिए): प्रतिस्थापन "हैक" है कि मैंने पाया निम्नलिखित है। यदि आप ऐसा करते हैं, तो cmd2 के लिए सुनिश्चित करें कि आप के बाद fd 4 केवल बंद करें, आप इससे fd 0 को रीडायरेक्ट करते हैं।

7

बस एक ही समस्या थी। मेरा समाधान:

process_1 | process_2 & 
PID_OF_PROCESS_2=$! 
PID_OF_PROCESS_1=`jobs -p` 

बस सुनिश्चित करें कि प्रक्रिया_1 पहली पृष्ठभूमि प्रक्रिया है। अन्यथा, आपको jobs -l के पूर्ण आउटपुट को पार्स करने की आवश्यकता है।

+0

नौकरियां बनाने पर इस तरह से विश्लेषण कर सकते हैं -एल। बाद में बनाओ: PID_OF_PROCESS_1 = 'jobs -l | grep process_1 | कट-एफ 2-डी "" ' – rfranr

0

मैं पाइप नौकरी से सभी पीआईडी ​​प्राप्त करने के लिए सख्त समाधान की तलाश कर रहा था, और एक आशाजनक दृष्टिकोण बुरी तरह विफल रहा (इस उत्तर के पिछले संशोधन देखें)।

तो, दुर्भाग्य से, सबसे अच्छा मैं ऊपर आ सकता है के साथ जीएनयू awk का उपयोग कर jobs -l उत्पादन को पार्स किया जाता है:

function last_job_pids { 
    if [[ -z "${1}" ]] ; then 
     return 
    fi 

    jobs -l | awk ' 
     /^\[/ { delete pids; pids[$2]=$2; seen=1; next; } 
     // { if (seen) { pids[$1]=$1; } } 
     END { for (p in pids) print p; }' 
} 
1
@ Demosthenex के जवाब से प्रेरणा के साथ

: subshells का उपयोग कर:

$ (echo $BASHPID > pid1; exec vmstat 1 5) | tail -1 & 
[1] 17371 
$ cat pid1 
17370 
$ pgrep -fl vmstat 
17370 vmstat 1 5 
3

में सुधार @Marvin और @Nils Goroll के जवाब एक ऑनलाइनर के साथ हैं जो पाइप में सभी आदेशों के लिए एक शेल सरणी चर में पाइप निकालें:

# run some command 
ls -l | rev | sort > /dev/null & 

# collect pids 
pids=(`jobs -l % | egrep -o '^(\[[0-9]+\]\+| ) [ 0-9]{5} ' | sed -e 's/^[^ ]* \+//' -e 's! $!!'`) 

# use them for something 
echo pid of ls -l: ${pids[0]} 
echo pid of rev: ${pids[1]} 
echo pid of sort: ${pids[2]} 
echo pid of first command e.g. ls -l: $pids 
echo pid of last command e.g. sort: ${pids[-1]} 

# wait for last command in pipe to finish 
wait ${pids[-1]} 

मेरे समाधान में ${pids[-1]} में आमतौर पर $! में उपलब्ध मान शामिल है। कृपया jobs -l % का उपयोग ध्यान दें जो केवल "वर्तमान" नौकरी आउटपुट करता है, जो डिफ़ॉल्ट रूप से आखिरी बार शुरू होता है।

नमूना उत्पादन:

pid of ls -l: 2725 
pid of rev: 2726 
pid of sort: 2727 
pid of first command e.g. ls -l: 2725 
pid of last command e.g. sort: 2727 

अद्यतन 2017/11/13:pids=... आदेश है कि जटिल (बहु लाइन) आदेशों के साथ बेहतर काम करता है बेहतर।

संबंधित मुद्दे