Bashrc में [-n "$ PS1"] का उद्देश्य


जवाबों:


20

यह जाँच कर रहा है कि शैल संवादात्मक है या नहीं। इस मामले में, केवल ~/.bash_profileफ़ाइल को सोर्स करना यदि शेल इंटरेक्टिव है।

देखें "क्या यह शेल इंटरएक्टिव है?" बैश मैनुअल में, जो उस विशिष्ट मुहावरे का हवाला देता है। (यह जाँचने की भी सिफारिश करता है कि क्या शेल परीक्षण द्वारा इंटरेक्टिव है कि क्या $-विशेष चर में iचरित्र है, जो इस समस्या के लिए एक बेहतर दृष्टिकोण है।)


बैश, कम से कम, पीएस 1 और पीएस 2 को खोल देगा यदि शेल इंटरैक्टिव है । आप इसे अपने लिए देख सकते हैं ( export PS1='abc$ '; bash -c 'echo "[$PS1]"' ), जो केवल प्रिंट करता है []। ऐसा लगता है कि zsh ऐसा नहीं करता है, कम से कम एक प्रयोग से ... किसी भी मामले में, यह जाँचने का इरादा है [ -n "$PS1" ]कि शेल संवादात्मक है या नहीं।
फिल्मब्रांडेन

3
यही कारण है कि bashunsets PS1 जब गैर-सहभागी (आपके पिछले टिप्पणी में टाइपो) एक बग IMO है, PS1, एक पार्टी विशेष के चर नहीं है, यह कोई व्यवसाय यह unsetting है। यह एकमात्र शेल है जो ऐसा करता है (हालांकि गैर-संवादात्मक होने पर भी डिफ़ॉल्ट मान पर yashसेट PS1होता है)।
स्टीफन चेजलस

1
चूंकि प्रश्न में कोड एक बैश-विशिष्ट फ़ाइल में है, इसलिए यह एक उचित उत्तर की तरह लगता है। अन्य उत्तर POSIX चश्मा या अन्य गोले के अधिक सामान्य मामले को संबोधित करते हैं। आपने उत्तर दिया "इसका उद्देश्य क्या है?" शेष भाग को उचित रूप से छोड़ते हुए प्रश्न में इरादा। यह जानना अच्छा है कि बैश क्या कर रहा है और संभवतः लक्ष्य को पूरा करने के बेहतर तरीके भी।
जेफ स्कालर

यदि यह अधिक विश्वसनीय विकल्प (कहना, [[ $- = *i* ]] && source ~/.bash_profile) का सुझाव देता है तो मैं इस उत्तर पर और अधिक पूर्ण विचार करूंगा ।
चार्ल्स डफी

@CharlesDuffy स्पष्ट रूप से मुझे नहीं लगता कि इसमें बहुत गलत है [ -n "${PS1}" ], लेकिन मैंने अभी भी अपने उत्तर को उजागर करने के लिए अद्यतन किया है कि बैश मैनुअल भी यह $-निर्धारित करने के लिए निरीक्षण / अनुशंसा करता है कि क्या शेल इंटरैक्टिव है, मुझे उम्मीद है कि आप पाएंगे कि उत्तर में सुधार होगा। चीयर्स!
filbranden

19

यह क्या करता है

यह परीक्षण का एक व्यापक तरीका है कि क्या खोल इंटरैक्टिव है। खबरदार कि यह केवल बाश में काम करता है, यह अन्य गोले के साथ काम नहीं करता है। तो यह ठीक है (यदि मूर्खतापूर्ण) के लिए .bashrc, लेकिन यह काम नहीं करेगा .profile(जो कि श द्वारा पढ़ा जाता है, और बैश केवल श के संभावित कार्यान्वयन में से एक है, और सबसे आम नहीं है)।

क्यों यह काम करता है (केवल बकवास में!)

एक इंटरैक्टिव शेल डिफ़ॉल्ट प्रॉम्प्ट स्ट्रिंग के लिए शेल चरPS1 सेट करता है । इसलिए यदि शेल संवादात्मक है, PS1तो सेट किया जाता है (जब तक कि उपयोगकर्ता .bashrcने इसे हटा नहीं दिया है, जो अभी तक शीर्ष पर नहीं हुआ है .bashrc, और आप विचार कर सकते हैं कि यह वैसे भी एक मूर्खतापूर्ण बात है)।

यह बैश में सच है: बैश के गैर-संवादात्मक उदाहरण परेशान होते हैं PS1जब वे शुरू होते हैं। ध्यान दें कि यह व्यवहार बैश के लिए विशिष्ट है, और यकीनन एक बग (क्यों होता है bash -c '… do stuff with $var…'जब काम नहीं varहै PS1?)। लेकिन 4.4 (और जैसा कि मैं लिखता हूं, नवीनतम संस्करण) बैश के सभी संस्करण ऐसा करते हैं।

कई सिस्टम PS1पर्यावरण को निर्यात करते हैं। यह एक बुरा विचार है, क्योंकि कई अलग-अलग गोले का उपयोग करते हैं PS1लेकिन एक अलग वाक्यविन्यास के साथ (जैसे बश की त्वरित बचना , ज़ीश के शीघ्र भागने से पूरी तरह से अलग है )। लेकिन यह व्यापक रूप से पर्याप्त है कि व्यवहार में, यह देखते हुए कि PS1एक विश्वसनीय संकेतक नहीं है कि शेल इंटरैक्टिव है। शेल PS1पर्यावरण से विरासत में मिला हो सकता है ।

यहाँ क्यों (मिस) इसका इस्तेमाल किया गया

.bashrcवह फ़ाइल है जो बैश स्टार्टअप में पढ़ता है जब यह इंटरैक्टिव है। एक कम प्रसिद्ध तथ्य यह है कि बैश भी पढ़ता .bashrcहै एक लॉगिन शेल है और बैश के उत्तराधिकारियों का निष्कर्ष है कि यह एक दूरस्थ सत्र है (बैश की जांच करता है कि क्या उसके माता-पिता हैं rshdया नहीं sshd)। इस दूसरे मामले में, यह संभावना नहीं है कि PS1पर्यावरण में सेट किया जाएगा, क्योंकि अभी तक कोई डॉट फ़ाइल नहीं चली है।

हालाँकि, कोड इस जानकारी का उपयोग करने का तरीका उल्टा है।

  • यदि शेल एक इंटरैक्टिव शेल है, तो यह .bash_profileउस शेल में चलता है। लेकिन .bash_profileएक लॉगिन-टाइम स्क्रिप्ट है। यह कुछ कार्यक्रम चला सकता है जो प्रति सत्र केवल एक बार चलाने का इरादा रखते हैं। यह कुछ पर्यावरण चर को ओवरराइड कर सकता है जो उपयोगकर्ता ने उस शेल को चलाने से पहले जानबूझकर एक अलग मूल्य पर सेट किया था। .bash_profileएक गैर-लॉगिन शेल में चलना विघटनकारी है।
  • यदि शेल एक गैर-संवादात्मक दूरस्थ लॉगिन शेल है, तो यह लोड नहीं होगा .bash_profile। लेकिन यह ऐसा मामला है जहां लोड .bash_profileकरना उपयोगी हो सकता है, क्योंकि एक गैर-संवादात्मक लॉगिन शेल स्वचालित रूप से लोड नहीं होता है /etc/profileऔर ~/.profile

मुझे लगता है कि लोग ऐसा करने का कारण उन उपयोगकर्ताओं के लिए हैं जो GUI (एक बहुत ही सामान्य मामला) के माध्यम से लॉग इन करते हैं और जिन्होंने .bash_profileइसके बजाय अपने पर्यावरण चर सेटिंग्स को रखा है .profile। अधिकांश GUI लॉगिन तंत्र आह्वान करते हैं .profileलेकिन नहीं .bash_profile(पढ़ने .bash_profileके लिए सत्र स्टार्टअप के भाग के रूप में b के बजाय bash चलाने की आवश्यकता होगी)। इस कॉन्फ़िगरेशन के साथ, जब उपयोगकर्ता एक टर्मिनल खोलता है, तो वे अपने पर्यावरण चर प्राप्त करेंगे। हालांकि, उपयोगकर्ता को GUI अनुप्रयोगों में अपने पर्यावरण चर नहीं मिलेंगे, जो भ्रम का एक बहुत ही सामान्य स्रोत है। यहाँ समाधान का उपयोग पर्यावरण चर सेट करने के .profileबजाय .bash_profileकरना है। के बीच एक पुल जोड़ना .bashrcऔर इससे .bash_profileअधिक समस्याएं पैदा करता है।

इसके बजाय क्या करना है

परीक्षण का एक सीधा, पोर्टेबल तरीका है कि क्या वर्तमान शेल इंटरेक्टिव है: परीक्षण कि क्या विकल्प -iसक्षम है।

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This shell is not interactive";;
esac

यह केवल पढ़ने के.bashrc लिए उपयोगी है यदि शेल गैर-संवादात्मक है - अर्थात कोड क्या करता है इसके विपरीत! पढ़ें कि क्या बैश एक (गैर-संवादात्मक) लॉगिन शेल है, और यदि यह एक इंटरैक्टिव शेल है तो इसे न पढ़ें।.profile.profile

if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi

4
ध्यान देने योग्य बात यह हो सकती है कि यदि शेल इंटरएक्टिव है [[ -o interactive ]](ksh, bash, zsh) या case $- in (*i*) ...; esac(POSIX)
Stéphane Chazelas

2
मेरे बैश (संस्करण 4.4.12) वास्तव में परेशान करने के लिए लगता है PS1अगर अंतःक्रियात्मक रूप से नहीं चलाया जाता है। यह परीक्षण करना काफी आसान है: PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'कुछ भी प्रिंट नहीं करेगा, जबकि आपकी बैश स्टार्टअप फाइलों में सेट PS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'के मूल्य को प्रिंट करता है $PS1(यह स्ट्रिंग "कोयल" प्रिंट नहीं करेगा)।
FooF

1
@ स्टीफन Chazelas: POSIX की आवश्यकता नहीं है कि $-होता है iएक इंटरैक्टिव खोल के साथ।
स्किल

1
Bosh यह 2012 से ksh के संगत होने के लिए करता है। यह सिर्फ पॉसिंक द्वारा आवश्यक नहीं था जब तक कि आप बदलाव को प्रभावी नहीं बनाते।
स्किल

1
सच कहूँ तो, मैं कहूँगा कि [ -n "${PS1}" ] गलत कॉलिंग बहुत दूर जा रही है, आखिरकार यह केवल तब टूटता है जब कोई PS1 को निर्यात कर रहा है (जो आपके उत्तर में कहता है कि यह एक बुरा विचार है और यहां तक ​​कि इसके कारणों में जाते हैं) और यह प्रभावित नहीं करता है वैसे भी बैश करें (क्योंकि यह PS1 और PS2 को खोल देता है यदि शेल गैर-संवादात्मक है।) शायद "हतोत्साहित" जैसे शब्द का उपयोग करना या दृष्टिकोण की "सीमाओं" के बारे में बात करना बेहतर होता। मुझे नहीं लगता कि यह "गलत" है। अगर कुछ भी गलत है PS1 निर्यात कर रहा है, तो यह सुनिश्चित है! वैसे भी, इस के विवरण में जाने के लिए धन्यवाद।
फाइलब्रांडेन

1

ऐसा लगता है कि यह अजीब अवधारणा इस तथ्य का परिणाम है कि bashएक पॉसिक्स शेल क्लोन के रूप में शुरू नहीं हुई थी, लेकिन एक Bourne Shellक्लोन के रूप में ।

नतीजतन, POSIX इंटरैक्टिव व्यवहार ( $ENVइंटरेक्टिव गोले के लिए बुलाया जाता है) को बाद में जोड़ा गया है bashऔर व्यापक रूप से ज्ञात नहीं है।

एक शेल है जो समान व्यवहार को अनुदान देता है। यह cshऔर $promptविशिष्ट मूल्य वाले csh अनुदान हैं:

$prompt not set          non-interactive shell, test $?prompt.
$prompt set but == ""    .cshrc called by the which(1) command.
$prompt set and != ""    normal interactive shell.

लेकिन यह न तो बॉर्न शेल पर लागू होता है और न ही पोसिक्स शेल पर।

POSIX शेल के लिए, फ़ाइल में इंटरैक्टिव गोले के लिए कोड डालना एकमात्र तरीका है:

$ENV

इसका एक शेल विशिष्ट नाम है। यह उदा

$HOME/.kshrc    for the korn shell
$HOME/.bashrc   for bash
$HOME/.mkshrc   for mksh
$HOME/.shrc     for the POSIX Bourne Shell

अन्य लोगों ने शेल ध्वज का उल्लेख किया -i, लेकिन यह विश्वसनीय प्रोग्रामिंग के लिए उपयोग करने योग्य नहीं है। POSIX न कि आवश्यकता है set -iकाम करता है, और न ही है कि $-एक शामिल iइंटरैक्टिव गोले के लिए। POSIX के लिए केवल यह आवश्यक है कि sh -iशेल को इंटरेक्टिव मोड में लागू किया जाए।

चूंकि चर $PS1को पर्यावरण से आयात किया जा सकता है, इसलिए गैर-संवादात्मक मोड में भी इसका मूल्य हो सकता है। तथ्य यह है कि bash unsetरों PS1किसी भी गैर-सहभागी खोल में मानक द्वारा दी गई नहीं है और किसी भी अन्य खोल द्वारा नहीं किया।

तो स्वच्छ प्रोग्रामिंग (यहां तक ​​कि bash) के लिए इंटरैक्टिव गोले के लिए कमांड डालनी है $HOME/.bashrc


0

मैं पहले बात करने जा रहा हूं कि डेबियन क्या है, और ज्यादातर समय उबंटू बैश के लिए भी सेट करता है। और अन्य प्रणालियों पर बाद का स्पर्श।

शेल प्रारंभ फ़ाइलों की सेटिंग में बहुत सारी राय है।
मेरी भी अपनी राय है लेकिन मैं सही सेटिंग्स के मौजूदा उदाहरण दिखाने की कोशिश करूंगा।
मैं डिबुआन का उपयोग करूंगा क्योंकि इसकी फ़ाइलों के उदाहरण ढूंढना काफी आसान है।
और डेबियन का उपयोग किया जाता है, इसलिए सेटिंग्स को अच्छी तरह से परीक्षण किया गया है,

PS1 को सेट करने की जाँच का लक्ष्य क्या है?

केवल यह पता लगाने के लिए कि शेल इंटरेक्टिव है या नहीं।

डिफ़ॉल्ट /etc/profileडेबियन में और ubuntu (से / usr / share / आधार फ़ाइलें / प्रोफाइल):

if [ "${PS1-}" ]; then
    if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then

अगर पढ़ा है: यदि इंटरैक्टिव (PS1 डिफ़ॉल्ट सेट) और यह बैश शेल है (लेकिन डिफ़ॉल्ट के रूप में कार्य नहीं कर रहा है sh) तो PS1 को किसी विशेष नए (डिफ़ॉल्ट डिफ़ॉल्ट नहीं) में बदल दें।

डिफ़ॉल्ट /etc/bash.bashrcडेबियन में भी शामिल हैं:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

यह क्या करता है में बहुत स्पष्ट है: यदि इंटरैक्टिव स्रोत (बाकी) नहीं है।

हालांकि, में /etc/skel/.bashrcएक उदाहरण है (का उपयोग करते हुए एक इंटरैक्टिव खोल के लिए परीक्षण करने के लिए सही रास्ते से $-):

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

यह स्पष्ट रूप से PS1 का एक और एक विकल्प क्यों दिखाना चाहिए।

सही क्रम

आपके द्वारा बताई जा रही सेटिंग से बचना चाहिए।
आदेश (सिस्टम सेटिंग से (बैश के लिए) और अधिक विशिष्ट उपयोगकर्ता सेटिंग्स करने के लिए) है /etc/profile, /etc/bash.bashrc, ~/.profileऔर अंत में ~/.bashrc। यह सबसे व्यापक प्रभाव डालता है (और अधिक गोले के लिए) /etc/profile(जिसके पास रूट का स्वामित्व होता है) इसके बाद /etc/bash.bashrc(जो रूट का भी स्वामित्व होता है) लेकिन केवल बैश को प्रभावित करता है। फिर व्यक्तिगत सेटिंग्स में आते हैं $HOME, पहला ~/.profileअधिकांश गोले के लिए है और ~/.bashrc(लगभग बराबर ~/.bash_profile), केवल बैश के लिए विशिष्ट है।

इसलिए यह स्रोत के लिए गलत है ~/.bashrcमें ~/.profile, यह एक विशिष्ट उपयोगकर्ता एक अधिक सामान्य है कि है करने के लिए पार्टी के लिए सेटिंग बदलाव ला रहा है और अधिक गोले को प्रभावित करने वालेइस तरह से किए जाने पर छोड़कर :

# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

यह जाँचता है कि बैश चल रहा है और केवल लोड होने पर .bashrcही ऐसा है।

यह डेबियन से आने वाला एक अपस्ट्रीम निर्णय है। औचित्य यहाँ समझाया गया है

तथ्य यह है, रिवर्स, सोर्सिंग में ~/.profileमें ~/.bash_profile(या ~/.bashrc) है केवल फिर से लागू करने के सामान्य नियम है कि पहले से ही एक विशेष उपयोग के मामले के लिए लोड किया जाना चाहिए था, और इसलिए "नहीं है कि बुरा" (मैं नहीं "अच्छा" कह रहा हूँ)। और मैं अच्छा नहीं कह रहा हूं क्योंकि इससे फाइलों की सोर्सिंग लूप हो सकती है। जैसे जब एक उप-निर्देशिका एक माता-पिता को लोड करती है, तो वह एक निर्देशिका लूप होती है।

और इस क्रॉस सोर्सिंग में है कि इंटरेक्टिव शेल के लिए चेक समझ में आता है। केवल जब एक शेल इंटरेक्टिव होता है ~/.bashrc, तो लोड किया जाता है, लेकिन यह बदले में लोड हो सकता है ~/.profile(या अन्य तरीके से) और इस मामले में है कि एक इंटरेक्टिव शेल के लिए जाँच का उपयोग किया जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.