किसी भी कमांड के PID को कमांड के बैकग्राउंड पाइप्ड अनुक्रम में प्राप्त करें


11

यदि, में bash, मैं निष्पादित करता हूं:

cmd1 | cmd2 | ... | cmdi | ... | cmdn &

जहां cmd{1..n}मैं अलग नहीं हो सकता, मैं पीआईडी ​​कैसे प्राप्त करूं cmdi? वैकल्पिक रूप से, मैं इस cmdiप्रक्रिया का संकेत कैसे दे सकता हूं ? (उदाहरण के लिए, इसे भेजने के SIGUSR1?) pkill/ pgrep, pidofआदि अच्छा जवाब की तरह लग रही नहीं है के अन्य उदाहरण के बाद से cmdiशायद, चल ही पाइप लाइन के हिस्से के रूप भी शामिल है। jobs -pका पीआईडी ​​देता है cmd1, मेरे लिए।

iमें कुछ भी हो सकता {1..n}



1
@ जी-मैन केयर समझाने के लिए? मुझे केवल सतही समानता दिखाई देती है, और जैसा कि मैंने रमेश के उत्तर में बताया था, आदेशों के समुच्चय को संशोधित करने का अधिक उपयोग नहीं है।
मूरू

सतही समानता? cat /var/run/out | nc -l 8080क्या केवल सतही रूप से समान है cmd1 | cmd2? आपका बाधा, कि आप नंगे-हड्डियों की पाइपलाइन टाइप करना चाहते हैं और फिर पीआईडी ​​को पुनर्प्राप्त करना चाहते हैं , (1) प्रश्न में नहीं कहा गया है, और (2) एक अच्छे, सामान्य समाधान के लिए अनुमति देने की संभावना नहीं है।
जी-मैन का कहना है कि 'मोनिका' की बहाली

@ जी-मैन इसके विपरीत, आप उन बाधाओं को लागू कर रहे हैं जो सरल नहीं हैं। cmd1 | cmd2एक बहुत ही विशेष मामला है जहां दोनों पीआईडी ​​आसानी से प्राप्त करने योग्य हैं। क्या मैंने n के बारे में कुछ कहा? तो आप n = 2 क्यों मानेंगे? क्या मैंने इस बारे में कुछ कहा कि सेमीडी क्या है? तो आप यह क्यों मानेंगे कि मैं सीमडी को संशोधित कर सकता हूं। मैं एक सामान्य समाधान के लिए कह रहा हूं और आप प्रतिबंध लगा रहे हैं।
मूरू

जवाबों:


6

प्रश्न के मूल संस्करण के लिए, जब केवल अंतिम कमांड का पीआईडी ​​वांछित था, विशेष चर $!एकदम सही है।

foo | bar | baz &
baz_pid=$!

अन्य प्रक्रियाओं के PID के लिए समान आसान पहुँच नहीं है।

$pipestatus(Zsh) और $PIPESTATUS(बैश) को जोड़े हुए एक लंबा समय लगा , आखिरकार हमें $?अंतिम बॉर्न शेल के बाद से पिछले एक के अलावा एक पाइप लाइन में सभी एक्ज़िट स्टेटस तक पहुंच प्रदान की गई। हो सकता है कि $!अंतत: कुछ अनुरूप होगा ।


क्या आपको बुरा लगेगा अगर मैंने सूची में एक मनमाना आदेश के पीआईडी ​​के लिए पूछने के लिए प्रश्न संपादित किया? या मुझे एक नया प्रश्न शुरू करना चाहिए?
मूरू

आपको शायद उस एक के जवाब के लिए अभी और इंतजार करना होगा। मेरे पास

यह ठीक है, तत्काल समस्या हल हो गई है, अब जिज्ञासा प्रभारी है। मैं इसे संपादित करूँगा। बस एक हेड-अप, जब से मैंने देखा है कि सवालों में भारी बदलाव आया है और पुराने उत्तरों को छोड़ दिया गया है।
मूरू

@ muru - ध्यान दें कि यह एक नया क्यू इस संदर्भ में बनाने के लिए बेहतर होता।
slm

@ एसएलएम ने विधिवत उल्लेख किया। भविष्य में ऐसा करेंगे।
मुरु

4

मुझे लगता है कि आप यहाँ सुझाए अनुसार कुछ कर सकते हैं ।

(ls -l | echo "Hello" | df -h & echo $! >&3 ) 3>pid

यहाँ ऊपर दिए गए उदाहरण में, मैंने तीसरी पाइप्ड प्रक्रिया के पिड को पुनः प्राप्त किया है और इसे फाइल पिड के रूप में नोट किया है। मैं इसे किसी भी पाइप्ड प्रक्रिया के लिए नोट कर सकता था।


दिलचस्प है, लेकिन इसमें कमांड के सेट को संशोधित करना शामिल है। एक बार कमांड निष्पादित होने के बाद ज्यादा उपयोग नहीं।
मुरु

@ मरमू - क्या? किसी भी पीआईडी ​​का उपयोग करने के बाद उसका निष्पादन समाप्त हो जाता है? क्या आप पाइपलाइन की पीआईडी ​​चाहते हैं? jobs -p। इसके साथ संकेत दें SIGPIPE। क्या आप चाहते हैं cmdi- यह।
मिकसेर्व सेप 18'14

1
@mikeserv नहीं अगर वे पृष्ठभूमि में हैं, जैसा कि हम बोलते हैं। मैं किस टोना-टोटका के लिए कमांड लाइन को संशोधित करने वाला हूं?
मूरू

1
@ मूरू एक टोना-टोटका होगा। आपको डिबगर की आवश्यकता है।
मोकेसर सेप 18'14

मुझे यह पृष्ठभूमि प्रक्रियाओं को शुरू करने के लिए एक उपयोगी पैटर्न लगता है, जो उन्हें किसी राज्य तक पहुंचने के लिए इंतजार कर रहा है, और फिर उन्हें मार रहा है। मामले में किसी को भी दिलचस्पी है: gist.github.com/MatrixManAtYrService/…
MatrixManAtYrService

2

एक बहुत-पोर्टेबल, लिनक्स-विशिष्ट समाधान उन पाइपों का उपयोग करके प्रक्रियाओं को ट्रैक करने के लिए हो सकता है जो उन्हें कनेक्ट करते हैं। हम पाइपलाइन में पहले ( jobs -p) और अंतिम ( $!) कमांड के पीआईडी ​​प्राप्त कर सकते हैं । PID का उपयोग करके, यह स्क्रिप्ट काम कर सकती है:

#! /bin/bash

PROC=$1
echo $PROC

if [[ $(readlink /proc/$PROC/fd/1) =~ ^pipe: ]]
then
    # Assuming first process in chain...
    NEXT_FD=1
elif [[ $(readlink /proc/$PROC/fd/0) =~ ^pipe: ]]
then
    # Last process in chain...
    NEXT_FD=0
else
    # Doesn't look like a pipe.
    exit
fi

NEXT_PROC_PIPE=$(readlink /proc/$PROC/fd/$NEXT_FD)

while [[ $NEXT_PROC_PIPE =~ ^pipe: ]] 
do
    PROC=$(find /proc/*/fd -type l -printf "%p/%l\n" 2>/dev/null | awk -F'/' '($6 == "'"$NEXT_PROC_PIPE"'") && ($3 != "'$PROC'" ) {print $3}')
    NEXT_PROC_PIPE=$(readlink /proc/$PROC/fd/$NEXT_FD)
    echo $PROC
done

जिज्ञासु के लिए, इस तरह की चीज़ के बारे में यहाँ और अधिक है: unix.stackexchange.com/a/486233/146169
MatrixManAtYrService

0

मैं इस कोड में यहां शून्य-आधारित सरणियों का उपयोग करता हूं। बस सावधान रहें कि आप क्या चलाते हैं eval

#!/bin/bash

cmd=('sleep 10' 'sleep 2' 'sleep 5')
first=1
for c in "${cmd[@]}"; do
  ((first)) && { pipe=$c; first=0; } || pipe+='|'$c
done
shopt -u lastpipe
eval $pipe &

printf 'Pipe:\n%s\n\n' "$pipe"

shellpid=$BASHPID
parent=$(ps -o pid= --ppid $shellpid | head -n -1)
declare -a pids=()
mapfile -t pids < <(printf '%s\n' $(ps -o pid= --ppid $parent))
printf '%s\n' 'Listing the arrays:'
printf '%2s %6s %s\n' i PID command
for i in "${!cmd[@]}"; do
    printf '%2d %6d %s\n' "$i" "${pids[i]}" "${cmd[i]}"
done

printf '\n%s\n' 'ps listing:'
ps xao pid,ppid,command | head -n 1
ps xao pid,ppid,command | tail | head -n -3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.