当我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)
我将如何kali
从ID=
bash 中抓取?我将如何2018.1
从VERSION=
bash 中抓取?
Jde*_*eBP 19
awk
是糟糕的想法采购这些类型的文件与一个shell脚本解释器是一个贫穷的想法,因为它引入了另一个哪里有超级用户权限执行恶意可以隐藏shell脚本,或者可以引入之类的东西变量的覆盖喜欢的地方PATH
,LANG
和LD_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 %
还有一个事实是,如果ID
或PRETTY_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依赖setenv
,read-conf
以及printenv
这些命令所内置的NOSH工具集的命令,从而使clearenv
,setenv
和read-conf
每一个发现在链中的下一个命令,而无需使用PATH
环境变量都没有。(我加之前内置的printenv
,稍长原来的单行做了精心的使用"`command -v printenv`"
,以避免搜索用于printenv
后受感染的配置文件有恶意设置改变PATH
,并且之后clearenv
抹去了从环境变量。)
read-conf
”。 手册. nosh 工具集。软件。clearenv
”。 手册. nosh 工具集。软件。setenv
”。 手册. nosh 工具集。软件。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 ;}
打印值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)
有关解释,请参阅其他两个很好的答案: