linux - एक शेल स्क्रिप्ट कॉलिंग खोल के पर्यावरण चर सेट कर सकते हैं?




bash shell (14)

"डॉट स्पेस स्क्रिप्ट" कॉलिंग वाक्यविन्यास का प्रयोग करें। उदाहरण के लिए, यहां एक स्क्रिप्ट के पूर्ण पथ का उपयोग करके इसे कैसे किया जाए:

. /path/to/set_env_vars.sh

और यदि आप स्क्रिप्ट के समान निर्देशिका में हैं तो यहां यह कैसे करें:

. set_env_vars.sh

ये किसी दूसरे को लोड करने के बजाय वर्तमान खोल के नीचे स्क्रिप्ट निष्पादित करते हैं (जो होता है यदि आपने किया ./set_env_vars.sh )। चूंकि यह एक ही खोल में चलता है, आपके द्वारा सेट किए गए पर्यावरणीय चर उपलब्ध होने पर उपलब्ध होंगे।

यह source set_env_vars.sh को कॉल करने जैसा ही बात है, लेकिन यह टाइप करने के लिए छोटा है और कुछ स्थानों पर काम कर सकता है जहां source नहीं है।

मैं एक शेल स्क्रिप्ट लिखने की कोशिश कर रहा हूं कि, जब चलाएगा, तो कुछ पर्यावरण चर सेट करेगा जो कॉलर के खोल में सेट रहेंगे।

setenv FOO foo

सीएसएच / टीसीएसएच में, या

export FOO=foo

sh / bash में केवल स्क्रिप्ट के निष्पादन के दौरान इसे सेट करें।

मुझे पहले से यह पता है

source myscript

एक नया खोल लॉन्च करने के बजाय स्क्रिप्ट के आदेश चलाएंगे, और इसके परिणामस्वरूप "कॉलर" वातावरण स्थापित हो सकता है।

लेकिन यहाँ रगड़ है:

मैं चाहता हूं कि यह स्क्रिप्ट या तो बैश या सीएसएच से कॉल करने योग्य हो। दूसरे शब्दों में, मैं चाहता हूं कि शैल के उपयोगकर्ता मेरी स्क्रिप्ट चलाने में सक्षम हों और उनके खोल का वातावरण बदल जाए। तो 'स्रोत' मेरे लिए काम नहीं करेगा, चूंकि कोई उपयोगकर्ता csh चल रहा है, वह बैश स्क्रिप्ट का स्रोत नहीं बना सकता है, और उपयोगकर्ता चल रहा है bash एक csh स्क्रिप्ट स्रोत नहीं कर सकता है।

क्या कोई उचित समाधान है जिसमें स्क्रिप्ट पर दो संस्करणों को लिखने और बनाए रखने में शामिल नहीं है?


$ SHELL / $ TERM पर सेट किए जाने के आधार पर लेखन सशर्त के अलावा, नहीं। पर्ल का उपयोग करने में क्या गलत है? यह बहुत सर्वव्यापी है (मैं एक यूनिक्स संस्करण के बारे में नहीं सोच सकता जो इसमें नहीं है), और यह आपको परेशानी को छोड़ देगा।


आप अलग-अलग bash_profile के साथ एक और एक बैश का आह्वान कर सकते हैं। इसके अलावा, आप मल्टी-बैशप्रोफाइल वातावरण में उपयोग करने के लिए विशेष bash_profile बना सकते हैं।

याद रखें कि आप bashprofile के अंदर फ़ंक्शंस का उपयोग कर सकते हैं, और यह कार्य वैश्विक स्तर पर उपलब्ध होंगे। उदाहरण के लिए, "फ़ंक्शन उपयोगकर्ता {निर्यात USER_NAME $ 1}" रनटाइम में चर सेट कर सकता है, उदाहरण के लिए: उपयोगकर्ता olegchir & en env | grep olegchir


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

एक चीज जो आप कर सकते हैं वह एक ऐसी स्क्रिप्ट लिखना है जो tcsh या sh के लिए सही कमांड को उत्सर्जित करती है, जिस पर इसे लागू किया जाता है। यदि आप स्क्रिप्ट हैं "सेटिट" है तो करें:

ln -s setit setit-sh

तथा

ln -s setit setit-csh

अब या तो सीधे या उपनाम में, आप इसे sh से करते हैं

eval `setit-sh`

या यह सीएसएच से

eval `setit-csh`

सेटिट अपनी आउटपुट शैली निर्धारित करने के लिए $ 0 का उपयोग करता है।

यह टीईआरएम पर्यावरण परिवर्तनीय सेट प्राप्त करने के लिए लोगों का उपयोग करने के बारे में याद दिलाता है।

यहां का लाभ यह है कि सेटिट सिर्फ उस शेल में लिखा गया है जिसमें आप पसंद करते हैं:

#!/bin/bash
arg0=$0
arg0=${arg0##*/}
for nv in \
   NAME1=VALUE1 \
   NAME2=VALUE2
do
   if [ x$arg0 = xsetit-sh ]; then
      echo 'export '$nv' ;'
   elif [ x$arg0 = xsetit-csh ]; then
      echo 'setenv '${nv%%=*}' '${nv##*=}' ;'
   fi
done

ऊपर दिए गए प्रतीकात्मक लिंक के साथ, और बैकक्वॉट अभिव्यक्ति के eval के साथ, यह वांछित परिणाम है।

सीएसएच, टीसीएसएच, या इसी तरह के गोले के लिए आमंत्रण को सरल बनाने के लिए:

alias dosetit 'eval `setit-csh`'

या sh, bash, और पसंद के लिए:

alias dosetit='eval `setit-sh`'

इसके बारे में एक अच्छी बात यह है कि आपको केवल एक ही स्थान पर सूची बनाए रखना है। सिद्धांत रूप में आप सूची में भी एक सूची में चिपक सकते हैं और "इन" और "डू" के बीच cat nvpairfilename डाल सकते हैं।

यह बहुत कुछ है कि लॉगिन शेल टर्मिनल सेटिंग्स कैसे किया जाता है: एक स्क्रिप्ट लॉगिन खोल में निष्पादित करने के लिए स्टेटमेंट आउटपुट करेगा। एक उपनाम आमतौर पर "tset vt100" में, आमंत्रण को सरल बनाने के लिए उपयोग किया जाएगा। जैसा कि एक और उत्तर में बताया गया है, आईएनएन यूजनेट समाचार सर्वर में भी इसी तरह की कार्यक्षमता है।


आप हमेशा उपनाम का उपयोग कर सकते हैं

alias your_env='source ~/scripts/your_env.sh'

आपकी खोल प्रक्रिया में माता-पिता के पर्यावरण की एक प्रति है और माता-पिता की प्रक्रिया के पर्यावरण तक कोई पहुंच नहीं है। जब आपकी खोल प्रक्रिया आपके पर्यावरण में किए गए किसी भी बदलाव को समाप्त कर देती है तो खो जाती है। एक स्क्रिप्ट फ़ाइल को सोर्सिंग एक शैल पर्यावरण को कॉन्फ़िगर करने के लिए सबसे अधिक उपयोग की जाने वाली विधि है, आप केवल बुलेट काटने और खोल के दो स्वादों में से प्रत्येक के लिए एक को बनाए रखना चाहते हैं।


एक अन्य कामकाज जिसे मैंने उल्लेख नहीं किया है वह एक चर को वैरिएबल मान लिखना है।

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

लेकिन फिर मैं इस साधारण हैक के साथ आया:

पहला आदेश ( testset ):

#!/bin/bash

if [ $# -eq 1 ]
then
  echo $1 > ~/.TESTCASE
  echo "TESTCASE has been set to: $1"
else
  echo "Come again?"
fi

दूसरा आदेश ( testrun ):

#!/bin/bash

TESTCASE=$(cat ~/.TESTCASE)
drush test-run $TESTCASE

एक और विकल्प "पर्यावरण मॉड्यूल" ( http://modules.sourceforge.net/ ) का उपयोग करना है। दुर्भाग्यवश यह मिश्रण में तीसरी भाषा का परिचय देता है। आप टीसीएल की भाषा के साथ पर्यावरण को परिभाषित करते हैं, लेकिन सामान्य संशोधनों के लिए कुछ आसान कमांड हैं (प्रीपेड बनाम एपेंड बनाम सेट)। आपको पर्यावरण मॉड्यूल स्थापित करने की भी आवश्यकता होगी। फिर आप जिस वातावरण को चाहते हैं उसका नाम देने के लिए module load *XXX* का उपयोग कर सकते हैं। मॉड्यूल कमांड मूल रूप से थॉमस Kammeyer द्वारा वर्णित eval तंत्र के लिए एक फैंसी उपनाम है। यहां मुख्य लाभ यह है कि आप पर्यावरण को एक भाषा में बनाए रख सकते हैं और इसे "पर्यावरण मॉड्यूल" पर भरोसा कर सकते हैं ताकि इसे sh, ksh, bash, csh, tcsh, zsh, पायथन (?!? !!) आदि में अनुवाद किया जा सके।


तकनीकी रूप से, यह सही है - केवल 'eval' एक और खोल फोर्क नहीं करता है। हालांकि, उस एप्लिकेशन के दृष्टिकोण से जिसे आप संशोधित माहौल में चलाने की कोशिश कर रहे हैं, अंतर शून्य है: बच्चे को अपने माता-पिता के पर्यावरण को विरासत में मिला है, इसलिए (संशोधित) वातावरण सभी अवरोही प्रक्रियाओं को व्यक्त किया जाता है।

आईपीएस वास्तव में, बदले गए पर्यावरण परिवर्तनीय 'छड़ें' - जब तक आप मूल प्रोग्राम / खोल के तहत चल रहे हों।

अगर माता-पिता (पर्ल या खोल) के बाद पर्यावरण चर के लिए यह बेहद जरूरी है, तो माता-पिता के खोल को भारी उठाने के लिए जरूरी है। प्रलेखन में मैंने जो एक तरीका देखा है, वह वर्तमान स्क्रिप्ट के लिए आवश्यक 'निर्यात' भाषा के साथ एक निष्पादन योग्य फ़ाइल को उत्पन्न करने के लिए है, और उसके बाद पैरेंट खोल को निष्पादित करने के लिए चालित करें - हमेशा इस तथ्य को समझने के लिए कि आपको प्रस्तावना चाहिए यदि आप संशोधित वातावरण के एक अस्थिर संस्करण को छोड़ने की कोशिश कर रहे हैं तो 'स्रोत' के साथ कमांड करें। सबसे अच्छा एक Kluge।

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

संक्षेप में, कोई अच्छी (और आसान) विधियां नहीं हैं। संभवतः यह सुनिश्चित करना मुश्किल हो गया था कि सिस्टम की सुरक्षा को अपरिवर्तनीय रूप से समझौता नहीं किया गया था।


मुझे कोई जवाब नहीं दिख रहा है कि इस समस्या को सहकारी प्रक्रियाओं के साथ कैसे काम करना है। ssh-agent जैसी चीजों के साथ एक आम पैटर्न यह है कि बच्चे की प्रक्रिया एक अभिव्यक्ति को मुद्रित करे, जिसे माता-पिता eval कर सकते हैं।

bash$ eval $(shh-agent)

उदाहरण के लिए, ssh-agent में सीएसएच या बॉर्न-संगत आउटपुट सिंटैक्स का चयन करने के विकल्प हैं।

bash$ ssh-agent
SSH2_AUTH_SOCK=/tmp/ssh-era/ssh2-10690-agent; export SSH2_AUTH_SOCK;
SSH2_AGENT_PID=10691; export SSH2_AGENT_PID;
echo Agent pid 10691;

(इससे एजेंट को चलना शुरू हो जाता है, लेकिन आप वास्तव में इसका उपयोग करने की अनुमति नहीं देते हैं, जब तक कि आप अब इस आउटपुट को अपने शेल प्रॉम्प्ट पर कॉपी न करें।) तुलना करें:

bash$ ssh-agent -c
setenv SSH2_AUTH_SOCK /tmp/ssh-era/ssh2-10751-agent;
setenv SSH2_AGENT_PID 10752;
echo Agent pid 10752;

(जैसा कि आप देख सकते हैं, csh और tcsh varibles सेट करने के लिए setenv का उपयोग करता है।)

आपका खुद का कार्यक्रम भी ऐसा कर सकता है।

bash$ foo=$(makefoo)

आपकी makefoo स्क्रिप्ट बस गणना और मूल्य मुद्रित करेगी, और कॉलर को जो भी चाहें वह करने दें - इसे एक चर के लिए असाइन करना एक सामान्य उपयोग केस है, लेकिन शायद ऐसा कुछ नहीं है जिसे आप टूल में हार्ड-कोड बनाना चाहते हैं जो उत्पन्न करता है मूल्य।


मैंने कई सालों पहले ऐसा किया था। अगर मैं सही ढंग से याद करता हूं, तो मैंने प्रत्येक .bashrc और .cshrc में पैरामीटर के साथ एक उपनाम शामिल किया है, जो पर्यावरण को एक सामान्य रूप में सेट करने के संबंधित रूपों को अलियासिंग करता है।

फिर स्क्रिप्ट जिसे आप किसी भी दो गोले में स्रोत करेंगे, उस अंतिम रूप के साथ एक कमांड है, जो कि प्रत्येक शेल में उपयुक्त है।

अगर मुझे ठोस उपनाम मिलते हैं, तो मैं उन्हें पोस्ट करूंगा।


मैंने पाइप, eval और सिग्नल का उपयोग कर एक समाधान बनाया।

parent() {
    if [ -z "$G_EVAL_FD" ]; then
            die 1 "Rode primeiro parent_setup no processo pai"
    fi
    if [ $(ppid) = "$$" ]; then
            "[email protected]"
    else
            kill -SIGUSR1 $$
            echo "[email protected]">&$G_EVAL_FD
    fi
}
parent_setup() {
    G_EVAL_FD=99
    tempfile=$(mktemp -u)
    mkfifo "$tempfile"
    eval "exec $G_EVAL_FD<>'$tempfile'"
    rm -f "$tempfile"
    trap "read CMD <&$G_EVAL_FD; eval \"\$CMD\"" USR1
}
parent_setup #on parent shell context
( A=1 ); echo $A # prints nothing
( parent A=1 ); echo $A # prints 1

यह किसी भी कमांड के साथ काम कर सकता है।


यह काम करता है - यह वह नहीं है जिसका मैं उपयोग करूंगा, लेकिन यह 'काम करता है'। चलो पर्यावरण परिवर्तक TEREDO_WORMS सेट करने के लिए एक स्क्रिप्ट teredo TEREDO_WORMS :

#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL -i

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

इस स्क्रिप्ट को चलाने से पहले, हमने वातावरण में SHELL को सी खोल में सेट किया है, और पर्यावरण परिवर्तनीय TEREDO_WORMS सेट नहीं है:

% env | grep SHELL
SHELL=/bin/csh
% env | grep TEREDO
%

जब स्क्रिप्ट चलती है, तो आप एक नए खोल में होते हैं, एक अन्य इंटरैक्टिव सी खोल, लेकिन पर्यावरण चर सेट है:

% teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%

जब आप इस खोल से बाहर निकलते हैं, तो मूल खोल लेता है:

% exit
% env | grep TEREDO
%

पर्यावरण चर मूल खोल के वातावरण में सेट नहीं है। यदि आप कमांड चलाने के लिए exec teredo का उपयोग करते हैं, तो मूल इंटरैक्टिव शैल कोर्न शेल द्वारा प्रतिस्थापित किया जाता है जो पर्यावरण को सेट करता है, और उसके बाद बदले में एक नए इंटरैक्टिव सी खोल द्वारा प्रतिस्थापित किया जाता है:

% exec teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%

यदि आप exit (या कंट्रोल-डी ) टाइप करते हैं, तो आपका खोल निकलता है, शायद आपको उस विंडो से बाहर लॉग आउट कर रहा है, या आपको प्रयोग के शुरू होने से पहले शेल के पिछले स्तर पर ले जा रहा है।

बैश या कॉर्न शैल के लिए एक ही तंत्र काम करता है। आप पाते हैं कि बाहर निकलने के आदेश के बाद संकेत अजीब स्थानों में दिखाई देता है।

टिप्पणियों में चर्चा पर ध्यान दें। यह एक समाधान नहीं है जिसे मैं अनुशंसा करता हूं, लेकिन यह एक ही स्क्रिप्ट के निर्दिष्ट उद्देश्य को पर्यावरण को स्थापित करने के लिए प्राप्त करता है जो सभी गोले के साथ काम करता है (जो एक इंटरैक्टिव खोल बनाने के लिए -i विकल्प स्वीकार करता है)। आप किसी अन्य तर्क को रिले करने के विकल्प के बाद "[email protected]" भी जोड़ सकते हैं, जो तब शेल को सामान्य 'सेट पर्यावरण और निष्पादन आदेश' उपकरण के रूप में उपयोग करने योग्य बना सकता है। यदि आप अन्य तर्क हैं तो आप -i को छोड़ना चाहेंगे, जिससे:

#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL "${@-'-i'}"

"${@-'-i'}" बिट का अर्थ है' यदि तर्क सूची में कम से कम एक तर्क होता है, तो मूल तर्क सूची का उपयोग करें; अन्यथा, गैर-मौजूदा तर्कों के लिए -i


संक्षिप्त उत्तर नहीं है, आप मूल प्रक्रिया के पर्यावरण को बदल नहीं सकते हैं, लेकिन ऐसा लगता है कि आप जो चाहते हैं वह एक पर्यावरण वातावरण चर के साथ एक वातावरण है और उपयोगकर्ता द्वारा चुने गए खोल।

तो क्यों बस कुछ पसंद नहीं है

#!/usr/bin/env bash
FOO=foo $SHELL

फिर जब आप पर्यावरण के साथ होते हैं, तो exit





tcsh