4

When I cat /etc/os-release I get the following:

PRETTY_NAME="Kali GNU/Linux Rolling"
NAME="Kali GNU/Linux"
ID=kali
VERSION="2018.1"
VERSION_ID="2018.1"
ID_LIKE=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.kali.org/"
SUPPORT_URL="http://forums.kali.org/"
BUG_REPORT_URL="http://bugs.kali.org/"

How would I grab kali from ID= in bash? How would I grab 2018.1 from VERSION= in bash?

  • Why did you think they would work? – Jesse_b Mar 22 '18 at 12:01
9

you can source the file and use var's value

. /etc/os-release
echo $ID
echo $VERSION

or try with awk

awk -F= '$1=="ID" { print $2 ;}' /etc/os-release

where

  • -F= tell awk to use = as separator
  • $1=="ID" filter on ID
  • { print $2 ;} print value
8

Sourcing and awk are poor ideas

Sourcing these sorts of files with a shell script interpreter is a poor idea, as it introduces yet another place where the malicious can hide shell script to be executed with superuser permissions, or can introduce things like an override for variables like PATH, LANG, and LD_LIBRARY_PATH.

% cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch with subversive \$PATH)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
echo 1>&2 'install -m 0644 /etc/shadow /home/malefactor/etc/ 2>/dev/null'
PATH="/home/malefactor/bin:${PATH}"
%
% ( source /etc/os-release ; command -v start-stop-daemon ; )
install -m 0644 /etc/shadow /home/malefactor/etc/ 2>/dev/null
/home/malefactor/bin/start-stop-daemon
%

Sourcing actually violates one of the defined semantics for /etc/os-release, which is that (to quote its manual) "variable expansion is explicitly not supported".

Similarly, awk as supplied in Archemar's answer does not correctly handle quoting; and any value can be quoted. Notice how Archemar's answer does not address the VERSION value in the question, which the given awk script does not provide the correct value for, because it erroneously retains the quoting and does not handle escape sequences.

% awk -F= '$1=="VERSION" { print $2 ;}' /etc/os-release
"9 (stretch)"      
% awk -F= '$1=="PRETTY_NAME" { print $2 ;}' /etc/os-release
"Debian GNU/Linux 9 (stretch with subversive \$PATH)"
%

/etc/os-release is actually permitted a fairly broad latitude in quoting, and also requires that escape sequences be processed properly. awk is not really the right tool for the job at all, here.

There are other, subtler, problems such as leakage of already set variables into the results if the actual key sought is missing from the file.

% ( source /etc/os-release ; echo $LANG ; )
install -m 0644 /etc/shadow /home/malefactor/etc/ 2>/dev/null
en_GB.UTF-8
%

There's also the fact that if ID or PRETTY_NAME are missing, they are defined as having default values. And on top of that, there's the fallback to /usr/lib/os-release to deal with.

Learning from other people

Files that contain key-equals-value assignments, with sh-style quoting, escaping, and commentary, are a fairly common thing. Some programming languages have library functions for dealing with them directly. The lesson of OpenBSD's rules shift on /etc/rc.conf in OpenBSD 5.6 is that it is the wiser course to use such library functions, if available, or dedicated tools that have nowhere near the capabilities of a full shell interpreter, for processing such files.

From shell scripts, I for one use a tool named read-conf to process such files:

% read_os() {
    if test -r /etc/os-release
    then
        clearenv setenv "$1" "$2" read-conf /etc/os-release "`command -v printenv`" "$1"
    else
        clearenv setenv "$1" "$2" read-conf /usr/lib/os-release "`command -v printenv`" "$1"
    fi
}
% read_os ID linux
debian
% read_os VERSION
9 (stretch)
% read_os PRETTY_NAME Linux
Debian GNU/Linux 9 (stretch with subversive $PATH)
% read_os PATH
/home/malefactor/bin:${PATH}
% read_os LANG
%

Notice the careful use of command -v to avoid searching for printenv after the infected configuration file has maliciously set an altered PATH. (One of these days, I'll add a built-in printenv that read-conf can chain to.)

Further reading

  • Theo de Raadt et al. (2014-11-01). OpenBSD 5.6 Changelog. OpenBSD.
  • Jonathan de Boyne Pollard (2018). "read-conf". Manual. nosh toolset. Softwares.
  • Jonathan de Boyne Pollard (2018). "clearenv". Manual. nosh toolset. Softwares.
  • Jonathan de Boyne Pollard (2018). "setenv". Manual. nosh toolset. Softwares.
  • Jonathan de Boyne Pollard (2018). "printenv". Manual. nosh toolset. Softwares.
  • Guilty !! I would have tought that only root can write /etc/os-release and root have no need to deploy malevolent script. Thoses seems fine manual you speak about ... – Archemar Mar 31 '18 at 16:38
0
ID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
VERSION=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"')
echo $ID:$VERSION

For the explanation see the other two great answers:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.