तुरंत ("सुपर") शेल पर लौटे बिना प्रारंभिक कमांड के साथ एक इंटरएक्टिव बैश को चलाएं


86

मैं एक bash सब-रन चलाना चाहता हूं, (1) कुछ कमांड्स रन करता हूं, (2) और फिर उस सब-सब्सक्रिप्शन में रहता हूं जो मैं चाहता हूं। मैं इनमें से प्रत्येक को व्यक्तिगत रूप से कर सकता हूं:

  1. -cध्वज का उपयोग करके कमांड चलाएं :

    $> bash -c "ls; pwd; <other commands...>"

    हालाँकि, यह कमांड निष्पादित होने के तुरंत बाद "सुपर" शेल में वापस आ जाता है। मैं भी सिर्फ एक इंटरैक्टिव उपधारा चला सकते हैं:

  2. नई bashप्रक्रिया शुरू करें :

    $> bash

    और जब तक मैं स्पष्ट रूप से नहीं कहूंगा, तब तक यह सब से बाहर नहीं निकलेगा ... लेकिन मैं कोई प्रारंभिक आदेश नहीं चला सकता। निकटतम समाधान मैंने पाया है:

    $> bash -c "ls; pwd; <other commands>; exec bash"

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

मैं एक ही लाइन पर यह करना चाहता हूं। एक बार जब मैं सदस्यता से बाहर निकल जाता हूं, तो मुझे बिना घटना के नियमित "सुपर" शेल पर वापस लौटना चाहिए। एक रास्ता होना चाहिए ~~

NB: मैं क्या नहीं पूछ रहा हूँ ...

  1. यह नहीं पूछ रहा कि बैश मैन पेज की पकड़ कहां से लाएं
  2. यह नहीं पूछ रहा कि फाइल से कमांड को कैसे पढ़ना है ... मुझे पता है कि यह कैसे करना है, यह वह समाधान नहीं है जिसकी मुझे तलाश है
  3. tmux या gnu स्क्रीन का उपयोग करने में रुचि नहीं है
  4. इसके संदर्भ में दिलचस्पी नहीं है। यानी, प्रश्न का अर्थ सामान्य होना है, न कि किसी विशेष उद्देश्य के लिए
  5. यदि संभव हो तो, मैं वर्कअराउंड का उपयोग करने से बचना चाहता हूं जो कि मैं चाहता हूं, लेकिन एक "गंदे" तरीके से पूरा करें। मैं सिर्फ एक लाइन पर यह करना चाहता हूं। विशेष रूप से, मैं ऐसा कुछ नहीं करना चाहताxterm -e 'ls'

मैं एक उम्मीद समाधान की कल्पना कर सकता हूं, लेकिन यह मुश्किल से एक-लाइनर है जो आप चाहते हैं। किस तरह से exec bashसमाधान आपके लिए अनुपयुक्त है?
ग्लेन जैकमैन

@glennjackman क्षमा करें, मैं शब्दजाल से परिचित नहीं हूं। एक "उम्मीद समाधान" क्या है? इसके अलावा, exec bashसमाधान में दो अलग-अलग उपधारा शामिल हैं। मुझे एक निरंतर उपधारा चाहिए।
SABBATINI लुका

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


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

जवाबों:


77

यह अस्थायी नामित पाइपों के साथ आसानी से किया जा सकता है :

bash --init-file <(echo "ls; pwd")

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


9
यह संभवतः इसका मतलब है कि $HOME/.bashrcहालांकि निष्पादित नहीं किया गया है। इसे अस्थायी नामित पाइप से शामिल करना होगा।
हब्रो

9
स्पष्ट करने के लिए, कुछ इस तरह से:bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
हब्रो

5
यह इतना सकल है लेकिन यह काम करता है। मैं विश्वास नहीं कर सकता कि बैश सीधे इसका समर्थन नहीं करता है।
पैट नीमेयर

2
@Gus, कमांड .का एक पर्याय है source: ss64.com/bash/source.html
जोनाथन पॉटर

1
क्या उपयोगकर्ता स्विचिंग के साथ काम करने का कोई तरीका है, जैसे sudo bash --init-file <(echo "ls; pwd")या sudo -iu username bash --init-file <(echo "ls; pwd")?
jeremysprofile

10

आप इसे एक अस्थायी फ़ाइल के साथ एक राउंडअबाउट तरीके से कर सकते हैं, हालांकि इसमें दो लाइनें लगेंगी:

echo "ls; pwd" > initfile
bash --init-file initfile

एक अच्छे प्रभाव के लिए आप इसमें शामिल करके अस्थायी फ़ाइल को स्वयं निकाल सकते हैं rm $BASH_SOURCE
एडुआर्डो इवानेक

एडुआर्डो, धन्यवाद। यह एक अच्छा समाधान है, लेकिन ... क्या आप कह रहे हैं कि यह फ़ाइल I / O के साथ फ़ेल किए बिना नहीं हो सकता । स्पष्ट कारण हैं कि मैं इसे एक स्व-निहित कमांड के रूप में क्यों रखना पसंद करूंगा, क्योंकि पल-पल फाइलें मिक्स में आती हैं, मुझे यह चिंता करना शुरू करना होगा कि कैसे यादृच्छिक टेम्प-फाइल्स बनाने के लिए और फिर, जैसा कि आपने उल्लेख किया है, उन्हें हटाते हुए। अगर मुझे कठोर बनना है तो बस इस तरह से और अधिक प्रयास की आवश्यकता है। इसलिए एक अधिक न्यूनतर, सुरुचिपूर्ण समाधान की इच्छा।
SABBATINI लुका

1
@SABBATINILuca: मैं ऐसा कुछ नहीं कह रहा हूं। यह सिर्फ एक तरीका है, और mktempअस्थायी फ़ाइल समस्या को हल करता है जैसा कि @cjc ने बताया है। बाश स्टड से इनिट कमांड को पढ़ने का समर्थन कर सकता है , लेकिन जहां तक ​​मैं बता सकता हूं कि यह नहीं है। इनिट -फ़ाइल के रूप में निर्दिष्ट करना और उन्हें आधा काम देना, लेकिन बैश तब बाहर निकलता है (शायद इसलिए कि यह पाइपलाइन का पता लगाता है )। सुरुचिपूर्ण समाधान, IMHO, निष्पादन का उपयोग करना है।
एडुआर्डो इवानेक

1
क्या यह आपकी सामान्य बैश इनिशियलाइज़ेशन को भी ओवरराइड नहीं करता है? @SABBATINILuca आप इसके साथ क्या हासिल करने की कोशिश कर रहे हैं, आपको शेल कमांड को कुछ कमांड चलाने और फिर उस शेल को खुला रखने की आवश्यकता क्यों है?
user9517

11
यह एक पुराना प्रश्न है, लेकिन बैश निम्नलिखित सिंटैक्स का उपयोग करके अस्थायी नामित पाइप बना सकते हैं: बैश - इनिट-फाइल <(इको "ls; pwd")।
रेयान

5

इसके बजाय यह प्रयास करें:

$> bash -c "ls;pwd;other commands;$SHELL"

$SHELL यह इंटरैक्टिव मोड में खोल को खोल देता है, जिसके साथ एक करीबी की प्रतीक्षा कर रहा है exit


9
FYI करें, यह बाद में एक नया शेल खोलता है, इसलिए यदि कोई भी कमांड वर्तमान शेल की स्थिति को प्रभावित करता है (जैसे किसी फ़ाइल को
सोर्स

3

"एक्सपेक्ट सॉल्यूशन" जिसका मैं जिक्र कर रहा था, एक्सपेक्ट प्रोग्रामिंग लैंग्वेज के साथ बैश शेल प्रोग्रामिंग कर रहा है :

#!/usr/bin/env expect
set init_commands [lindex $argv 0]
set bash_prompt {\$ $}              ;# adjust to suit your own prompt
spawn bash
expect -re $bash_prompt {send -- "$init_commands\r"}
interact
puts "exiting subshell"

आप इसे ऐसे ही चलाएंगे: ./subshell.exp "ls; pwd"


मुझे लगता है कि इससे इतिहास में आदेशों को दर्ज करने का फायदा होगा, क्या मैं गलत हूं? अगर मैं इस मामले में bashrc / प्रोफ़ाइल निष्पादित करता हूं, तो मैं उत्सुक हूं?
मुहुर्त

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

1

देशी उपधाराओं का उपयोग क्यों नहीं किया जाता है?

$ ( ls; pwd; exec $BASH; )
bar     foo     howdy
/tmp/hello/
bash-4.4$ 
bash-4.4$ exit
$

कोष्ठक के साथ आज्ञाओं को जोड़ना इन आदेशों को चलाने के लिए बैश स्पॉन को एक उपप्रकार बनाता है, इसलिए, उदाहरण के लिए, आप मूल शैल को प्रभावित किए बिना पर्यावरण में परिवर्तन कर सकते हैं। यह मूल रूप से अधिक पठनीय के बराबर है bash -c "ls; pwd; exec $BASH"

यदि वह अभी भी क्रिया दिखता है, तो दो विकल्प हैं। एक समारोह के रूप में इस स्निपेट को रखना है:

$ run() { ( eval "$@"; exec $BASH; ) }
$ run 'ls; pwd;'
bar     foo     howdy
/tmp/hello/
bash-4.4$ exit
$ run 'ls;' 'pwd;'
bar     foo     howdy
/tmp/hello/
bash-4.4$ exit
$

एक और exec $BASHछोटा करना है:

$ R() { exec $BASH; }
$ ( ls; pwd; R )
bar     foo     howdy
/tmp/hello/
bash-4.4$ exit
$

मुझे व्यक्तिगत Rरूप से दृष्टिकोण अधिक पसंद है , क्योंकि भागने के तार के साथ खेलने की कोई आवश्यकता नहीं है।


1
मुझे यकीन नहीं है कि अगर ओपी के मन में परिदृश्य के लिए निष्पादन का उपयोग करने के लिए कोई गुफाएं हैं, लेकिन मेरे लिए यह सबसे अच्छा समाधान प्रस्तावित है, क्योंकि यह किसी भी स्ट्रिंग से बचने के मुद्दों के बिना सादे बैश कमांड का उपयोग करता है।
पीटर

1

अगर sudo -E bashकाम नहीं करता है, तो मैं निम्नलिखित का उपयोग करता हूं, जो अब तक मेरी उम्मीदों पर खरा उतरा है:

sudo HOME=$HOME bash --rcfile $HOME/.bashrc

मैंने HOME = $ HOME सेट किया क्योंकि मैं चाहता हूं कि मेरा नया सत्र रूट के HOME के ​​बजाय मेरे उपयोगकर्ता के HOME पर सेट हो, जो कि कुछ सिस्टम पर डिफ़ॉल्ट रूप से होता है।


0

से कम सुरुचिपूर्ण --init-file, लेकिन शायद अधिक साधन:

fn(){
    echo 'hello from exported function'
}

while read -a commands
do
    eval ${commands[@]}
done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.