परिचय: टर्मिनल के पर्दे के पीछे क्या होता है?
जब भी हम लिनक्स टर्मिनल में कोई कमांड टाइप करके Enter दबाते हैं, तो ऑपरेटिंग सिस्टम के भीतर कई सूक्ष्म प्रक्रियाएं एक साथ सक्रिय हो जाती हैं। इस लेख में हम Bash शेल के उसी बुनियादी तंत्र की पड़ताल करेंगे। कमांड की खोज और पहचान से लेकर प्रोसेस निर्माण (Fork & Exec), I/O रीडायरेक्शन और सबशेल के व्यवहार को वास्तविक टर्मिनल उदाहरणों के जरिए सरल शब्दों में समझाया गया है।
1. कमांड की पहचान और खोज प्रक्रिया (Alias, Builtin और PATH)
किसी भी निर्देश को निष्पादित करने से पहले शेल यह पता लगाता है कि वह निर्देश किस श्रेणी का है। इसके लिए type कमांड का उपयोग किया जाता है, जो यह स्पष्ट करता है कि संबंधित कमांड शेल का आंतरिक हिस्सा (shell builtin) है, कोई एलियास (alias) है, शेल फ़ंक्शन है अथवा डिस्क पर मौजूद कोई बाहरी बाइनरी फ़ाइल है।
उदाहरण के लिए, cd पर इसे चलाने से तुरंत स्पष्ट हो जाता है कि यह कोई अलग निष्पादन योग्य फ़ाइल नहीं बल्कि शेल का इन-बिल्ट कमांड है।
⚙️ [महत्वपूर्ण विकल्प]
-t : केवल कमांड की प्रकृति (builtin, alias, file, keyword, function) को एकल शब्द में प्रदर्शित करता है।-a : उस नाम से जुड़े सभी संभावित निष्पादन योग्य रूपों (एलियास, बिल्ट-इन या पाथ में मौजूद फ़ाइलें) की पूरी सूची प्रस्तुत करता है।-p : यदि कमांड कोई बाहरी डिस्क फ़ाइल है, तो केवल उसका पूर्ण पथ (path) दिखाता है।

अब type के जरिए ls की पड़ताल करते हैं।
परिणाम से साफ दिखता है कि ls कोई आंतरिक बिल्ट-इन कमांड नहीं है, बल्कि फाइलसिस्टम में /usr/bin/ls स्थान पर रखी एक स्वतंत्र बाइनरी निष्पादन फ़ाइल है।

जब किसी बाइनरी फ़ाइल को रन करना होता है, तो which कमांड पर्यावरण चर PATH में सूचीबद्ध डायरेक्टरीज़ को स्कैन करके उस फ़ाइल की वास्तविक लोकेशन ढूंढता है।
यदि हम ls के साथ इसे चलाएं, तो यह हमें /usr/bin/ls का संपूर्ण एब्सोल्यूट पाथ लौटाता है जिसे सिस्टम द्वारा निष्पादित किया जाता है।
⚙️ [महत्वपूर्ण विकल्प]
-a : खोज प्रक्रिया पहले परिणाम पर नहीं रुकती, बल्कि PATH में मौजूद सभी मेल खाने वाले पाथ सूचीबद्ध करती है।

शेल बाहरी प्रोग्रामों को कहां-कहां खोजता है, यह जानने के लिए echo $PATH से वर्तमान पाथ डायरेक्टरीज़ देखी जा सकती हैं।
कोलन (:) चिह्नों से अलग की गई इस डायरेक्टरी सूची को शेल हमेशा बाएं से दाएं क्रम में स्कैन करता है और पहला सही मिलान मिलते ही फ़ाइल रन कर देता है।

2. प्रोसेस निर्माण और निष्पादन: Fork और Exec कार्यप्रणाली
सिस्टम में चल रही प्रक्रियाओं के पदानुक्रम (Process Hierarchy) को ग्राफ़िकल रूप में देखने के लिए हम सबसे पहले psmisc पैकेज इंस्टॉल करते हैं, जिसमें pstree यूटिलिटी शामिल होती है।

वर्तमान शेल के प्रोसेस आईडी ($$) के साथ pstree -p $$ चलाने पर हमें उस शेल से जुड़े सभी चाइल्ड प्रोसेस का ट्री स्ट्रक्चर उनके PID सहित दिखाई देता है।
इससे स्पष्ट होता है कि मूल शेल (bash) ने कैसे एक नया चाइल्ड प्रोसेस उत्पन्न (Fork) करके pstree को निष्पादित किया।

bash -c 'sleep 2' & कमांड के जरिए हम एक सबशेल में sleep 2 को बैकग्राउंड (&) में शुरू करते हैं।
इस प्रक्रिया में मुख्य शेल तुरंत प्रतिक्रिया के लिए मुक्त हो जाता है, जबकि पृष्ठभूमि में एक नया असिंक्रोनस चाइल्ड प्रोसेस काम करने लगता है।

सिस्टम में सक्रिय स्लीप प्रक्रियाओं की जांच के लिए ps -ef | grep [s]leep का प्रयोग किया जाता है।
जैसे ही तय समय (2 सेकंड) पूरा होता है, प्रोसेस स्वतः समाप्त हो जाता है और फ़िल्टर किए गए परिणाम में कुछ भी दिखाई नहीं देता।

3. इनपुट-आउटपुट रीडायरेक्शन और पाइपलाइन का प्रवाह
रीडायरेक्शन और पाइप के व्यावहारिक परीक्षण के लिए हम mkdir -p /tmp/bash_demo && echo 'Hello Bash World' > /tmp/bash_demo/sample.txt चलाकर एक समर्पित डायरेक्टरी और अभ्यास फ़ाइल तैयार करते हैं।

निर्मित फ़ाइल की सामग्री को स्टैण्डर्ड आउटपुट (stdout) पर देखने के लिए cat /tmp/bash_demo/sample.txt रन करते हैं।
टर्मिनल पर Hello Bash World टेक्स्ट का प्रिंट होना यह दर्शाता है कि फ़ाइल में डेटा सही ढंग से सुरक्षित हो चुका है।

शेल द्वारा खुले फ़ाइल डिस्क्रिप्टर्स (File Descriptors) का मुआयना करने के लिए ls -l /proc/$$/fd का इस्तेमाल किया जाता है।
यहां स्पष्ट रूप से दिखता है कि स्टैण्डर्ड इनपुट (0), स्टैण्डर्ड आउटपुट (1), और स्टैण्डर्ड एरर (2) किस प्रकार प्रोसेस के साथ लिंक होकर डेटा प्रवाह को संभालते हैं।

cat /tmp/bash_demo/sample.txt | tr 'a-z' 'A-Z' कमांड में पाइप (|) का कमाल देखने को मिलता है, जहां cat का आउटपुट सीधे tr कमांड के इनपुट में भेज दिया जाता है।
नतीजतन, फ़ाइल का लोअरकेस टेक्स्ट तुरंत अपरकेस में बदलकर टर्मिनल स्क्रीन पर HELLO BASH WORLD के रूप में आउटपुट होता है।

4. पर्यावरण चर इनहेरिटेंस और सबशेल (Subshell) पृथक्करण
DEMO_LOCAL='LocalValue' कमांड केवल मौजूदा शेल सत्र तक सीमित एक स्थानीय वेरिएबल DEMO_LOCAL असाइन करता है।
यह वेरिएबल सिर्फ इसी सक्रिय शेल प्रक्रिया की मेमोरी में रहता है और किसी भी नए बनने वाले चाइल्ड प्रोसेस को ट्रांसफर नहीं होता।

इसके विपरीत, export DEMO_GLOBAL='GlobalValue' कमांड DEMO_GLOBAL को एक पर्यावरण चर (Environment Variable) बनाकर सिस्टम एनवायरनमेंट में जोड़ देता है।
इस प्रकार एक्सपोर्ट किया गया वेरिएबल मौजूदा शेल के साथ-साथ भविष्य में बनने वाले सभी चाइल्ड प्रोसेस में स्वतः इनहेरिट हो जाता है।

कोष्ठक () का उपयोग करके जब (echo "[서브셸] Local: $DEMO_LOCAL, Global: $DEMO_GLOBAL") चलाया जाता है, तो यह कमांड मौजूदा शेल की प्रतिलिपि बनाकर सबशेल में निष्पादित होता है।
चूंकि सबशेल पैरेंट प्रोसेस की मेमोरी का हूबहू क्लोन होता है, इसलिए यह बिना एक्सपोर्ट किए गए लोकल वेरिएबल और ग्लोबल वेरिएबल दोनों को आसानी से एक्सेस कर लेता है।

इसके विपरीत, bash -c 'echo "[자식셸] Local: $DEMO_LOCAL, Global: $DEMO_GLOBAL"' एक बिलकुल नया चाइल्ड शेल प्रोसेस आरंभ करता है।
इसके परिणाम में हम देख सकते हैं कि चाइल्ड शेल केवल एक्सपोर्ट किए गए ग्लोबल पर्यावरण चर को ही पढ़ पाता है, जबकि मूल शेल का लोकल वेरिएबल यहां पूरी तरह अनदेखा रह जाता है।

इस प्रकार हमने समझा कि लिनक्स Bash शेल किसी कमांड को स्वीकार करने के बाद आंतरिक स्तर पर किस तरह उसका विश्लेषण और निष्पादन करता है।
टर्मिनल के इस अंतर्निहित व्यवहार और लाइफसाइकिल को गहराई से जानकर आप अधिक मजबूत, त्रुटिहीन स्क्रिप्टिंग और बेहतर सिस्टम प्रबंधन कर सकेंगे।