Bash script - How to reference a file for variable

2019-01-06 09:11发布

问题:

Hi I want to call a settings file for a variable, how can I do this in bash?

So the settings file will define the variables (eg: CONFIG.FILE) :

production="liveschool_joe"
playschool="playschool_joe"

And the script will use those variables in it

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

How can I get bash to do something like that? Will I have to use awk/sed etc...?

回答1:

The short answer

Use the source command.


An example using source

For example:

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

Note that the output from sh ./script.sh in this example is:

~$ sh ./script.sh 
playschool_joe
liveschool_joe

This is because the source command actually runs the program. Everything in config.sh is executed.


Another way

You could use the built-in export command and getting and setting "environment variables" can also accomplish this.

Running export and echo $ENV should be all you need to know about accessing variables. Accessing environment variables is done the same way as a local variable.

To set them, say:

export variable=value

at the command line. All scripts will be able to access this value.



回答2:

even shorter using the dot:

#!/bin/bash
. CONFIG_FILE

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


回答3:

Use the source command to import other scripts:

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


回答4:

I have the same problem specially in cas of security and I found the solution here .

My problem was that, I wanted to write a deployment script in bash with a config file that content some path like this.

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

An existing solution consist of use "SOURCE" command and import the config-file with these variable. 'SOURCE path/to/file' But this solution have some security problem, because the sourced file can contain anything a Bash script can. That creates security issues. A malicicios person can "execute" arbitrary code when your script is sourcing its config file.

Imagine something like this:

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

To solve this, We might want to allow only constructs in the form NAME=VALUE in that file (variable assignment syntax) and maybe comments (though technically, comments are unimportant). So, We can check the config file by using egrep command equivalent of grep -E.

This is how I have solve the issue.

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


回答5:

in Bash, to source some command's output, instead of a file:

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

reference



回答6:

If the variables are being generated and not saved to a file you cannot pipe them in into source. The deceptively simple way to do it is this:

some command | xargs


回答7:

config.env

var1='foo'

script.sh

export $(cat config.env | grep -v ^# | xargs)
echo $var1


回答8:

Converting parameter file to Environment variables

Usually I go about parsing instead of sourcing, to avoid complexities of certain artifacts in my file. It also offers me ways to specially handle quotes and other things. My main aim is to keep whatever comes after the '=' as a literal, even the double quotes and spaces.

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

Note the little trick I had to do to consider my quoted text as a single parameter with space to my cntpars function. There was one extra level of evaluation required. If I wouldn't do this, as in Option 2, I would have passed 2 parameters as follows:

  • "value
  • content"

Double quoting during command execution causes the double quotes from the parameter file to be kept. Hence the 3rd Option also fails.

The other option would be of course to just simply not provide variables in double quotes, as in Option 4, and then just to make sure that you quote them when needed.

Just something to keep in mind.

Real-time lookup

Another thing I like to do is to do a real-time lookup, avoiding the use of environment variables:

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

Not the most efficient, but with smaller files works very cleanly.



回答9:

The script containing variables can be executed imported using bash. Consider the script-variable.sh

#!/bin/sh
scr-var=value

Consider the actual script where the variable will be used :

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