从 /etc/os-release 获取操作系统的 ID

Nic*_*mou 11 text-processing

当我cat /etc/os-release得到以下信息时:

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/"
Run Code Online (Sandbox Code Playgroud)

我将如何kaliID=bash 中抓取?我将如何2018.1VERSION=bash 中抓取?

Jde*_*eBP 19

采购和awk是糟糕的想法

采购这些类型的文件与一个shell脚本解释器是一个贫穷的想法,因为它引入了另一个哪里有超级用户权限执行恶意可以隐藏shell脚本,或者可以引入之类的东西变量的覆盖喜欢的地方PATHLANGLD_LIBRARY_PATH

% cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (使用颠覆性的 \$PATH 进行扩展)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (拉伸)"
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
%

采购实际上违反了定义的语义之一/etc/os-release,即(引用其手册)“明确不支持变量扩展”。

同样,awk正如 Archemar 的回答所提供的那样,不能正确处理引用;并且可以引用任何值。请注意 Archemar 的答案如何没有解决问题中的VERSION值,给定的awk脚本没有为其提供正确的值,因为它错误地保留了引用并且不处理转义序列。

% awk -F= '$1=="VERSION" { 打印 $2 ;}' /etc/os-release
“9(伸展)”      
% awk -F= '$1=="PRETTY_NAME" { 打印 $2 ;}' /etc/os-release
“Debian GNU/Linux 9(带有颠覆性的 \$PATH)”
%

/etc/os-release实际上在引用方面允许有相当广泛的自由度,并且还要求正确处理转义序列。 awk在这里根本不是适合这项工作的工具。

还有其他更微妙的问题,例如如果文件中缺少实际寻找的密钥,则已经设置的变量会泄漏到结果中。

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

还有一个事实是,如果IDPRETTY_NAME缺失,它们被定义为具有默认值。最重要的是,还有后备/usr/lib/os-release要处理。

向他人学习

包含键等于值赋值的文件,带有sh样式引用、转义和注释,是相当常见的事情。一些编程语言具有直接处理它们的库函数。OpenBSD 规则/etc/rc.conf在 OpenBSD 5.6 中转变的教训是,使用此类库函数(如果可用)或专用工具处理此类文件是更明智的做法,这些工具远不及完整 shell 解释器的功能。

在 shell 脚本中,我使用了一个名为的工具read-conf来处理这些文件:

% read_os() {
    if test -r /etc/os-release
    然后
        clearenv setenv "$1" "$2" read-conf /etc/os-release printenv "$1"
    别的
        clearenv setenv "$1" "$2" read-conf /usr/lib/os-release printenv "$1"
    菲
}
% read_os ID linux
Debian
% read_os 版本
9(拉伸)
% read_os PRETTY_NAME Linux
Debian GNU/Linux 9(使用颠覆性的 $PATH 进行扩展)
% read_os 路径
/home/malefactor/bin:${PATH}
% read_os LANG
%

该aforegiven依赖setenvread-conf以及printenv这些命令所内置的NOSH工具集的命令,从而使clearenvsetenvread-conf每一个发现在链中的下一个命令,而无需使用PATH环境变量都没有。(我加之前内置的printenv,稍长原来的单行做了精心的使用"`command -v printenv`",以避免搜索用于printenv 受感染的配置文件有恶意设置改变PATH,并且之后clearenv抹去了从环境变量。)

进一步阅读

  • Theo de Raadt 等人。(2014-11-01)。OpenBSD 5.6 更新日志。开放式BSD。
  • 乔纳森·德·博因·波拉德 (2018)。“ read-conf”。 手册. nosh 工具集。软件。
  • 乔纳森·德·博因·波拉德 (2018)。“ clearenv”。 手册. nosh 工具集。软件。
  • 乔纳森·德·博因·波拉德 (2018)。“ setenv”。 手册. nosh 工具集。软件。
  • 乔纳森·德·博因·波拉德 (2018)。“ printenv”。 手册. nosh 工具集。软件。


Arc*_*mar 13

您可以获取文件并使用 var 的值

. /etc/os-release
echo $ID
echo $VERSION
Run Code Online (Sandbox Code Playgroud)

或尝试 awk

awk -F= '$1=="ID" { print $2 ;}' /etc/os-release
Run Code Online (Sandbox Code Playgroud)

在哪里

  • -F= 告诉 awk 使用 = 作为分隔符
  • $1=="ID" 过滤 ID
  • { print $2 ;} 打印值

  • 正如 JdeBP 所说,以及 thedailywtf.com 经常指出的那样,“源化”文件是一种冒险的生活方式。 (3认同)

ana*_*nik 9

ID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
VERSION=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"')
echo $ID:$VERSION
Run Code Online (Sandbox Code Playgroud)

有关解释,请参阅其他两个很好的答案: