Add or update a configuration record in /etc/environment

26,584

Solution 1

Instead of trying to parse /etc/environment file, you could instead create a file with your own name in /etc/profile.d/, as I described in my answer to a relevant question. Then you could just copy it over during installation, because it contains just your content. Let alone that it will make your scripts shorter.

Solution 2

grep -q JAVA_HOME /etc/environment || echo 'JAVA_HOME="/usr/lib/jvm/java-5-sun"' >> /etc/environment

The grep command returns 0 (true) if the pattern is found in the file. So, the above reads:

check if JAVA_HOME is set in the file
OR set JAVA_HOME in the file

0-15:49 root@noneedto ~# cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
0-15:49 root@noneedto ~# grep JAVA_HOME /etc/environment && echo true
1-15:49 root@noneedto ~# grep -q JAVA_HOME /etc/environment || echo 'JAVA_HOME="/usr/lib/jvm/java-5-sun"' >> /etc/environment
0-15:49 root@noneedto ~# grep JAVA_HOME /etc/environment && echo true
JAVA_HOME="/usr/lib/jvm/java-5-sun"
true
0-15:49 root@noneedto ~# grep -q JAVA_HOME /etc/environment || echo 'JAVA_HOME="/usr/lib/jvm/java-5-sun"' >> /etc/environment
0-15:49 root@noneedto ~# cat /etc/environment
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
JAVA_HOME="/usr/lib/jvm/java-5-sun"

As you can see, if you invoke this one-liner multiple times, subsequent invocations do not add to the file because grep returns true before you attempt to append the file.

Share:
26,584
Maxim Veksler
Author by

Maxim Veksler

Doing healthy things at K Health

Updated on February 25, 2020

Comments

  • Maxim Veksler
    Maxim Veksler about 4 years

    My /etc/environment looks like this:

    cat /etc/environment
    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
    

    I wish to use a command (sed, awk, python, whatever....) that will make it look like this:

    cat /etc/environment
    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
    JAVA_HOME="/usr/lib/jvm/java-6-sun"
    

    Now the catch is, I would rather it be a 1 liner (in the fields of sed -XYZ /DoMagic/ /etc/environment), it needs to contain merging logic that is - either appends a new configuration record or update an existing one. Bottom line, it should prevent the file from looking like this: (Caused by in experienced shell scripters calling echo >> on each invocation)

    cat /etc/environment
    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
    JAVA_HOME="/usr/lib/jvm/java-5-sun"
    JAVA_HOME="/usr/lib/jvm/java-6-sun"
    JAVA_HOME="/usr/lib/jvm/java-6-sun"
    JAVA_HOME="/usr/lib/jvm/java-6-sun"
    

    I guess this is a trick questions, because what I'm trying to avoid using custom scripts, such as

    /usr/local/bin/PropUpdate /etc/environment JAVA_HOME "/usr/lib/jvm/java-6-sun"
    

    /usr/local/bin/PropUpdate is the following script (written for the sake of example, may contain bugs. Comments are appreciated)

    #!/bin/bash
    
    # Append/Update a configuration record in a file
    #
    # Usage example:
    # /usr/local/bin/PropUpdate /etc/environment JAVA_HOME "/usr/lib/jvm/java-6-sun"
    #
    # Author Maxim Veksler <[email protected]>
    # Version 0.5-2010-07-27
    
    
    EXPECTED_ARGS=3
    E_BADARGS=3
    E_BADFILE=4
    
    if [[ $# -ne ${EXPECTED_ARGS} ]]; then
      echo "Usage: `basename $0` /path/to/config.conf ParameterName newValueText" >&2
      exit $E_BADARGS
    fi
    
    CONFIGURATION_FILE="$1"
    CONFIGURATION_PARAMETER="$2"
    CONFIGURATION_VALUE="$3"
    
    if [[ ! -e "${CONFIGURATION_FILE}" ]]; then
            echo "Configuration file ${CONFIGURATION_FILE} does not exist" >&2
            exit $E_BADFILE
    fi
    
    if [[ ! -w "${CONFIGURATION_FILE}" ]]; then
            echo "Can't modify ${CONFIGURATION_FILE}" >&2
            exit $E_BADFILE
    fi
    
    
    
    #########################################
    ## Decide what parameter we are adding ##
    #########################################
    __param_found=0
    
    # First check CONFIGURATION_PARAMETER supplied by use that contains "="
    if [[ ${CONFIGURATION_PARAMETER} == *=* ]]; then
            # It should exist in the file, plain
            if grep -qE "^${CONFIGURATION_PARAMETER}" "${CONFIGURATION_FILE}"; then
                    __param_found=1
                    SUFFIX_REGEX='[[:space:]]*'
            fi
    else
            # OK, sophisticated user, did not send "=" with the parameter...
            if grep -qE "^${CONFIGURATION_PARAMETER}[[:space:]]*=" "${CONFIGURATION_FILE}"; then
                    # Let's check if such configuration with Parameter + "=" exists
                    __param_found=1
                    SUFFIX_REGEX='[[:space:]]*=[[:space:]]*'
            elif grep -qE "^${CONFIGURATION_PARAMETER}[[:space:]]+" "${CONFIGURATION_FILE}"; then
                    # If such parameter exists, at all
                    __param_found=1
                    SUFFIX_REGEX='[[:space:]]\+'
            fi
    fi
    
    
    if [[ $__param_found == 1 ]]; then
            #echo sed -i "s|^\(${CONFIGURATION_PARAMETER}${SUFFIX_REGEX}\).*$|\1${CONFIGURATION_VALUE}|g" "${CONFIGURATION_FILE}"
            sed -i "s|^\(${CONFIGURATION_PARAMETER}${SUFFIX_REGEX}\).*$|\1${CONFIGURATION_VALUE}|g" "${CONFIGURATION_FILE}"
    
    else
            if [[ ${CONFIGURATION_PARAMETER} == *=* ]]; then
                    # Configuration parameter contains "=" in it's name, good just append
                    echo "${CONFIGURATION_PARAMETER}${CONFIGURATION_VALUE}" >> "${CONFIGURATION_FILE}"
            else
                    # Try to guess if this file is a "param = value" or "param value" type of file.
                    if grep -qE "^[[:alnum:]]+[[:space:]]*=" "${CONFIGURATION_FILE}"; then
                            # Seems like a "param = value" type of file
                            echo "${CONFIGURATION_PARAMETER}=${CONFIGURATION_VALUE}" >> "${CONFIGURATION_FILE}"
                    else
                            # Seems like a "param  value" type of file
                            echo "${CONFIGURATION_PARAMETER} ${CONFIGURATION_VALUE}" >> "${CONFIGURATION_FILE}"
                    fi
            fi
    fi
    
    #cat $CONFIGURATION_FILE
    

    Thank you, Maxim.

    -- Update: I actually kinda liked this script, so I've improved it a bit. It now seems to be production ready. Enjoy.