mgi*_*ida 7 linux echo coreutils portability
在echo
中coreutils
似乎是无处不在的,但不是每个系统都会有它在同一个地方(一般/bin/echo
)。在echo
不知道它在哪里的情况下调用它的最安全方法是什么?
如果echo
系统上不存在coreutils二进制文件,我对命令失败感到满意——这比回显与我想要的不同。
注意:这里的动机是找到echo
二进制文件,而不是找到一组参数,其中每个 shell 的echo
内置函数都是一致的。例如,似乎没有一种方法可以通过内置的 echo 安全地打印连字符,而不知道您是否在zsh
或 中bash
。
请注意,这coreutils
是一个由 GNU 项目开发的软件包,用于为 GNU 系统提供一组 Unix 基本实用程序。您只能在 GNU 系统(、、、、...)上找到开箱即用的coreutilsecho
。在其他系统上,您会发现不同的(通常具有不同的行为,这是最不可移植的应用程序之一)实现。FreeBSD 会有 FreeBSD ,大多数基于 Linux 的系统会有 busybox ,AIX 会有 AIX ...Debian
trisquel
Cygwin
Fedora
CentOS
echo
echo
echo
echo
有些系统甚至会有不止一个(比如/bin/echo
和/usr/ucb/echo
在 Solaris 上(后者是软件包的一部分,现在在更高版本的 Solaris 中是可选的,例如您可以从中获得的 for GNU 实用程序软件包/usr/gnu/bin/echo
),所有这些都具有不同的 CLI)。
GNUcoreutils
已被移植到大多数类 Unix(甚至非类 Unix,如 MS Windows)系统,因此您可以在大多数系统上编译coreutils
' echo
,但这可能不是您要寻找的。
另请注意,您会发现 的版本之间不兼容coreutils
echo
(例如,它过去不使用 识别\x41
序列-e
),并且其行为可能会受到环境(POSIXLY_CORRECT
变量)的影响。
现在,echo
要从文件系统运行(通过查找$PATH
),就像其他所有内置函数一样,典型的方法是使用env
:
env echo this is not the builtin echo
Run Code Online (Sandbox Code Playgroud)
在zsh
(不模拟其他外壳时),您还可以执行以下操作:
command echo ...
Run Code Online (Sandbox Code Playgroud)
无需执行额外的env
命令。
但我希望上面的文字清楚地表明它对可移植性没有帮助。为了便携性和可靠性,请printf
改用.
# $(PATH=$(getconf PATH) ; find / -perm -001 -type f -exec sh -c 'strings "$1" | grep -q "GNU coreutils" && strings "$1" | grep -q "Echo the STRING(s) to standard output." && printf "%s" "$1"' sh {} \; | head -n 1) --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
or: /bin/echo LONG-OPTION
...
or available locally via: info '(coreutils) echo invocation'
Run Code Online (Sandbox Code Playgroud)
老实说,我认为这是一个坏主意,但这将echo
在合理的环境中找到 coreutils 的工作非常可靠。这些都是与 POSIX 兼容的命令 ( getconf
, find
, sh
, grep
, strings
, printf
, head
),所以它在任何地方的行为都应该相同。该getconf
给我们每个工具的符合POSIX标准的第一个版本的路径,在默认的版本是不规范的情况。
它查找包含可打印字符串“GNU coreutils”和“Echo the STRING(s) to standard output”的任何可执行文件,这些字符串出现在 GNUecho
的--help
输出中并且在程序文本中确实存在。如果有多个副本,它会任意选择它找到的第一个副本。如果没有找到,则失败 -$(...)
扩展为空字符串。
但是,我不会称其为“安全”,因为系统上任何地方都存在此(可执行)脚本会给您带来一些麻烦:
#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /
Run Code Online (Sandbox Code Playgroud)
所以重申一下,我认为这是一个非常糟糕的主意。除非您打算将已知echo
s 的哈希列入白名单,否则没有合理的、可移植的方法来找到可以安全地在未知系统上运行的给定版本。在某些时候,您将不得不根据猜测运行一些东西。
我鼓励您改用printf
命令,它接受格式和您想从字面上使用的任何参数。
# printf '%s' -e
-e
Run Code Online (Sandbox Code Playgroud)
printf
在 POSIX 中,如果您提供格式,则所有系统的行为方式都相同。
就我个人而言,我echo
完全避免在我的 shell 脚本中使用,printf '%s\n' blablabla
当字符串很短时使用here-document,当字符串很长时使用。
引用autoconf 手册的第11.14 节 Shell Builtins 的限制:
回声
简单
echo
可能是可移植性问题最令人惊讶的来源。echo
除非选项和转义序列都被省略,否则无法移植。不要指望任何选择。不要在参数中使用反斜杠,因为对它们的处理没有达成共识。为
echo '\n' | wc -l
,所述sh
的的Solaris输出2
,但击和岩组(在sh
仿真模式)输出1
。问题是真的echo
:所有的 shell 都理解'\n'
为由反斜杠和n
. 中的命令置换,echo 'string\c'
会搞乱的内部状态ksh88上AIX 6.1,使得其将打印的第一个字符s
只,跟着一个新行,然后完全丢弃在下一个回波的输出在一个命令替换。由于这些问题,请勿将包含任意字符的字符串传递给
echo
. 例如,echo "$foo"
只有当您知道foo的值不能包含反斜杠且不能以 开头时才是安全的-
。如果这可能不是真的,
printf
通常比echo
and更安全和更容易使用echo -n
。因此,可移植性不是主要问题的脚本应该printf '%s\n'
在echo
可能失败时使用,并且类似地使用printf %s
代替echo -n
. 对于可移植的 shell 脚本,建议使用这样的 here-document:
cat <<EOF
$foo
EOF
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1480 次 |
最近记录: |