बैश कैसे लागू करें, नए शेल के अंदर कमांड चलाएं, और फिर उपयोगकर्ता को वापस कंट्रोल दें?


86

यह या तो वास्तव में सरल होना चाहिए या वास्तव में जटिल होना चाहिए, लेकिन मुझे इसके बारे में कुछ भी पता नहीं चल सका है ... मैं एक नया bash उदाहरण खोलने की कोशिश कर रहा हूं, फिर इसके अंदर कुछ कमांड चलाएं, और इसके अंदर उपयोगकर्ता को नियंत्रण वापस दें एक ही उदाहरण

मैंने कोशिश की:

$ bash -lic "some_command"

लेकिन यह some_commandनए उदाहरण के अंदर निष्पादित होता है, फिर इसे बंद कर देता है। मैं चाहता हूं कि यह खुला रहे।

एक और विवरण जो उत्तर को प्रभावित कर सकता है: अगर मुझे यह काम करने के लिए मिल सकता है तो मैं इसे अपने .bashrcउपनाम (एस) के रूप में उपयोग करूंगा , इसलिए aliasकार्यान्वयन के लिए बोनस अंक !


मैं उपनाम के बारे में अंतिम भाग नहीं समझता। उपनाम वर्तमान शेल के संदर्भ में निष्पादित होते हैं, इसलिए उनके पास समस्या नहीं है जिसे आप हल करने के लिए कह रहे हैं (हालांकि आमतौर पर, कई कारणों से उपनाम से बेहतर कार्य होते हैं)।
ट्रिपलए

2
मैं alias shortcut='bash -lic "some_command"'अपने .bashrc में कुछ इस तरह डालना चाहता हूं कि वह चला जाए shortcutऔर उसमें some_commandपहले से ही एक नया खोल हो।
फेलिक्स सपरेली

जवाबों:


63
bash --rcfile <(echo '. ~/.bashrc; some_command')

अस्थायी फ़ाइलों के निर्माण को तितर-बितर करता है। अन्य साइटों पर प्रश्न:


मैंने विंडोज 10 में ऐसा करने का प्रयास किया (बैच "स्टार्टअप" फ़ाइल / स्क्रिप्ट लिखने की कोशिश), और मुझे मिल गयाThe system cannot find the file specified.
डॉक्टर ब्लू

1
@ यह कदम से कदम डिबग: 1) cat ~/.bashrcकाम करता है ? 2) cat <(echo a)काम करता है ? ३) bash --rcfile somefileकाम करता है ?
सिरो सेंटिल्ली 32 i i i

1
@ देखें कि हम सिर्फ इस मुद्दे पर डब्ल्यूएसएल (स्टार्टअप बैच फ़ाइल से बैश लॉन्चिंग) में भाग गए थे। हमारा समाधान कुछ पात्रों से बचना था ताकि बैच इसे समझ सके: bash.exe --rcfile ^<^(echo 'source $HOME/.bashrc; ls; pwd'^)विंडोज़ कमांड प्रॉम्प्ट से चलना चाहिए।
user2561747

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


39

यह एक देर से जवाब है, लेकिन मुझे ठीक यही समस्या थी और Google ने मुझे इस पृष्ठ पर भेजा, इसलिए यहां पूर्णता के लिए मुझे समस्या के बारे में कैसे पता चला।

जहां तक ​​मैं बता सकता हूं, मेरे bashपास वह विकल्प नहीं है जो मूल पोस्टर करना चाहता था। -cविकल्प हमेशा के बाद आदेशों के बाद मार दिया वापस आ जाएगी।

टूटा हुआ समाधान : इसके आस-पास सबसे सरल और स्पष्ट प्रयास है:

bash -c 'XXXX ; bash'

यह आंशिक रूप से काम करता है (एक अतिरिक्त उप-शेल परत के साथ)। हालाँकि, समस्या यह है कि जबकि एक सब-शेल निर्यात किए गए पर्यावरण चर, विरासत और विरासत को विरासत में मिला होगा। तो यह कुछ चीजों के लिए काम कर सकता है लेकिन सामान्य समाधान नहीं है।

बेहतर : इसके आस-पास का तरीका स्टार्टअप फ़ाइल को गतिशील रूप से बनाना और इस नई इनिशियलाइज़ेशन फ़ाइल के साथ कॉल बैश करना है, जिससे यह सुनिश्चित होता है कि आपकी नई इनइट फ़ाइल आपके नियमित रूप से कॉल करती है ~/.bashrcयदि आवश्यक हो।

# Create a temporary file
TMPFILE=$(mktemp)

# Add stuff to the temporary file
echo "source ~/.bashrc" > $TMPFILE
echo "<other commands>" >> $TMPFILE
echo "rm -f $TMPFILE" >> $TMPFILE

# Start the new bash shell 
bash --rcfile $TMPFILE

अच्छी बात यह है कि अस्थायी इनिट फ़ाइल जैसे ही उपयोग में लाई जाएगी, यह उस जोखिम को कम कर देगा, जिसे सही तरीके से साफ नहीं किया गया है।

नोट: मुझे यकीन नहीं है कि / etc / bashrc को आमतौर पर एक सामान्य गैर-लॉगिन शेल के भाग के रूप में कहा जाता है। यदि ऐसा है तो आप स्रोत / आदि / bashrc के रूप में अच्छी तरह से अपने लिए चाहते हो सकता है ~/.bashrc


rm -f $TMPFILEबात यह बनाता है। मुझे वास्तव में इसके लिए मेरे द्वारा उपयोग किए जाने वाले केस याद नहीं हैं, और मैं अब अधिक उन्नत स्वचालन तकनीकों का उपयोग करता हूं, लेकिन यह जाने का तरीका है!
फेलिक्स सपरेली

7
प्रक्रिया प्रतिस्थापन के साथ कोई tmp फ़ाइलेंbash --rcfile <(echo ". ~/.bashrc; a=b")
सिरो Santilli郝海东冠状病六四事件法轮功

3
अगर आपकी बैश स्क्रिप्ट सफल हो जाती है तो अस्थायी फ़ाइल को केवल तभी साफ़ किया जाएगा। अधिक मजबूत समाधान का उपयोग करना होगा trap
ट्रिपलए

5

आप --rcfileअपनी पसंद की फ़ाइल पढ़ने के लिए इसे बैश करने के लिए पास कर सकते हैं । यह फ़ाइल आपके बजाय पढ़ी जाएगी .bashrc। (यदि यह एक समस्या है, ~/.bashrcतो दूसरी स्क्रिप्ट से स्रोत ।)

संपादित करें: इसलिए सामान के साथ एक नया शेल शुरू करने के लिए एक फ़ंक्शन ~/.more.shकुछ इस तरह दिखाई देगा:

more() { bash --rcfile ~/.more.sh ; }

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


3

स्क्रिप्ट चलाने के बजाए आप अपनी कार्यक्षमता चाहते हैं। उदाहरण के लिए:

$ बिल्ली स्क्रिप्ट
cmd1
CMD2
$। लिपि
इस बिंदु पर $ cmd1 और cmd2 को इस शेल के अंदर चलाया गया है

हम्म। यह काम करता है, लेकिन क्या सब कुछ एक में एम्बेड करने का कोई तरीका नहीं है alias=''?
फेलिक्स सपरेली

1
कभी भी उपनाम का उपयोग न करें; इसके बजाय कार्यों का उपयोग करें। आप डाल सकते हैं: 'फू' () {cmd1; CMD2; } 'स्टार्ट अप स्क्रिप्ट्स के अंदर, और फिर foo निष्पादित करने से दो कमांड चालू शेल में चलेंगे। ध्यान दें कि इन समाधानों में से कोई भी आपको एक नया शेल नहीं देता है, लेकिन आप 'निष्पादन बैश' और फिर 'फू' कर सकते हैं
विलियम पर्ससेल

1
नेवर से नेवर। उपनामों का अपना स्थान है
ग्लेन जैकमैन

क्या एक उपयोग के मामले का एक उदाहरण है जहां एक फ़ंक्शन का उपयोग उपनाम के बजाय नहीं किया जा सकता है?
विलियम पर्ससेल

3

~/.bashrcइस तरह एक अनुभाग में आवेदन करें:

if [ "$subshell" = 'true' ]
then
    # commands to execute only on a subshell
    date
fi
alias sub='subshell=true bash'

तो फिर आप के साथ उपधारा शुरू कर सकते हैं sub


मौलिकता के लिए अंक। उपनाम ही शायद बेहतर है env subshell=true bash(जैसा कि $subshellबाद की आज्ञाओं के लिए लीक नहीं होगा ): env बनाम निर्यात का उपयोग करना
फेलिक्स सपरेली

तुम सही हो। लेकिन मैंने देखा कि यह बिना भी काम करता है env। यह परिभाषित करने के लिए कि क्या परिभाषित है या नहीं, मैं उपयोग करता हूं echo $subshell(इसके बजाय env | grep subshellआप उपयोग करते हैं)।
डैशोहोक्सा

3

स्वीकृत उत्तर वास्तव में मददगार है! बस उस प्रक्रिया प्रतिस्थापन (यानी, <(COMMAND)) को कुछ गोले (जैसे, dash) में समर्थित नहीं है ।

मेरे मामले में, मैं शेल शुरू करने और चयनित पायथन आभासी वातावरण को सक्रिय करने के लिए थुनार फ़ाइल प्रबंधक में एक कस्टम एक्शन (मूल रूप से एक-लाइन शेल स्क्रिप्ट) बनाने की कोशिश कर रहा था। मेरा पहला प्रयास था:

urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")

%fThunar द्वारा संभाले गए आभासी वातावरण के लिए रास्ता कहाँ है। मुझे एक त्रुटि मिली (कमांड लाइन से थूनर चलाकर):

/bin/sh: 1: Syntax error: "(" unexpected

तब मुझे एहसास हुआ कि मेरी sh(अनिवार्य रूप से dash) प्रक्रिया प्रतिस्थापन का समर्थन नहीं करती है।

मेरा समाधान bashप्रक्रिया स्तर प्रतिस्थापन की व्याख्या करने के लिए शीर्ष स्तर पर आह्वान करना था , अतिरिक्त स्तर की कीमत पर:

bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'

वैकल्पिक रूप से, मैंने यहां-दस्तावेज़ का उपयोग करने की कोशिश की, dashलेकिन कोई सफलता नहीं मिली। कुछ इस तरह:

echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile

पुनश्च: मेरे पास टिप्पणियों को पोस्ट करने के लिए पर्याप्त प्रतिष्ठा नहीं है, मॉडरेटर्स कृपया इसे टिप्पणी में स्थानांतरित करने के लिए स्वतंत्र महसूस करें या यदि इस प्रश्न के साथ सहायक नहीं हैं तो इसे हटा दें।


यदि कोई शीर्ष पर बैश नहीं चाहता (या उसके पास नहीं है), तो प्रक्रिया प्रतिस्थापन को सीधे लागू करने के लिए विभिन्न दस्तावेज तरीके हैं, ज्यादातर पंद्रह के साथ।
फेलिक्स सपरेली जू

2

डावराजा के जवाब के अनुसार , यहां एक बैश स्क्रिप्ट है जो उद्देश्य को हल करेगी।

एक स्थिति पर विचार करें यदि आप सी-शेल का उपयोग कर रहे हैं और आप सी-शेल संदर्भ / विंडो को छोड़कर एक कमांड निष्पादित करना चाहते हैं,

निष्पादित किया जाने वाला कमांड : वर्तमान निर्देशिका में सटीक शब्द 'परीक्षण' को केवल * .h, * .c फ़ाइलों में पुन : खोजे

grep -nrs --color -w --include="*.{h,c}" Testing ./

समाधान 1 : सी-शेल से बैश में प्रवेश करें और कमांड निष्पादित करें

bash
grep -nrs --color -w --include="*.{h,c}" Testing ./
exit

समाधान 2 : इच्छित आदेश को एक पाठ फ़ाइल में लिखें और बैश का उपयोग करके इसे निष्पादित करें

echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt
bash tmp_file.txt

समाधान 3 : बैश का उपयोग करके एक ही लाइन पर कमांड चलाएँ

bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./'

समाधान 4 : एक स्काइपर्ट (एक-बार) बनाएं और भविष्य के सभी कमांड के लिए इसका उपयोग करें

alias ebash './execute_command_on_bash.sh'
ebash grep -nrs --color -w --include="*.{h,c}" Testing ./

स्क्रिप्ट इस प्रकार है,

#!/bin/bash
# =========================================================================
# References:
# https://stackoverflow.com/a/13343457/5409274
# https://stackoverflow.com/a/26733366/5409274
# https://stackoverflow.com/a/2853811/5409274
# https://stackoverflow.com/a/2853811/5409274
# https://www.linuxquestions.org/questions/other-%2Anix-55/how-can-i-run-a-command-on-another-shell-without-changing-the-current-shell-794580/
# https://www.tldp.org/LDP/abs/html/internalvariables.html
# https://stackoverflow.com/a/4277753/5409274
# =========================================================================

# Enable following line to see the script commands
# getting printing along with their execution. This will help for debugging.
#set -o verbose

E_BADARGS=85

if [ ! -n "$1" ]
then
  echo "Usage: `basename $0` grep -nrs --color -w --include=\"*.{h,c}\" Testing ."
  echo "Usage: `basename $0` find . -name \"*.txt\""
  exit $E_BADARGS
fi  

# Create a temporary file
TMPFILE=$(mktemp)

# Add stuff to the temporary file
#echo "echo Hello World...." >> $TMPFILE

#initialize the variable that will contain the whole argument string
argList=""
#iterate on each argument
for arg in "$@"
do
  #if an argument contains a white space, enclose it in double quotes and append to the list
  #otherwise simply append the argument to the list
  if echo $arg | grep -q " "; then
   argList="$argList \"$arg\""
  else
   argList="$argList $arg"
  fi
done

#remove a possible trailing space at the beginning of the list
argList=$(echo $argList | sed 's/^ *//')

# Echoing the command to be executed to tmp file
echo "$argList" >> $TMPFILE

# Note: This should be your last command
# Important last command which deletes the tmp file
last_command="rm -f $TMPFILE"
echo "$last_command" >> $TMPFILE

#echo "---------------------------------------------"
#echo "TMPFILE is $TMPFILE as follows"
#cat $TMPFILE
#echo "---------------------------------------------"

check_for_last_line=$(tail -n 1 $TMPFILE | grep -o "$last_command")
#echo $check_for_last_line

#if tail -n 1 $TMPFILE | grep -o "$last_command"
if [ "$check_for_last_line" == "$last_command" ]
then
  #echo "Okay..."
  bash $TMPFILE
  exit 0
else
  echo "Something is wrong"
  echo "Last command in your tmp file should be removing itself"
  echo "Aborting the process"
  exit 1
fi

2
यह एक पूरी तरह से अलग समस्या के लिए एक अलग जवाब है। (यह अच्छा है कि आपने यह पता लगा लिया है, लेकिन यह इस धागे पर नहीं है। यदि यह इस साइट पर मौजूद नहीं है, तो अपने दूसरे वाक्य के साथ एक नया प्रश्न खोलने पर विचार करें, फिर तुरंत ही इसका उत्तर बाकी के साथ दें ... यह इस तरह से संभाला जाना चाहिए Also) इसके अलावा Ciro Santilli के जवाब के लिए एक अस्थायी फ़ाइल का निर्माण किए बिना इसे करने के तरीके के लिए देखें।
फेलिक्स सपरेली

फ्लैग-न- ए -जवाब, क्योंकि यह इस प्रश्न का उत्तर देने का प्रयास नहीं है (हालांकि यह एक अलग जवाब देने का एक बहुत अच्छा प्रयास है!)
चार्ल्स डफी

0

यहाँ अभी तक एक और (काम कर) संस्करण है:

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

gnome-terminal -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'

मुझे टर्मिनल को सजाने के लिए कभी-कभी उपयोगी भी लगता है, जैसे कि colorfor बेहतर ओरिएंटेशन के साथ।

gnome-terminal --profile green -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'

-1

एक पृष्ठभूमि के खोल में कार्यकारी आदेश

बस &कमांड के अंत में जोड़ें , जैसे:

bash -c some_command && another_command &

-1
$ bash --init-file <(echo 'some_command')
$ bash --rcfile <(echo 'some_command')

मामले में आप प्रक्रिया प्रतिस्थापन का उपयोग नहीं कर सकते हैं या नहीं करना चाहते हैं:

$ cat script
some_command
$ bash --init-file script

दूसरा रास्ता:

$ bash -c 'some_command; exec bash'
$ sh -c 'some_command; exec sh'

shएक ही रास्ता ( dash, busybox):

$ ENV=script sh

अच्छे विकल्प, लेकिन ENV=scriptशीर्ष उत्तर के एक स्पष्ट प्रति-पेस्ट के साथ भ्रमित होने से बचने के लिए शीर्ष भाग ( हटाए जाने से पहले या हटाए गए) को प्राप्त करने से लाभ होगा ।
फेलेक्स सपरेली

@ FélixSaparelli खुलकर सब समाधान होना करने के लिए, लेकिन ENV+ shएक अन्य उत्तर में मौजूद हैं, लेकिन ज्यादातर पाठ की टन में दफन या अनावश्यक / गैर जरूरी कोड से घिरा हुआ। मेरा मानना ​​है कि संक्षिप्त, स्पष्ट सारांश से हर किसी को फायदा होगा।
एक्स-यूरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.