कैसे "सही ढंग से" एक खोल से एक आवेदन शुरू करते हैं


21

मुझे सवाल का ठीक-ठीक उच्चारण करना कठिन लगता है लेकिन मैं अपना सर्वश्रेष्ठ दूंगा। मैं dwmअपने डिफ़ॉल्ट विंडो मैनेजर के रूप में उपयोग करता हूं औरdmenuमेरे अनुप्रयोग लांचर के रूप में। मैं शायद ही अपने ब्राउज़र से अलग जीयूआई अनुप्रयोगों का उपयोग करें। मेरा ज्यादातर काम सीधे कमांड लाइन से होता है। इसके अलावा, मैं ऑपरेटिंग सिस्टम, एप्लिकेशन आदि के बारे में अतिसूक्ष्मवाद का बहुत बड़ा प्रशंसक हूं। जिन उपकरणों से मुझे छुटकारा नहीं मिला उनमें से एक एप्लिकेशन लॉन्चर था। मुख्य रूप से इसलिए कि मुझे इस बात की सटीक समझ नहीं है कि एप्लिकेशन लांचर कैसे काम करते हैं / वे क्या करते हैं। यहां तक ​​कि व्यापक इंटरनेट खोज केवल अस्पष्ट स्पष्टीकरण दिखाती है। जो मैं करना चाहता हूं वह मेरे एप्लिकेशन लॉन्चर से भी छुटकारा दिलाता है क्योंकि वास्तव में आवेदन को अलग करने के अलावा मेरे पास इसके लिए कोई उपयोग नहीं है। ऐसा करने के लिए, मैं वास्तव में यह जानना चाहूंगा कि शेल से एप्लिकेशन को "सही ढंग से" कैसे शुरू किया जाए। जिससे "सही ढंग से" का अनुमान लगाया जा सकता है जैसे "एक एप्लिकेशन लॉन्चर करेगा"।

मुझे शेल से प्रक्रियाओं को फैलाने के निम्नलिखित तरीकों के बारे में पता है:

  1. exec /path/to/Program एक नई प्रक्रिया बनाए बिना निर्दिष्ट कमांड के साथ शेल को बदलें
  2. sh -c /path/to/Program शेल आश्रित प्रक्रिया
  3. /path/to/Program शेल आश्रित प्रक्रिया
  4. /path/to/Program 2>&1 & लॉन्च शेल स्वतंत्र प्रक्रिया
  5. nohup /path/to/Program & लॉन्च शेल स्वतंत्र प्रक्रिया और आउटपुट को पुनर्निर्देशित करना nohup.out

अद्यतन 1: मैं उदाहरण देकर बता सकता हूं कि विभिन्न स्थितियों में dmenuबार-बार कॉल से इसे फिर से बनाना क्या है ps -efl। यह एक नया शेल खोलता है /bin/bashऔर इस शेल के एक बच्चे के रूप में आवेदन करता है /path/to/Program। जब तक बच्चा चारों ओर है, तब तक शेल आसपास रहेगा। (यह कैसे प्रबंधित करता है यह मेरे से परे है ...) इसके विपरीत यदि आप nohup /path/to/Program &एक शेल से जारी करते हैं /bin/bashतो प्रोग्राम इस शेल का बच्चा बन जाएगा लेकिन यदि आप इस शेल से बाहर निकलते हैं तो प्रोग्राम का जनक अपरिपक्व प्रक्रिया होगी। इसलिए यदि पहली प्रक्रिया उदाहरण के लिए है /sbin/init verboseऔर यह है PPID 1तो यह कार्यक्रम का जनक होगा। यहाँ मैंने एक ग्राफ़ का उपयोग करके समझाने की कोशिश की: के chromiumमाध्यम से लॉन्च किया गया था dmenu, firefoxका उपयोग करके लॉन्च किया गया था exec firefox & exit:

systemd-+-acpid
        |-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
        |                 |                           `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
        |                 |                                                    |-{Compositor}]
        |                 |                                                    |-{HTMLParserThrea}]
        |                 |                                                    |-{OptimizingCompi}]
        |                 |                                                    `-3*[{v8:SweeperThrea}]]
        |                 |-chromium
        |                 |-chromium-+-chromium
        |                 |          |-{Chrome_ChildIOT}
        |                 |          `-{Watchdog}
        |                 |-{AudioThread}
        |                 |-3*[{BrowserBlocking}]
        |                 |-{BrowserWatchdog}
        |                 |-5*[{CachePoolWorker}]
        |                 |-{Chrome_CacheThr}
        |                 |-{Chrome_DBThread}
        |                 |-{Chrome_FileThre}
        |                 |-{Chrome_FileUser}
        |                 |-{Chrome_HistoryT}
        |                 |-{Chrome_IOThread}
        |                 |-{Chrome_ProcessL}
        |                 |-{Chrome_SafeBrow}
        |                 |-{CrShutdownDetec}
        |                 |-{IndexedDB}
        |                 |-{LevelDBEnv}
        |                 |-{NSS SSL ThreadW}
        |                 |-{NetworkChangeNo}
        |                 |-2*[{Proxy resolver}]
        |                 |-{WorkerPool/1201}
        |                 |-{WorkerPool/2059}
        |                 |-{WorkerPool/2579}
        |                 |-{WorkerPool/2590}
        |                 |-{WorkerPool/2592}
        |                 |-{WorkerPool/2608}
        |                 |-{WorkerPool/2973}
        |                 |-{WorkerPool/2974}
        |                 |-{chromium}
        |                 |-{extension_crash}
        |                 |-{gpu-process_cra}
        |                 |-{handle-watcher-}
        |                 |-{inotify_reader}
        |                 |-{ppapi_crash_upl}
        |                 `-{renderer_crash_}
        |-2*[dbus-daemon]
        |-dbus-launch
        |-dhcpcd
        |-firefox-+-4*[{Analysis Helper}]
        |         |-{Cache I/O}
        |         |-{Cache2 I/O}
        |         |-{Cert Verify}
        |         |-3*[{DOM Worker}]
        |         |-{Gecko_IOThread}
        |         |-{HTML5 Parser}
        |         |-{Hang Monitor}
        |         |-{Image Scaler}
        |         |-{JS GC Helper}
        |         |-{JS Watchdog}
        |         |-{Proxy R~olution}
        |         |-{Socket Thread}
        |         |-{Timer}
        |         |-{URL Classifier}
        |         |-{gmain}
        |         |-{localStorage DB}
        |         |-{mozStorage #1}
        |         |-{mozStorage #2}
        |         |-{mozStorage #3}
        |         |-{mozStorage #4}
        |         `-{mozStorage #5}
        |-gpg-agent
        |-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
        |                               |          `-{Xorg.bin}
        |                               `-dwm-+-dwmstatus
        |                                     `-xterm---bash-+-bash
        |                                                    `-pstree
        |-systemd---(sd-pam)
        |-systemd-journal
        |-systemd-logind
        |-systemd-udevd
        |-wpa_actiond
        `-wpa_supplicant

अद्यतन 2: मुझे लगता है कि प्रश्न को भी उबाला जा सकता है: किसी प्रक्रिया का जनक क्या होना चाहिए? यह उदाहरण के लिए एक खोल होना चाहिए या यह initप्रक्रिया होना चाहिए अर्थात प्रक्रिया के साथ PID 1?


3
आपके प्रश्न का उत्तर "आप जो चाहते हैं परिणाम प्राप्त होगा।"
वेन वर्नर

1
खतरे, कचरा - आप कुछ अच्छे प्रश्न पूछते हैं। लेकिन मुझे लगता है कि यहाँ नाक पर वेन है - आपका नवीनतम संपादन इस बारे में पूछता है init- जिसका उत्तर हो सकता है ... हो सकता है? यह इस बात पर निर्भर करता है कि आप कैसे / क्या बात करते हैं, क्या initउपयोग करते हैं और डेटा चैनल कहां हैं। सामान्य तौर पर वह सामान अपने आप काम करना शुरू कर देगा - यही वह initहै जिसके लिए है। किसी भी मामले में, आमतौर पर जब आप एक प्रक्रिया को समाप्त करते हैं init। या यदि आप नौकरी पर नियंत्रण चाहते हैं, तो वर्तमान शेल।
mikeserv

हाहा, चीयर्स @mikeserv; यहाँ सुबह 4:37 बजे और पहले दिन की पहली हंसी। सच है, वह सामान हमेशा किसी न किसी तरह काम करता है। मैं हटाऊंगा dmenuऔर देखूंगा कि मैंने जो कुछ भी सीखा, उसके साथ कैसे मिला। मुझे लगता है exec /path/to/Program & exitया /bin/bash -c /path/to/Program & exitकाफी प्रयोग करने योग्य है। लेकिन वे सभी बनाते हैं 1अर्थात जब तक मेरे initमाता-पिता Programठीक हैं, जब तक यह समझ में आता है और किसी भी मूल *nixसिद्धांतों का उल्लंघन नहीं करता है ।
lord.garbage

@ lord.gar कचरा - ऐसा इसलिए है क्योंकि आप exec &, मुझे लगता है। मैं आमतौर पर टर्मिनल से अपना सामान लेती हूं ... शायद आपको बेन क्राउल के सवाल से कुछ फायदा होगा । मेरे पास वहां एक उत्तर है, लेकिन वे सभी बहुत अच्छे हैं। वैसे भी, जब आप एक प्रक्रिया की पृष्ठभूमि बनाते हैं और उसके माता-पिता की मृत्यु हो जाती है, जैसे: sh -c 'cat & kill $$'आप इसे अनाथ कर देते हैं, और यह अंततः समाप्त हो जाता है। यह init का काम है - यही कारण है कि वे सभी इसके लिए आते हैं।
mikeserv

हो सकता है कि अब के लिए एक सरल प्रश्न यह है: शेल से उपरोक्त प्रक्रिया पेड़ प्राप्त करना कैसे संभव है systemd--bash--chromium:। सभी तरीके जो मैं कोशिश करता हूं, अंत systemd--chromiumमें शेल से फ़ायरफ़ॉक्स को छिड़कते समय निम्नलिखित रूप के एक प्रक्रिया वृक्ष का नेतृत्व करेंगे । यहाँ शैल को किस तरह से चित्रित किया गया है? यह किसी भी टर्मिनल से संबद्ध नहीं है।
lord.garbage 13

जवाबों:


7

ठीक है, आपको इसकी अच्छी समझ है। आपके पास जो कुछ है, उसे स्पष्ट करने के लिए,

  • sh -c /path/to/Program के समान है

    $  
    % / पथ / से / कार्यक्रम 
    % Ctrl+ D                             (या आप " निकास " टाइप कर सकते हैं ) 
    $

    जहाँ आप एक नई शेल प्रक्रिया शुरू करते हैं, नए शेल में एप्लिकेशन कमांड पथ प्रदान करते हैं, और फिर नए शेल को समाप्त करते हैं। मैंने दृष्टांत प्रयोजनों के लिए एक अलग संकेत देने वाला नया खोल दिखाया है; यह शायद वास्तविक जीवन में नहीं होगा। इसलिए वे एक भी आदेश (एक बार प्रयोग करने अनाम स्क्रिप्ट की तरह) की तरह लग रहे निर्माण, ज्यादातर एक बंडल में कई आदेशों लपेटकर की तरह मुश्किल सामान कर रही है, के लिए उपयोगी है, या खोल चर से संभवतः जटिल आदेशों भवन,। आप शायद ही कभी इसे केवल एक प्रोग्राम को सरल तर्क (नों) के साथ चलाने के लिए उपयोग करेंगे।sh -c "command"

  • 2>&1मानक मानक के लिए मानक त्रुटि को पुनर्निर्देशित करता है। यह वास्तव में बहुत कुछ नहीं करता है &; इसके बजाय, आप इसका उपयोग तब करते हैं जब कोई कमांड स्क्रीन पर त्रुटि संदेश भेजता है, भले ही आप कहें और आप फ़ाइल में त्रुटि संदेशों को कैप्चर करना चाहते हैं।command > file
  • आउटपुट को पुनर्निर्देशित करना nohup.outएक तुच्छ पक्ष-प्रभाव है nohup। के प्राथमिक उद्देश्य को चलाने के लिए है एसिंक्रोनस रूप से (आमतौर पर के रूप में जाना "पृष्ठभूमि में", या के रूप में एक "स्वतंत्र प्रक्रिया खोल", अपने शब्दों को उपयोग करने के लिए) और कॉन्फ़िगर यह अगर आप को चलाने के लिए जारी रखने के लिए तो यह सक्षम होने का एक बेहतर मौका है कमांड चालू होने के दौरान शेल (जैसे, लॉगआउट) को समाप्त करें।nohup command &command

bash(1)और बैश संदर्भ मैनुअल सूचना के अच्छे स्रोत हैं।


7

किसी प्रोग्राम को निष्पादित करने और टर्मिनल से अलग करने के कुछ तरीके हैं। एक इसे एक उपखंड की पृष्ठभूमि में चलाने के लिए है , इस तरह ( firefoxअपने पसंदीदा कार्यक्रम के साथ बदलें ):

(firefox &)

एक और प्रक्रिया को भंग करना है:

firefox & disown firefox

आप के बारे में कैसे एप्लिकेशन लांचर काम, उत्सुक हैं dmenu: 1 द्विआधारी प्रदान करता है और 2 शेल स्क्रिप्ट dmenu, dmenu_pathऔर dmenu_runक्रमश:।

dmenu_rundmenu_pathdmenu के आउटपुट को पाइप करता है , जो बदले में आपके $SHELLवैरिएबल पर जो कुछ भी सेट होता है। यदि यह खाली है, तो यह उपयोग करेगा /bin/sh

#!/bin/sh
dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &

dmenu_pathथोड़ा अधिक जटिल है, लेकिन संक्षेप में यह आपके $PATHपर्यावरण चर में बायनेरिज़ की सूची प्रदान करता है , और यदि संभव हो तो कैश का उपयोग करता है।

#!/bin/sh
cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
if [ -d "$cachedir" ]; then
        cache=$cachedir/dmenu_run
else
        cache=$HOME/.dmenu_cache # if no xdg dir, fall back to dotfile in ~
fi
IFS=:
if stest -dqr -n "$cache" $PATH; then
        stest -flx $PATH | sort -u | tee "$cache"
else
        cat "$cache"
fi

यह गोले में चल रहे कार्यक्रमों के लिए आवश्यक नहीं है। dmenu_runएक शेल में पाइपिंग के बिना लिखने का दूसरा तरीका होगा:

#!/bin/sh
$(dmenu_path | dmenu "$@") &

6

मुझे जी-मैन का जवाब बहुत पसंद है। लेकिन मैं जवाब दे रहा हूं क्योंकि मुझे लगता है कि आप चिंताओं को भ्रमित कर रहे हैं। जैसा कि वेन बताते हैं, सबसे अच्छा जवाब "जो भी परिणाम आप चाहते हैं वह प्राप्त होता है"।

यूनिक्स प्रक्रिया प्रबंधन में, प्रत्येक प्रक्रिया में एक अभिभावक होता है। इसका एक अपवाद वह initप्रक्रिया है जो बूट पर OS द्वारा शुरू की जाती है। माता-पिता की प्रक्रिया के लिए यह सामान्य व्यवहार है कि जब वह मर जाता है तो उसके साथ बच्चे की सभी प्रक्रियाएं करें। यह सभी चाइल्ड प्रोसेस को SITEUP सिग्नल भेजकर किया जाता है; SIGHUP की डिफ़ॉल्ट हैंडलिंग प्रक्रिया को समाप्त कर देती है।

यदि आप अपनी पसंद की भाषा में कांटा (2) / निष्पादन (3) कॉल को कोडित करते हैं, तो उपयोगकर्ता प्रक्रियाओं की शेल स्पैनिंग अलग नहीं है। शेल आपके माता-पिता हैं, और यदि शेल समाप्त हो जाता है (उदाहरण के लिए, आप लॉग ऑफ करते हैं), तो बच्चे की प्रक्रिया (एस) यह spawns इसके साथ जाती है। आपके द्वारा वर्णित बारीकियां उस व्यवहार को संशोधित करने के सिर्फ तरीके हैं।

exec /path/to/programकॉल निष्पादन (3) की तरह है । हां, यह आपके शेल की जगह ले लेगा program, जो भी माता-पिता ने शेल लॉन्च किया है।

sh -c /path/to/programइस तरह के व्यर्थ में एक बच्चे के खोल प्रक्रिया है कि एक बच्चे की प्रक्रिया का निर्माण करेगा program। यह केवल मूल्यवान है यदि /path/to/programवास्तव में स्क्रिप्ट निर्देशों का अनुक्रम है, और निष्पादन योग्य फ़ाइल नहीं है। ( sh /path/to/script.shएक शेल स्क्रिप्ट को चलाने के लिए इस्तेमाल किया जा सकता है जिसमें एक अवर शेल में निष्पादन अनुमतियों का अभाव है)

/path/to/programएक "अग्रभूमि" प्रक्रिया बनाता है, जिसका अर्थ है कि शेल किसी अन्य कार्रवाई करने से पहले प्रक्रिया पूरी होने का इंतजार करता है। सिस्टम कॉल के संदर्भ में, यह कांटा (2) / निष्पादन (3) / वेटपिड (2) की तरह है । ध्यान दें कि बच्चे को माता-पिता से stdin / stdout / stderr विरासत में मिली है।

/path/to/program &(अनदेखी पुनर्निर्देशन) एक "पृष्ठभूमि प्रक्रिया" बनाता है। प्रक्रिया अभी भी शेल का एक बच्चा है, लेकिन माता-पिता इसे समाप्त करने के लिए इंतजार नहीं कर रहे हैं।

nohup /path/to/programनियंत्रित टर्मिनल बंद होने पर SITEUP भेजने से रोकने के लिए nohup (1) को आमंत्रित करता programहै। चाहे वह अग्रभूमि में हो या पृष्ठभूमि एक विकल्प है (हालांकि सबसे अधिक प्रक्रिया पृष्ठभूमि में है)। ध्यान दें कि nohup.outकेवल आउटपुट है यदि आप अन्यथा stdout रीडायरेक्ट नहीं करते हैं।

जब आप पृष्ठभूमि में एक प्रक्रिया डालते हैं, अगर मूल प्रक्रिया मर जाती है, तो दो चीजों में से एक होती है। यदि अभिभावक एक नियंत्रित टर्मिनल है , तो बच्चों को SITEUP भेजा जाएगा। यदि यह नहीं है, तो प्रक्रिया "अनाथ" हो सकती है, और initप्रक्रिया द्वारा विरासत में मिली है ।

जब आप इनपुट / आउटपुट / एरर को रिडायरेक्ट करते हैं, तो आप बस फाइल डिस्क्रिप्टर को कनेक्ट कर रहे होते हैं, जो कि हर प्रक्रिया को अपने माता-पिता से विरासत में मिली फाइलों से अलग होती है। इसमें से कोई भी प्रक्रिया स्वामित्व या वृक्ष की गहराई को प्रभावित नहीं करता है (लेकिन यह हमेशा पृष्ठभूमि प्रक्रियाओं के लिए एक टर्मिनल से 3 दूर सभी को पुनर्निर्देशित करने के लिए समझ में आता है)।

कहा कि सब के साथ, मुझे नहीं लगता कि आपको शेल या उप-शेल या उप-प्रक्रियाओं द्वारा प्रक्रिया निर्माण से संबंधित होना चाहिए, जब तक कि एक विशिष्ट समस्या नहीं है जो आप प्रक्रिया प्रबंधन से संबंधित संबोधित कर रहे हैं।


नाइटपिक: sh -c /path/to/programशेल स्क्रिप्ट के रूप में प्रोग्राम नहीं चलेगा यदि यह निष्पादन योग्य बिट्स, sh /path/to/programविल को याद कर रहा है । sh -c /path/to/programकेवल एक शेल खोलेंगे और /path/to/programउस शेल में एक कमांड के रूप में चलाएंगे , जो असफल होगा यदि यह निष्पादन योग्य नहीं है।
फाइलब्रांडेन

ठीक है, अगर हम नाइटपैकिंग कर रहे हैं, तो हम दोनों गलत हैं। शेल sh -c /path/to/programसे /path/to/programइनपुट के रूप में कमांड पढ़ता है । इसकी आवश्यकता नहीं है कि फ़ाइल ने अनुमति निष्पादित की है, लेकिन यह एक शेल स्क्रिप्ट होनी चाहिए
jwm

हम्म, sh /path/to/programवह करता है। बस खुद की कोशिश की: echo echo hello world >abc.shतो, sh ./abc.shप्रिंट hello world, जबकि sh -c ./abc.shकहते हैं sh: ./abc.sh: Permission denied(जो एक ही है जैसे कि आप ./abc.shवर्तमान शेल में सीधे चलेंगे ।) क्या मुझे कुछ याद आया? (या शायद मैं खुद को पिछली टिप्पणी में अच्छी तरह से व्यक्त नहीं किया था ...)
filbranden

मेरी गलती। sh -c _something_केवल _something_कमांड प्रॉम्प्ट पर टाइप करने के रूप में ही है , अवर खोल के spawning को छोड़कर। तो आप सही हैं कि यह निष्पादित बिट (फ़ाइल के रूप में) गुम होने पर विफल हो जाएगा। दूसरी ओर, आप शेल कमांड की एक श्रृंखला प्रदान कर सकते हैं जैसे sh -c "echo hello world"और यह ठीक काम करेगा। इसलिए यह आवश्यक नहीं है कि आपके पास जो टाइप है वह निष्पादित बिट (या यहां तक ​​कि एक फ़ाइल) हो, केवल शेल दुभाषिया इसके साथ कुछ कर सकता है।
jwm

मेरा मानना ​​है कि ओपी कुछ संकलित या सिस्टम निष्पादन योग्य की बात कर रहा था, इसलिए निष्पादन की अनुमति मान ली गई थी।
jwm
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.