शेल बिल्ड कमांड को समझना


12

में में बैश मैनुअल , यह है कि लिखा है

Builtin commands are contained >>> within <<< the shell itself

साथ ही, यह उत्तर बताता है कि

A built-in command is simply a command that the shell carries out itself,
instead of interpreting it as a request to load and run some
>>> other program <<<

जब मैं चलाने compgen -bपर bash 4.4, मैं आदेशों निर्मित सभी खोल की एक सूची प्राप्त करते हैं। मैं उदाहरण के लिए देखता हूं [और killशेल बिल्डिन होने के लिए सूचीबद्ध हैं। लेकिन उनके वास्तविक स्थान हैं:

/usr/bin/[
/bin/kill

मैंने सोचा था कि एक builtinसाधन होने के नाते कमांड को /bin/bashनिष्पादन योग्य में संकलित किया जाता है । तो क्या वास्तव में मुझे भ्रमित कर रहा है: कृपया मुझे सही करें, लेकिन एक अलग कमांड कैसे हो सकता है builtin, जब यह वास्तव में शेल का हिस्सा नहीं है?


1
कुछ आदेश मूल रूप से अलग-अलग उपयोगिताओं के रूप में मौजूद थे। उनकी उपस्थिति अब POSIX मानक अनुपालन, पोर्टेबिलिटी, साथ ही पीछे की संगतता के लिए है। शैल प्रदर्शन के लिए बनाए गए कुछ को कार्यान्वित करते हैं। कोई अन्य कारण हो सकता है, लेकिन इसके बारे में बहुत अधिक विस्तार के बिना।
सर्गी कोलोडियाज़नी

1
एक और कारण जो मैं सोच सकता था, वह यह है कि शेल के लिए कुछ अंतर्निहित कमांडों की विशेष रूप से जरूरत होती है, जैसे execफाइल डिस्क्रिप्टर में हेरफेर करना और eval कमांड के मूल्यांकन के लिए। उन्हें स्टैंडअलोन कमांड के रूप में ज़रूरत नहीं है
सर्जियो कोलोडियाज़नी

जवाबों:


16

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

चूंकि कुछ उपयोगिताओं को बनाने की आवश्यकता नहीं होती है, जब तक कि वे विशेष न हों, जैसे cd, उन्हें बाहरी उपयोगिताओं के रूप में भी प्रदान किया जाता है । ऐसा इसलिए है कि यदि स्क्रिप्ट को एक शेल द्वारा व्याख्यायित नहीं किया जाता है तो वे टूटेंगे नहीं जो एक बिलकुल समान नहीं है।

कुछ शेल के बिल्ट-इन बाहरी समतुल्य कमांड को एक्सटेंशन भी प्रदान करते हैं। printfउदाहरण के लिए बैश , करने में सक्षम है

$ printf -v message 'Hello %s' "world"
$ echo "$message"
Hello world

(एक वैरिएबल पर प्रिंट करें) जो बाहरी /usr/bin/printfरूप से करने में सक्षम नहीं होगा क्योंकि वर्तमान शेल सत्र में शेल चरों की पहुंच नहीं है (और उन्हें बदल नहीं सकते हैं)।

उपयोगिताओं में निर्मित यह भी प्रतिबंध नहीं है कि उनकी विस्तारित कमांड लाइन को एक निश्चित लंबाई से कम होना है। करते हुए

printf '%s\n' *

इसलिए सुरक्षित है यदि printfएक शेल अंतर्निहित कमांड है। कमांड लाइन की लंबाई पर प्रतिबंध execve()एक बाहरी कमांड को निष्पादित करने के लिए उपयोग किए जाने वाले सी लाइब्रेरी फ़ंक्शन से आता है । यदि कमांड लाइन और वर्तमान वातावरण ARG_MAXबाइट्स ( getconf ARG_MAXशेल में देखें ) से बड़ा है , तो कॉल execve()विफल हो जाएगी। यदि उपयोगिता शेल में निर्मित होती है, execve()तो कॉल नहीं किया जाता है।

यूटिलिटीज में निर्मित यूटिलिटीज में पाई जाने वाली उपयोगिताओं पर पूर्ववर्ती स्थिति लेती हैं $PATH। अंतर्निहित कमांड को अक्षम करने के लिए bash, उदाहरण के लिए उपयोग करें

enable -n printf

उपयोगिताओं की एक छोटी सूची है जिसे एक शेल में निर्मित करने की आवश्यकता है ( विशेष अंतर्निहित इन्स के POSIX मानक की सूची से लिया गया )

break
colon (:)
continue
dot (.)
eval
exec
exit
export
readonly
return
set
shift
times
trap
unset

इन्हें बनाने की आवश्यकता है क्योंकि वे वर्तमान शेल सत्र के पर्यावरण और कार्यक्रम प्रवाह को सीधे जोड़ते हैं। एक बाहरी उपयोगिता ऐसा करने में सक्षम नहीं होगी।

दिलचस्प बात cdयह है कि इस सूची का हिस्सा नहीं है, लेकिन POSIX निम्नलिखित के बारे में कहता है:

चूंकि cdमौजूदा शेल निष्पादन पर्यावरण को प्रभावित करता है, इसलिए इसे हमेशा शेल रेगुलर बिल्ट-इन के रूप में प्रदान किया जाता है। यदि इसे एक सबहेल या अलग उपयोगिता निष्पादन पर्यावरण में कहा जाता है, जैसे कि निम्न में से एक:

(cd /tmp)
nohup cd
find . -exec cd {} \;

यह कॉलर के वातावरण की कार्यशील निर्देशिका को प्रभावित नहीं करता है।

इसलिए मैं मान रहा हूं कि "विशेष" बिल्ट-इन में बाहरी समकक्ष नहीं हो सकते, जबकि cdसिद्धांत में यह हो सकता है (लेकिन यह बहुत ज्यादा नहीं होगा)।


IIRC, chdir/ cdबहुत प्रारंभिक यूनियनों में बाहरी बायनेरिज़ थे / प्री-यूनिक्स forkशुरू होने से पहले ।
Xophmeister

@Xophmeister Solaris 11.4 (बीटा) अभी भी है /usr/bin/cd, लेकिन यह वास्तव में वर्तमान कार्यशील निर्देशिका को नहीं बदलेगा। इसका मैनुअल कहता है: /usr/bin/cdआह्वान करने की प्रक्रिया पर कोई प्रभाव नहीं पड़ता है, लेकिन यह निर्धारित करने के लिए इस्तेमाल किया जा सकता है कि किसी दिए गए निर्देशिका को वर्तमान निर्देशिका के रूप में सेट किया जा सकता है या नहीं।
Kusalananda

2
बिल्डिंस के लिए एक और, बल्कि विशिष्ट कारण: बिल्डिन killभी अच्छा है क्योंकि आपको किसी अन्य प्रक्रिया को कांटा करने की आवश्यकता नहीं है, अच्छा है यदि आपने अपनी प्रक्रियाओं की संख्या को मारा है।
derobert

7

आप (बहुत जाहिर है) तथ्य यह है कि कुछ builtins मौजूद से उलझन में कर रहे हैं दोनों builtins के रूप में और बाहरी आदेशों के रूप में। इसलिए, जब आप सही होते हैं, उदाहरण के लिए, एक /bin/[कमांड है, तो इसका मतलब यह नहीं है कि इसका "वास्तविक स्थान" है /bin

इसका परीक्षण करने का कोई भी आसान तरीका स्विच के typeसाथ चलना है -aजो एक कमांड के सभी उपलब्ध उदाहरणों को दिखाएगा। मेरे आर्क सिस्टम पर, जो दिखाता है:

$ type -a [
[ is a shell builtin
[ is /sbin/[
[ is /usr/sbin/[
[ is /usr/bin/[

ध्यान दें कि /sbin, /usr/sbinऔर /binसभी सिम्बलिंक इंगित कर रहे हैं /usr/bin, इसलिए केवल एक बाहरी है [:

$ readlink -f /usr/sbin /sbin /bin/
/usr/bin
/usr/bin
/usr/bin

जैसा कि आप देख सकते हैं, [दोनों एक बिलिन और एक बाहरी कमांड है, और वही अन्य अन्य शेल बिल्डरों के बारे में सच है। हालांकि, यह इस तथ्य को नहीं बदलता है कि वे शेल बिल्ड भी हैं, शेल में ही संकलित हैं।


क्यों व्याकुल पहले से मौजूद आंतरिक कमांड के लिए अलग बाहरी कमांड प्रदान करें? वे नकल क्यों करते हैं?
लवविथमैथ्स

1
@linuxuser POSIX द्वारा इन उपयोगिताओं में से कुछ की आवश्यकता होती है, और आप यह नहीं जान सकते हैं कि उपयोगकर्ता द्वारा उपयोग किया जा रहा शेल क्या बिल्डिन प्रदान करेगा। ओएस के आंतरिक कमांड के रूप में उनके बारे में मत सोचो, वे केवल शेल के आंतरिक कमांड हैं, और शेल बदल सकता है।
terdon

मुझे अब 1 संदेह है, अगर आंतरिक आदेश शेल द्वारा प्रदान किए जाते हैं; फिर बाहरी आदेश कौन प्रदान करता है? जैसे मैंने कई आदेशों को देखा है जो आंतरिक और साथ ही बाहरी कमांड के रूप में उपलब्ध हैं, लेकिन मैंने उन्हें स्पष्ट रूप से स्थापित किया है; तो बाहरी आदेश कौन प्रदान करता है? डिस्ट्रो उन्हें सही प्रदान करता है?
लवविथमैथ्स

@linuxuser कमांड और ऑपरेटिंग सिस्टम पर निर्भर करता है। उदाहरण के लिए, मेरे आर्क लिनक्स पर, पैकेज और द्वारा /bin/printfस्थापित किया गया है । coreutils/bin/killutil-linux
terdon

मुझे खेद है, लेकिन मैं अभी भी स्पष्ट नहीं हूं कि उपरोक्त में से कौन डिस्ट्रो द्वारा प्रदान किया गया है? और दूसरे के बारे में क्या है जो डिस्ट्रो द्वारा प्रदान नहीं किया गया है तो कौन इसे प्रदान करता है।
लवविथमैथ्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.