Wie verweise ich mit Bash auf eine Datei für Variablen?


150

Ich möchte eine Einstellungsdatei für eine Variable aufrufen. Wie kann ich dies in Bash tun?

Die Einstellungsdatei definiert also die Variablen (z. B. CONFIG.FILE):

production="liveschool_joe"
playschool="playschool_joe"

Und das Skript verwendet diese Variablen darin

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

Wie kann ich Bash dazu bringen, so etwas zu tun? Muss ich awk / sed etc ... verwenden?

Antworten:


240

Die kurze Antwort

Verwenden Sie den sourceBefehl.


Ein Beispiel mit source

Beispielsweise:

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

Beachten Sie, dass die Ausgabe sh ./script.shin diesem Beispiel wie folgt lautet:

~$ sh ./script.sh 
playschool_joe
liveschool_joe

Dies liegt daran, dass der sourceBefehl das Programm tatsächlich ausführt. Alles in config.shwird ausgeführt.


Ein anderer Weg

Sie könnten das eingebaute verwenden export Befehl verwenden, und das Abrufen und Festlegen von "Umgebungsvariablen" kann dies ebenfalls erreichen.

Laufen exportundecho $ENV sollte alles sein, was Sie über den Zugriff auf Variablen wissen müssen. Der Zugriff auf Umgebungsvariablen erfolgt auf die gleiche Weise wie bei einer lokalen Variablen.

Um sie einzustellen, sagen Sie:

export variable=value

an der Kommandozeile. Alle Skripte können auf diesen Wert zugreifen.


Muss config.sh über eine Ausführungsberechtigung verfügen, damit dies funktioniert?
Ramiro

2
Gibt es eine Möglichkeit, sourceden Inhalt weiterzuleiten, anstatt eine Datei bereitzustellen? Wie some command | sourcefunktioniert nicht ...
Elliot Chance

1
Trotzdem habe ich die Lösung gefunden und für andere veröffentlicht.
Elliot Chance

und um Arrays wiederherzustellen, müssen Sie jeden Array-Eintragswert separat speichern (nicht die vollständige Array-Einzelzeile von declare -p), würde wie folgt aussehen someArray[3]="abc"...
Aquarius Power

1
@ Ramiro nein tut es nicht. Ich überprüfte. :)
Matt Komarnicki

22

noch kürzer mit dem Punkt:

#!/bin/bash
. CONFIG_FILE

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

17
Wenn Sie dies in einem Skript verwenden, ist die Kurzschrift nicht erforderlich und kann verwirrend sein. Warum nicht den vollständigen sourceBefehl verwenden, um dies zu verdeutlichen?
Lyle

2
@Lyle Weil Sie möchten, dass Ihr Skript nicht unbegründet von der portablen POSIX-Syntax abweicht, wenn Sie dies nicht müssen?
Tripleee

14

Verwenden Sie den sourceBefehl, um andere Skripte zu importieren:

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

Ich habe das gleiche Problem speziell im Sicherheitsbereich und habe hier die Lösung gefunden .

Mein Problem war, dass ich ein Bereitstellungsskript in bash mit einer Konfigurationsdatei schreiben wollte, die einen Pfad wie diesen enthält.

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

Eine vorhandene Lösung besteht darin, den Befehl "SOURCE" zu verwenden und die Konfigurationsdatei mit dieser Variablen zu importieren. 'SOURCE path / to / file' Diese Lösung weist jedoch einige Sicherheitsprobleme auf, da die Quelldatei alles enthalten kann, was ein Bash-Skript kann. Das schafft Sicherheitsprobleme. Eine Malicicios-Person kann beliebigen Code "ausführen", wenn Ihr Skript seine Konfigurationsdatei bezieht.

Stellen Sie sich so etwas vor:

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

Um dies zu lösen, möchten wir möglicherweise nur Konstrukte im Formular NAME=VALUEin dieser Datei (Syntax der Variablenzuweisung) und möglicherweise Kommentare zulassen (obwohl Kommentare technisch gesehen unwichtig sind). Wir können also die Konfigurationsdatei mit dem egrepBefehl äquivalent von überprüfengrep -E .

So habe ich das Problem gelöst.

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
Ich habe Ihre Syntaxprüfung nicht überprüft, um sicherzustellen, dass sie alle Fälle korrekt berücksichtigt, aber dies ist aufgrund des Sicherheitsproblems bei weitem die beste Idee.
Angelo

6
Das ist nicht sicher genug, das können Sie trotzdem CMD="$(rm -fr ~/*)".
Svlasov

Danke @svlasov, ich denke, es ist ein ernstes Problem. Ich bearbeite meine Antwort, um diese Art von Problem zu vermeiden, indem ich Zeichen ablehne, die für die Befehlssubstitution verwendet werden, wie (und `` `das Finale CONFIG_SYNTAX="(^\s*#|^\s*$|^\s*[a-z_][^[:space:]]*=[^;&\(`]*$)"
Erman

Immer noch nicht genug. foo=bar unleash_virusausgeführt werden kann. Beachten Sie foo=bar\ unleash_virus, foo="bar unleash_virus"und foo=bar #unleash_virussicher sind. Es ist nicht einfach, richtig zu bereinigen und keine harmlose Syntax zu blockieren, besonders wenn man an jedes mögliche Zitieren und Entkommen denkt.
Kamil Maciorowski

9

in Bash, um die Ausgabe eines Befehls anstelle einer Datei zu beziehen:

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

Referenz


3

Konvertieren der Parameterdatei in Umgebungsvariablen

Normalerweise analysiere ich statt Sourcing, um die Komplexität bestimmter Artefakte in meiner Datei zu vermeiden. Es bietet mir auch Möglichkeiten, Angebote und andere Dinge speziell zu behandeln. Mein Hauptziel ist es, alles, was nach dem '=' steht, als Literal beizubehalten, auch die doppelten Anführungszeichen und Leerzeichen.

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

Beachten Sie den kleinen Trick, den ich machen musste, um meinen zitierten Text als einen einzelnen Parameter mit Platz für meine cntparsFunktion zu betrachten. Es war eine zusätzliche Bewertungsebene erforderlich. Wenn ich dies nicht wie in Option 2 tun würde, hätte ich 2 Parameter wie folgt übergeben:

  • "value
  • content"

Durch doppelte Anführungszeichen während der Befehlsausführung werden die doppelten Anführungszeichen aus der Parameterdatei beibehalten. Daher schlägt auch die 3. Option fehl.

Die andere Option wäre natürlich, einfach keine Variablen in doppelten Anführungszeichen wie in Option 4 anzugeben und dann nur sicherzustellen, dass Sie sie bei Bedarf in Anführungszeichen setzen.

Nur etwas zu beachten.

Echtzeitsuche

Eine andere Sache, die ich gerne mache, ist eine Echtzeitsuche, bei der die Verwendung von Umgebungsvariablen vermieden wird:

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

Nicht die effizienteste, aber mit kleineren Dateien funktioniert sehr sauber.


2

Wenn die Variablen generiert und nicht in einer Datei gespeichert werden, können Sie sie nicht weiterleiten source. Der täuschend einfache Weg, dies zu tun, ist folgender:

some command | xargs

-1

Das Skript mit Variablen kann mit bash importiert ausgeführt werden. Betrachten Sie die script-variable.sh

#!/bin/sh
scr-var=value

Betrachten Sie das eigentliche Skript, in dem die Variable verwendet wird:

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

Dies funktioniert nicht. Es führt das Bash-Skript in einem Unterprozess aus und verliert dann alle Umgebungen (einschließlich Variablen), die es während seiner Lebensdauer erstellt hat. Auch src-varist keine gültige Kennung.
Tripleee

-1

Importieren Sie nur die Variablen, die Sie benötigen, um Namenskonflikte zu vermeiden:

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

    echo $(
        source "${file}";
        eval echo \$\{${variable}\}
    )
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.