सवाल अभी शुरू प्रक्रिया की पिड कैसे प्राप्त करें


मैं प्रक्रिया शुरू करना चाहता हूं (उदाहरण के लिए myCommand) और इसके पिड प्राप्त करें (इसे बाद में मारने की अनुमति दें)।

मैंने पीएस की कोशिश की और नाम से फ़िल्टर किया, लेकिन मैं नामों से प्रक्रिया को अलग नहीं कर सकता

myCommand
ps ux | awk '/<myCommand>/ {print $2}' 

क्योंकि प्रक्रिया नाम अद्वितीय नहीं हैं।

मैं प्रक्रिया को चला सकता हूं:

myCommand &

मैंने पाया कि मैं इस पीआईडी ​​को प्राप्त कर सकता हूं:

echo $!

क्या कोई आसान समाधान है?

मुझे अपने कॉमांड को निष्पादित करने और एक लाइन कमांड के परिणामस्वरूप पीआईडी ​​प्राप्त करने में खुशी होगी।


52
2017-11-24 08:28


मूल




जवाब:


इससे सरल क्या हो सकता है echo $!? एक पंक्ति के रूप में:

myCommand & echo $!

61
2017-11-24 08:46



धन्यवाद "इन" के साथ इन आदेशों को विलय करने में मुझे बहुत मदद मिली। - rafalmag
एक बैश स्क्रिप्ट में, एक लूप में जो प्रोग्राम शुरू करता है, $! सटीक नहीं है। कभी-कभी यह स्क्रिप्ट के ढक्कन को वापस लौटाता है, कभी-कभी स्क्रिप्ट से grep या awk रन के किसी भी समाधान को विशेष रूप से इस परिदृश्य में लॉन्च की गई प्रक्रिया के ढक्कन को प्राप्त करने के लिए? कुछ पिड = की तरहmyprogram बहुत अच्छा होगा
एनबी कि यह आपको एक का उपयोग कर कमांड शुरू करने की आवश्यकता है & पिछली पंक्ति के रूप में, अन्यथा गूंज मूल रूप से खाली हो जाती है। - rogerdpack
वैरिएबल को असाइन करना command & echo $! इस चरण में निष्पादन को फ्रीज करता है :( - Shashank Vivek
यह मेरे जीवन को बचाओ! धन्यवाद। - temple


एक छोटी लिपि में आदेश लपेटें

#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file

21
2017-11-24 08:48





मुझे किसी भी सरल समाधान के बारे में पता नहीं है, लेकिन $ का उपयोग नहीं कर रहा है! काफी है? यदि आप दूसरों के अनुसार कहा जाता है, तो आप हमेशा किसी अन्य चर के लिए मान असाइन कर सकते हैं।

एक साइड नोट के रूप में, पीएस से पाइप करने के बजाय आप इसका उपयोग कर सकते हैं pgrep या pidof


7
2018-03-20 16:58





आप उपयोग कर सकते हैं sh -c तथा exec कमांड की पीआईडी ​​भी प्राप्त करने के लिए से पहले यह चलता है

शुरू करना myCommand, ताकि इसे चलाने से पहले इसकी पीआईडी ​​मुद्रित हो, आप इसका उपयोग कर सकते हैं:

sh -c 'echo $$; exec myCommand'

यह काम किस प्रकार करता है:

यह एक नया खोल शुरू करता है, उस खोल के पीआईडी ​​को प्रिंट करता है, और फिर इसका उपयोग करता है exec में निर्मित बदलने के अपने आदेश के साथ खोल, यह सुनिश्चित करना कि यह एक ही पीआईडी ​​है। जब आपका खोल एक कमांड चलाता है exec बिल्टिन, आपका खोल है वास्तव में बनने वह आदेश, बजाय अधिक आम व्यवहार खुद की एक नई प्रतिलिपि बनाने के लिए, जिसका अपना अलग पीआईडी ​​है और फिर वह आदेश बन जाता है।

मुझे यह एसिंक्रोनस निष्पादन (के साथ) विकल्पों से कहीं अधिक सरल लगता है &), नौकरी नियंत्रण, या के साथ खोज ps। उन दृष्टिकोण ठीक हैं, लेकिन जब तक आपके पास उनका उपयोग करने का एक विशिष्ट कारण नहीं है - उदाहरण के लिए, शायद कमांड पहले से चल रहा है, इस मामले में अपने पीआईडी ​​की तलाश करना या नौकरी नियंत्रण का उपयोग करना समझ में आता है - मैं पहले इस तरह से विचार करने का सुझाव देता हूं। (और मैं निश्चित रूप से इसे प्राप्त करने के लिए एक जटिल लिपि या अन्य कार्यक्रम लिखने पर विचार नहीं करता)।

यह जवाब इस तकनीक का एक उदाहरण भी शामिल है।


उस आदेश के कुछ हिस्सों को कभी-कभी छोड़ा जा सकता है, लेकिन आम तौर पर नहीं।

यहां तक ​​कि यदि आप जिस शेल का उपयोग कर रहे हैं वह बोर्न-स्टाइल है और इस प्रकार इसका समर्थन करता है exec इन अर्थशास्त्र के साथ निर्मित, आप आम तौर पर उपयोग से बचने की कोशिश नहीं करना चाहिए sh -c (या समतुल्य) एक नया बनाने के लिए, अलग इस उद्देश्य के लिए खोल प्रक्रिया, क्योंकि:

  • एक बार खोल बन गया है myCommand, बाद के आदेश चलाने के लिए कोई खोल इंतजार नहीं है। sh -c 'echo $$; exec myCommand; foo चलाने की कोशिश नहीं कर पाएंगे foo खुद को बदलने के बाद myCommand। जब तक आप एक स्क्रिप्ट नहीं लिख रहे हैं जो इसे अपने अंतिम कमांड के रूप में चलाता है, तो आप इसका उपयोग नहीं कर सकते हैं echo $$; exec myCommand एक खोल में जहां आप अन्य आदेश चला रहे हैं।
  • आप एक का उपयोग नहीं कर सकते हैं subshell इसके लिए। (echo $$; exec myCommand) सिंटैक्टिक रूप से बेहतर हो सकता है sh -c 'echo $$; exec myCommand', लेकिन जब आप भागते हैं $$ के भीतर (  ), यह मूल शेल का पीआईडी ​​देता है, न कि सबहेल के। लेकिन यह सबहेल का पीआईडी ​​है जो नए कमांड का पीआईडी ​​होगा। कुछ गोले सबहेल के पीआईडी ​​को खोजने के लिए अपने स्वयं के गैर-पोर्टेबल तंत्र प्रदान करते हैं, जो आप करते हैं सकता है इसके लिए उपयोग करें। विशेष रूप से, बैश 4 में, (echo $BASHPID; exec myCommand) काम करेगा।

अंत में, ध्यान दें कि कुछ गोले एक प्रदर्शन करेंगे अनुकूलन जहां वे एक आदेश चलाते हैं जैसे कि exec (यानी, वे पहले फोर्किंग करना चाहते थे) जब यह ज्ञात होता है कि खोल को बाद में कुछ भी करने की आवश्यकता नहीं होगी। कुछ गोले इसे कभी भी करने का प्रयास करते हैं, यह आखिरी कमांड चलाने के लिए होता है, जबकि अन्य केवल तभी ऐसा करेंगे जब कमांड के पहले या बाद में कोई अन्य कमांड न हो, और अन्य इसे बिल्कुल नहीं करेंगे। प्रभाव यह है कि अगर आप लिखना भूल जाते हैं exec और बस उपयोग करें sh -c 'echo $$; myCommand' तो यह होगा कभी कभी आपको सही पीआईडी ​​दें कुछ के साथ सिस्टम कुछ गोले। मैं कभी भी भरोसा करने के खिलाफ सिफारिश करता हूं ऐसा व्यवहार, और इसके बजाय हमेशा शामिल हैं exec जब आपको यही चाहिए।


6
2017-11-24 14:13



मैं दौड़ने से पहले myCommand, मुझे अपनी बैश स्क्रिप्ट में कई पर्यावरण चर सेट करने की आवश्यकता है। क्या वे पर्यावरण को ले जाएंगे जिसमें exec आदेश चल रहा है? - user5359531
ऐसा लगता है कि मेरे पर्यावरण में आगे बढ़ता है exec आदेश। हालांकि, यह दृष्टिकोण तब काम नहीं करता है जब myCommand अन्य प्रक्रियाओं को शुरू करता है, जिन्हें आप के साथ काम करने की आवश्यकता होती है; जब मैं एक जारी करता हूं kill -INT <pid> कहा पे pid इस तरह से प्राप्त किया गया था, सिग्नल द्वारा शुरू की गई उप-प्रक्रियाओं तक नहीं पहुंचता है myCommand, जबकि अगर मैं दौड़ता हूं myCommand  वर्तमान सत्र और Ctrl + C में, संकेत सही ढंग से प्रचारित करते हैं। - user5359531
मैंने कोशिश की, लेकिन myCommand प्रक्रिया का पिड echo $$ +1 द्वारा पिड आउटपुट प्रतीत होता है। क्या मुझसे कुछ ग़लत हो रहा है? - crobar
मेरा आदेश इस तरह दिखता है: sh -c 'echo $$; exec /usr/local/bin/mbdyn -f "input.file" -o "/path/to/outputdir" > "command_output.txt" 2>&1 &' - crobar


फ़ाइल में पिड को पंजीकृत करने के बाद एक बैश स्क्रिप्ट से निष्पादन का उपयोग करें:

उदाहरण:

मान लें कि आपके पास "forever.sh" नामक एक स्क्रिप्ट है जिसे आप args p1, p2, p3 के साथ चलाना चाहते हैं

forever.sh स्रोत कोड:

#!/bin/sh

while [ 1 -lt 2 ] ; do
    logger "$0 running with parameters \"$@\""
    sleep 5
done

एक reaper.sh बनाएँ:

#!/bin/sh

echo $$ > /var/run/$1.pid
exec "$@"

reaper.sh के माध्यम से forever.sh चलाओ:

./reaper.sh ./forever.sh p1 p2 p3 p4 &

forever.sh प्रत्येक 5 सेकंड में syslog करने के लिए एक लाइन लॉगिंग करने से ज्यादा कुछ नहीं करता है

अब आपके पास /var/run/forever.sh.pid में पिड है

cat /var/run/forever.sh.pid 
5780

और हमेशा के लिए .sh aok चल रहा है। syslog grep:

Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"

आप इसे प्रक्रिया तालिका में देख सकते हैं:

ps axuwww|grep 'forever.sh p1' |grep -v grep
root      5780  0.0  0.0   4148   624 pts/7    S    16:07   0:00 /bin/sh ./forever.sh p1 p2 p3 p4

5
2017-07-19 17:02



ओह, और "ऑनलाइनर": / bin / sh -c 'echo $$> / tmp / my.pid && exec program args' & - user237419
तर्कों में आंतरिक सफेद जगह को सही ढंग से संरक्षित करने के लिए, आपको इसका उपयोग करना चाहिए exec "$@" के बजाय exec $*। तकनीकी रूप से जो आपको संरक्षित करने की आवश्यकता है वह व्हाइटस्पेस नहीं है लेकिन आईएफएस शैल पैरामीटर (जो अंतरिक्ष, टैब और न्यूलाइन पर डिफ़ॉल्ट है) में वर्णों की घटनाएं हैं। - Chris Johnsen
मुद्दा लेना। :) - user237419
धन्यवाद, मुझे $$ पैरामीटर नहीं पता था। यह बहुत उपयोगी हो सकता है। - rafalmag


बैश खोल में एक विकल्प $! हो सकता है jobs -p में निर्मित। कुछ मामलों में ! में $! वेरिएबल विस्तार से पहले (या इसके बजाय) खोल से व्याख्या की जाती है, जिससे अप्रत्याशित परिणाम होते हैं।

यह, उदाहरण के लिए, काम नहीं करेगा:

((yourcommand) & echo $! >/var/run/pidfile)

जबकि यह होगा:

((yourcommand) & jobs -p >/var/run/pidfile)

3
2017-11-24 08:46



मुझे लगता है कि आपका मतलब था ((yourcommand) और jobs -p> / var / run / pidfile)। - Dom
@ डोमिनिक ओ'ब्रायन आप बिल्कुल सही हैं। धन्यवाद। - mustaccio


आप कुछ इस तरह उपयोग कर सकते हैं:

$ myCommand ; pid=$!

या

$ myCommand && pid=$!

दो आदेश जोड़ों का उपयोग कर सकते हैं ; या &&। दूसरे मामले में, पिड केवल तभी सेट किया जाएगा जब पहला आदेश सफल हो। आप से प्रक्रिया आईडी प्राप्त कर सकते हैं $pid


1
2017-07-26 22:52



ओपी पीआईडी ​​प्राप्त करना चाहता है ताकि वह बाद में इसे मार सके। ; और echo $ echo से पहले बाहर निकलने के लिए मूल प्रक्रिया की आवश्यकता है! निष्पादित किया जाता है। - Iain
हाँ आप सही है। मेरे कॉमांड समाप्त होने के बाद यह आपको पिड देगा। - Khaled
संदर्भित $! बाद && या ; कमांड विभाजक के बाएं हाथ के लिए शुरू की गई प्रक्रिया का पीआईडी ​​आपको कभी नहीं देगा। $! केवल असीमित रूप से लॉन्च की गई प्रक्रियाओं के लिए सेट है (उदाहरण के लिए आमतौर पर & लेकिन कुछ गोले में अन्य विधियां भी होती हैं)। - Chris Johnsen
यह सहायक है, और क्यों कोई मुझे वोट नहीं देता? अच्छा काम हालांकि :) - temple


यह एक हैक-वाई उत्तर का थोड़ा सा है और अधिकतर लोगों के लिए काम नहीं करेगा। यह एक बड़ा सुरक्षा जोखिम मेथिंक भी है, इसलिए इसे तब तक न करें जब तक कि आप सुनिश्चित न हों कि आप सुरक्षित रहेंगे और इनपुट को स्वच्छ कर दिया जाएगा और ... अच्छा, आपको विचार मिलता है।

यहां छोटे सी प्रोग्राम को बाइनरी में संकलित करें start (या जो कुछ भी आप चाहते हैं), फिर अपने प्रोग्राम को चलाएं ./start your-program-here arg0 arg1 arg2 ...

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    if (argc >= 2)
    {
        printf("%lu\n", (long unsigned) getpid());
        if (execvp(argv[1], &argv[1]) < 0)
        {
            perror(NULL);
            return 127;
        }
    }
    return 0;
}

लंबी कहानी छोटी है, यह पीआईडी ​​को प्रिंट करेगा stdout, फिर प्रक्रिया में अपने कार्यक्रम लोड करें। यह अभी भी एक ही पीआईडी ​​होना चाहिए।


1