कैसे बैश का उपयोग कर चर के लिए एक फ़ाइल को संदर्भित करने के लिए?


151

मैं एक चर के लिए एक सेटिंग फ़ाइल को कॉल करना चाहता हूं, मैं इसे बाश में कैसे कर सकता हूं?

तो सेटिंग्स फ़ाइल चर को परिभाषित करेगी (जैसे: CONFIG.FILE):

production="liveschool_joe"
playschool="playschool_joe"

और स्क्रिप्ट इसमें उन चरों का उपयोग करेगी

#!/bin/bash
production="/REFERENCE/TO/CONFIG.FILE"
playschool="/REFERENCE/TO/CONFIG.FILE"
sudo -u wwwrun svn up /srv/www/htdocs/$production
sudo -u wwwrun svn up /srv/www/htdocs/$playschool

मैं ऐसा कुछ करने के लिए कैसे बैश हो सकता हूं? क्या मुझे awk / sed आदि का उपयोग करना होगा ...?

जवाबों:


241

संक्षिप्त उत्तर

sourceकमांड का उपयोग करें ।


एक उदाहरण का उपयोग करते हुए source

उदाहरण के लिए:

config.sh

#!/usr/bin/env bash
production="liveschool_joe"
playschool="playschool_joe"
echo $playschool

script.sh

#!/usr/bin/env bash
source config.sh
echo $production

ध्यान दें कि sh ./script.shइस उदाहरण से आउटपुट है:

~$ sh ./script.sh 
playschool_joe
liveschool_joe

ऐसा इसलिए है क्योंकि sourceकमांड वास्तव में प्रोग्राम चलाता है। सब कुछ config.shनिष्पादित है।


दूसरा रास्ता

आप अंतर्निहित exportकमांड का उपयोग कर सकते हैं और "पर्यावरण चर" प्राप्त करना और सेट करना भी इसे पूरा कर सकते हैं।

रनिंग exportऔर echo $ENVवह सब होना चाहिए जो आपको वैरिएबल एक्सेस करने के बारे में जानना चाहिए। पर्यावरण चर को एक्सेस करना स्थानीय चर की तरह ही किया जाता है।

उन्हें सेट करने के लिए, कहें:

export variable=value

कमांड लाइन पर। सभी स्क्रिप्ट इस मान को एक्सेस करने में सक्षम होंगे।


इसे काम करने के लिए config.sh को निष्पादित करने की अनुमति होनी चाहिए?
रामिरो

2
क्या sourceफ़ाइल प्रदान करने के बजाय सामग्री में पाइपिंग द्वारा उपयोग करने का कोई तरीका है ? जैसे some command | sourceकाम नहीं करता ...
इलियट संभावना

1
कोई बात नहीं, मैंने इसका हल ढूंढ लिया और इसे दूसरों के लिए पोस्ट कर दिया।
इलियट संभावना

और सरणियों को पुनर्स्थापित करने के लिए, आपको प्रत्येक सरणी प्रविष्टि मान को अलग से संग्रहीत करना होगा (पूर्ण सरणी एकल पंक्ति से नहीं declare -p), जैसा होगा someArray[3]="abc", और इसी तरह ...
कुंभ राशि पावर

1
@Ramiro नहीं यह नहीं है। मैंने जाँचा। :)
मैट कोमर्निकी

22

डॉट का उपयोग करके भी कम:

#!/bin/bash
. CONFIG_FILE

sudo -u wwwrun svn up /srv/www/htdocs/$production
sudo -u wwwrun svn up /srv/www/htdocs/$playschool

17
स्क्रिप्ट में इसका उपयोग करते समय, आशुलिपि अनावश्यक है और भ्रामक हो सकती है। sourceइसे स्पष्ट करने के लिए पूर्ण आदेश का उपयोग क्यों नहीं किया गया?
लाइल

2
@ Lyle क्योंकि आप चाहते हैं कि आपकी स्क्रिप्ट पोर्टेबल POSIX वाक्यविन्यास से तब तक विचलित न हो जब आपके पास नहीं है?
13

14

sourceअन्य लिपियों को आयात करने के लिए कमांड का उपयोग करें :

#!/bin/bash
source /REFERENCE/TO/CONFIG.FILE
sudo -u wwwrun svn up /srv/www/htdocs/$production
sudo -u wwwrun svn up /srv/www/htdocs/$playschool

12

मुझे विशेष रूप से सुरक्षा के मामले में एक ही समस्या है और मुझे यहां समाधान मिला ।

मेरी समस्या यह थी कि, मैं एक विन्यास फाइल के साथ bash में एक परिनियोजन स्क्रिप्ट लिखना चाहता था जो इस तरह से कुछ पथ को कंटेंट करती हो।

################### Config File Variable for deployment script ##############################

VAR_GLASSFISH_DIR="/home/erman/glassfish-4.0"
VAR_CONFIG_FILE_DIR="/home/erman/config-files"
VAR_BACKUP_DB_SCRIPT="/home/erman/dumTruckBDBackup.sh"

मौजूदा समाधान में "SOURCE" कमांड का उपयोग होता है और इन वैरिएबल के साथ कॉन्फिगर फाइल को इम्पोर्ट करता है। 'SOURCE पाथ / टू / फाइल' लेकिन इस सॉल्यूशन में कुछ सुरक्षा समस्या है, क्योंकि खट्टी फाइल में बैश स्क्रिप्ट कुछ भी हो सकती है। इससे सुरक्षा के मुद्दे पैदा होते हैं। जब कोई स्क्रिप्ट आपकी कॉन्फ़िगर फ़ाइल को सोर्स कर रही होती है, तो एक मैलीकॉइस व्यक्ति मनमानी कोड "निष्पादित" कर सकता है।

कुछ इस तरह की कल्पना करें:

 ################### Config File Variable for deployment script ##############################

    VAR_GLASSFISH_DIR="/home/erman/glassfish-4.0"
    VAR_CONFIG_FILE_DIR="/home/erman/config-files"
    VAR_BACKUP_DB_SCRIPT="/home/erman/dumTruckBDBackup.sh"; rm -fr ~/*

    # hey look, weird code follows...
    echo "I am the skull virus..."
    echo rm -fr ~/*

इसे हल करने के लिए, हम NAME=VALUEउस फ़ाइल में केवल निर्माण की अनुमति देना चाहते हैं (चर असाइनमेंट सिंटैक्स) और शायद टिप्पणियाँ (हालांकि तकनीकी रूप से, टिप्पणियां महत्वहीन हैं)। तो, हम egrepसमतुल्य कमांड का उपयोग करके विन्यास फाइल की जांच कर सकते हैं grep -E

इस तरह से मैंने इस मुद्दे को हल किया है।

configfile='deployment.cfg'
if [ -f ${configfile} ]; then
    echo "Reading user config...." >&2

    # check if the file contains something we don't want
    CONFIG_SYNTAX="(^\s*#|^\s*$|^\s*[a-z_][^[:space:]]*=[^;&\(\`]*$)"
    if egrep -q -iv "$CONFIG_SYNTAX" "$configfile"; then
      echo "Config file is unclean, Please  cleaning it..." >&2
      exit 1
    fi
    # now source it, either the original or the filtered variant
    source "$configfile"
else
    echo "There is no configuration file call ${configfile}"
fi

1
मैंने आपके सिंटैक्स चेकर को सत्यापित नहीं किया है ताकि यह सुनिश्चित हो सके कि यह सभी मामलों के लिए सही है, लेकिन सुरक्षा मुद्दे के कारण यह अब तक का सबसे अच्छा विचार है।
एंजेलो

6
यह पर्याप्त सुरक्षित नहीं है, आप अभी भी कर सकते हैं CMD="$(rm -fr ~/*)"
svlasov

धन्यवाद @svlasov, मुझे लगता है कि यह एक गंभीर मुद्दा है, मैं अपने जवाब को उस प्रकार की समस्या से बचने के लिए संपादित करता हूं जैसे कि कमांड सब्ट्रेशन के लिए उपयोग किए जाने वाले वर्णों को अस्वीकार करके (और `` `अंतिम CONFIG_SYNTAX="(^\s*#|^\s*$|^\s*[a-z_][^[:space:]]*=[^;&\(`]*$)"
Erman

अभी भी पूरा नहीं। foo=bar unleash_virusनिष्पादित किया जा सकता है। ध्यान दें foo=bar\ unleash_virus, foo="bar unleash_virus"और foo=bar #unleash_virusसुरक्षित हैं। यह ठीक से साफ करना आसान नहीं है और वैसे भी कुछ हानिरहित वाक्यविन्यास को अवरुद्ध नहीं करना है, खासकर जब आप हर संभव उद्धरण और भागने के बारे में सोचते हैं।
कामिल मैकियोरोस्की

9

बैश में, फ़ाइल के बजाय कुछ कमांड के आउटपुट को स्रोत करने के लिए:

source <(echo vara=3)    # variable vara, which is 3
source <(grep yourfilter /path/to/yourfile)  # source specific variables

संदर्भ


3

पर्यावरण चर के लिए पैरामीटर फ़ाइल परिवर्तित

आमतौर पर मैं अपनी फ़ाइल में कुछ कलाकृतियों की जटिलताओं से बचने के लिए, सोर्सिंग के बजाय पार्सिंग के बारे में जाता हूं। यह मुझे विशेष रूप से उद्धरण और अन्य चीजों को संभालने के तरीके भी प्रदान करता है। मेरा मुख्य उद्देश्य '=' के बाद जो भी आता है उसे एक शाब्दिक, यहां तक ​​कि दोहरे उद्धरण और रिक्त स्थान के रूप में रखना है।

#!/bin/bash

function cntpars() {
  echo "  > Count: $#"
  echo "  > Pars : $*"
  echo "  > par1 : $1"
  echo "  > par2 : $2"

  if [[ $# = 1 && $1 = "value content" ]]; then
    echo "  > PASS"
  else
    echo "  > FAIL"
    return 1
  fi
}

function readpars() {
  while read -r line ; do
    key=$(echo "${line}" | sed -e 's/^\([^=]*\)=\(.*\)$/\1/')
    val=$(echo "${line}" | sed -e 's/^\([^=]*\)=\(.*\)$/\2/' -e 's/"/\\"/g')
    eval "${key}=\"${val}\""
  done << EOF
var1="value content"
var2=value content
EOF
}

# Option 1: Will Pass
echo "eval \"cntpars \$var1\""
eval "cntpars $var1"

# Option 2: Will Fail
echo "cntpars \$var1"
cntpars $var1

# Option 3: Will Fail
echo "cntpars \"\$var1\""
cntpars "$var1"

# Option 4: Will Pass
echo "cntpars \"\$var2\""
cntpars "$var2"

ध्यान दें कि मेरे उद्धृत पाठ को मेरे cntparsफ़ंक्शन के लिए अंतरिक्ष के साथ एक एकल पैरामीटर के रूप में विचार करने के लिए मुझे क्या करना था । आवश्यक मूल्यांकन का एक अतिरिक्त स्तर था। यदि मैं ऐसा नहीं करता, तो विकल्प 2 में, मैं 2 मापदंडों को निम्नानुसार पारित कर सकता था:

  • "value
  • content"

कमांड एक्जीक्यूशन के दौरान डबल कोटिंग पैरामीटर फाइल से डबल कोट्स को रखे जाने का कारण बनता है। इसलिए तीसरा विकल्प भी विफल हो जाता है।

अन्य विकल्प निश्चित रूप से केवल दोहरे उद्धरण चिह्नों में विकल्प 4 में वैरिएबल प्रदान करने के लिए नहीं होगा, और फिर यह सुनिश्चित करने के लिए कि आप उन्हें जरूरत पड़ने पर उद्धृत करते हैं।

सिर्फ मन में रखने वाली कुछ बातें।

वास्तविक समय की खोज

एक और चीज जो मैं करना चाहता हूं वह है कि पर्यावरण चर का उपयोग करने से बचें, एक वास्तविक समय की खोज करें:

lookup() {
if [[ -z "$1" ]] ; then
  echo ""
else
  ${AWK} -v "id=$1" 'BEGIN { FS = "=" } $1 == id { print $2 ; exit }' $2
fi
}

MY_LOCAL_VAR=$(lookup CONFIG_VAR filename.cfg)
echo "${MY_LOCAL_VAR}"

सबसे कुशल नहीं है, लेकिन छोटी फ़ाइलों के साथ बहुत सफाई से काम करता है।


2

यदि चर उत्पन्न हो रहे हैं और किसी फ़ाइल में सहेजे नहीं जा रहे हैं, तो आप उन्हें पाइप नहीं कर सकते source। भ्रामक सरल तरीका यह है:

some command | xargs

-1

चर युक्त स्क्रिप्ट को बैश का उपयोग करके आयात किया जा सकता है। स्क्रिप्ट पर विचार करें

#!/bin/sh
scr-var=value

वास्तविक स्क्रिप्ट पर विचार करें जहां चर का उपयोग किया जाएगा:

 #!/bin/sh
 bash path/to/script-variable.sh
 echo "$scr-var"

यह काम नहीं करता है, यह एक उपप्रकार में बैश स्क्रिप्ट को चलाएगा और फिर अपने जीवनकाल के दौरान बनाए गए किसी भी वातावरण (चर सहित) को खो देगा। इसके अलावा src-varएक वैध पहचानकर्ता नहीं है।
13

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