Bash kullanarak değişkenler için bir dosyaya nasıl başvurulur?


157

Bir değişken için bir ayarlar dosyası çağırmak istiyorum, bunu bash'da nasıl yapabilirim?

Bu nedenle, ayarlar dosyası değişkenleri tanımlayacaktır (örneğin: CONFIG.FILE)

production="liveschool_joe"
playschool="playschool_joe"

Ve komut dosyası içindeki bu değişkenleri kullanacak

#!/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

Böyle bir şey yapmak için nasıl bash alabilirim? Awk / sed vb. Kullanmak zorunda mıyım?

Yanıtlar:


250

Kısa cevap

sourceKomutu kullanın .


Kullanan bir örnek source

Örneğin:

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.shBu örnekteki çıktının şu olduğunu unutmayın :

~$ sh ./script.sh 
playschool_joe
liveschool_joe

Bunun nedeni, sourcekomutun aslında programı çalıştırmasıdır. İçindeki her şey config.shyürütülür.


Diğer yol

Yerleşik exportkomutu kullanabilirsiniz ve "ortam değişkenlerini" almak ve ayarlamak da bunu başarabilir.

Koşu exportve echo $ENVdeğişkenleri erişme hakkında bilmeniz gereken her olmalıdır. Ortam değişkenlerine erişim, yerel bir değişkenle aynı şekilde yapılır.

Bunları ayarlamak için şunu söyleyin:

export variable=value

komut satırında. Tüm komut dosyaları bu değere erişebilecektir.


Bunun çalışması için config.sh'nin yürütme iznine sahip olması gerekir mi?
Ramiro

2
sourceBir dosya sağlamaktan ziyade içerikte kanal oluşturarak kullanmanın bir yolu var mı ? Beğen some command | sourceçalışmıyor ...
Elliot Chance

1
Boşver, çözümü buldum ve başkaları için postaladım.
Elliot Chance

ve dizileri geri yüklemek için, her dizi giriş değerini ayrı olarak saklamanız gerekir (tüm dizi tek satırını değil declare -p), böyle olur someArray[3]="abc", vb ...
Aquarius Power

1
@Ramiro hayır değil. Kontrol ettim. :)
Matt Komarnicki

23

noktayı kullanarak daha da kısa:

#!/bin/bash
. CONFIG_FILE

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

19
Bunu bir komut dosyasında kullanırken, steno gereksizdir ve kafa karıştırıcı olabilir. Netleştirmek için neden tam sourcekomutu kullanmıyorsunuz ?
Lyle

2
@Lyle Betiğinizin, mecbur olmadığınızda taşınabilir POSIX sözdiziminden gereksiz yere sapmamasını istediğiniz için mi?
üçlü

14

sourceDiğer komut dosyalarını içe aktarmak için komutu kullanın :

#!/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

Aynı sorunu özellikle güvenlik açısından yaşıyorum ve çözümü burada buldum .

Benim sorunum şuydu, bash'de bunun gibi bir yol içeren bir yapılandırma dosyasıyla bir dağıtım betiği yazmak istedim.

################### 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"

Mevcut bir çözüm, "SOURCE" komutunu kullanmaktan ve yapılandırma dosyasını bu değişkenle içe aktarmaktan oluşur. 'KAYNAK yolu / dosyaya' Ancak bu çözümün bazı güvenlik sorunları vardır, çünkü kaynaklı dosya Bash betiğinin yapabileceği her şeyi içerebilir. Bu, güvenlik sorunları yaratır. Bir malicicios kişisi, komut dosyanız kendi yapılandırma dosyasını temin ederken rastgele kod "yürütebilir".

Bunun gibi bir şey hayal edin:

 ################### 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 ~/*

Bunu çözmek için NAME=VALUE, o dosyada yalnızca formdaki yapılara (değişken atama sözdizimi) ve belki yorumlara (teknik olarak olsa da yorumlar önemsizdir) izin vermek isteyebiliriz . Böylece, config dosyasını egrepkomut eşdeğerini kullanarak kontrol edebiliriz grep -E.

Sorunu bu şekilde çözdüm.

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
Tüm durumları doğru hesapladığından emin olmak için sözdizimi denetleyicinizi doğrulamadım, ancak güvenlik sorunu nedeniyle bu açık ara en iyi fikir.
Angelo

6
Bu yeterince güvenli değil, yine de yapabilirsiniz CMD="$(rm -fr ~/*)".
svlasov

Teşekkürler @svlasov, bunun ciddi bir sorun olduğunu düşünüyorum, komut altyazıları için kullanılan (ve `` final CONFIG_SYNTAX="(^\s*#|^\s*$|^\s*[a-z_][^[:space:]]*=[^;&\(`]*$)"
Erman

Hala yeterli değil. foo=bar unleash_virusyürütülebilir. Not foo=bar\ unleash_virus, foo="bar unleash_virus"ve foo=bar #unleash_virusgüvenlidir. Düzgün bir şekilde sterilize etmek ve yine de zararsız bir sözdizimini engellememek kolay değildir, özellikle de her olası alıntıyı ve kaçmayı düşündüğünüzde.
Kamil Maciorowski

Dizileri engellememek için bunu güncellediniz mi? CONFIG_SYNTAX="(^\s*#|^\s*$|^\s*[a-z_][^[:space:]]*=[^;&\(`]*$|[a-z_][^[:space:]]*\+?=\([^;&\(`]*\)$)"
nooblag

10

Bash'de, bir dosya yerine bir komutun çıktısını kaynaklamak için:

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

referans


3

Parametre dosyasını Ortam değişkenlerine dönüştürme

Dosyamdaki bazı yapıların karmaşıklığını önlemek için genellikle kaynak bulmak yerine ayrıştırmaya devam ederim. Ayrıca, alıntıları ve diğer şeyleri özel olarak ele almam için yollar sunuyor. Temel amacım, '=' işaretinden sonra gelen her şeyi, hatta çift tırnak ve boşlukları bile birebir tutmaktır.

#!/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"

Alıntılanan metnimi işlevim için boşluk olan tek bir parametre olarak düşünmek için yapmam gereken küçük numaraya dikkat edin cntpars. Fazladan bir değerlendirme düzeyi gerekiyordu. Bunu yapmazsam, Seçenek 2'deki gibi, 2 parametreyi şu şekilde geçirirdim:

  • "value
  • content"

Komut yürütme sırasında çift tırnak, parametre dosyasındaki çift tırnakların tutulmasına neden olur. Dolayısıyla 3. Seçenek de başarısız olur.

Diğer seçenek, elbette, Seçenek 4'teki gibi değişkenleri çift tırnak içinde sağlamamak ve daha sonra gerektiğinde bunları alıntı yaptığınızdan emin olmaktır.

Sadece akılda tutulması gereken bir şey.

Gerçek zamanlı arama

Yapmaktan hoşlandığım bir diğer şey de ortam değişkenlerinin kullanımından kaçınarak gerçek zamanlı bir arama yapmaktır:

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}"

En verimli değil, ancak daha küçük dosyalarla çok temiz çalışıyor.


2

Değişkenler oluşturuluyorsa ve bir dosyaya kaydedilmiyorsa, onları içine yöneltemezsiniz source. Bunu yapmanın aldatıcı derecede basit yolu şudur:

some command | xargs

-1

Değişkenler içeren betik, bash kullanılarak içe aktarılabilir. Script-variable.sh dosyasını düşünün

#!/bin/sh
scr-var=value

Değişkenin kullanılacağı gerçek komut dosyasını düşünün:

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

Bu işe yaramaz, Bash komut dosyasını bir alt işlemde çalıştırır ve daha sonra yaşam süresi boyunca oluşturduğu tüm ortamı (değişkenler dahil) kaybeder. Ayrıca src-vargeçerli bir tanımlayıcı değildir.
üçlü

-1

Adlandırma çakışmalarını önlemek için yalnızca ihtiyacınız olan değişkenleri içe aktarın:

variableInFile () {
    variable="${1}"
    file="${2}"

    echo $(
        source "${file}";
        eval echo \$\{${variable}\}
    )
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.