Shell脚本 - 使用bin / echo而不是echo的原因?

时间:2016-06-21 03:45:28

标签: shell unix

我有一个2011年的shell脚本,其目的是在不同的unix系统上运行。

脚本定义了某些变量,我不明白它背后的逻辑,我想知道为什么这样做。例如:
而不是直接在脚本中使用echogrep,这些变量定义如下:
ECHO="/bin/echo"
GREP="/bin/grep"(对于linux)
对于Solaris或其他,也定义了相应的路径。 然后将它们用作${ECHO} "something out"

这种做法的目的是什么?为什么我不能直接使用它?

3 个答案:

答案 0 :(得分:5)

正如其他人所指出的那样,这些线条不太可能正确,更可能是:

ECHO="/bin/echo"
GREP="/bin/grep"  # (for linux)

假设它们是正确的,这样的代码曾经常见于shell脚本(不是我的,我可能会添加)。你不会再看到很多人使用这些了。<​​/ p>

echoksh(Korn shell,曾经是首选的shell),csh(C-shell,Sun上的默认shell)和sh(它之前的Bourne shell(POSIX)都有自己的echo内置版本,它们略有不同(主要围绕-n参数)。因此,独立程序/bin/echo有时用于可移植性。要为此付出性能代价。

grep和其他人:过去常常建议在脚本中设置外部程序的完整路径名。主要原因是安全性。理论上,用户可以在本地目录中提供自己的版本并更改其PATH变量。 PATH以及所有其他环境变量仍然被许多人视为安全风险。第二个原因是搜索$PATH目录的性能开销 - 这是在跟踪别名(ksh)或散列(bash)的日子之前。

我再说一遍,我不赞同所有这些观点,多年来我与那些观点的观点有争议,但这就是解释。在我看来,这种做法导致的问题多于解决的问题。

编辑:我提到的做法可以追溯到20世纪70年代和80年代。为什么他们会在2011年的剧本中?可能是因为&#34;我们总是这样做&#34;,a.k.a。&#34;公司政策&#34;,即没有人知道或关心为什么,我们只是这样做。或者,也可以是来自旧网站或书籍的复制粘贴,甚至是认为这是个好主意的人。

答案 1 :(得分:4)

这种做法没有充分的理由无论

它减少了脚本的可移植性(通过在移动到具有不同二进制位置的任何系统时需要修改),降低性能(通过在可用时禁止使用shell内置),以及(因为缓存PATH查找)不会显着提高运行时性能通过节省查询成本。

一个警告:在某些系统上,/bin/不是POSIX工具的规范位置;例如,/usr/xpg/bin/sh将是POSIX sh的位置,而/usr/xpg/bin/awk将是POSIX awk的位置,在一些古老的SunOS系统上。

在这样的系统上强制使用符合POSIX标准的工具的错误方法是在脚本顶部定义的变量中对这些路径进行硬编码。

在这样的系统上强制使用符合POSIX标准的工具的正确方法就是指定在/usr/xpg/bin之前放置/bin的PATH。例如,脚本可以指定[ -d /usr/xpg/bin ] && PATH=/usr/xpg/bin:$PATH,从而实现此目的。

或者,假设有人希望使用GNU find。可以根据需要指定一个包装器,而不是在脚本顶部设置一个FIND变量,如果不存在重命名的替代项,则可以使用标准find命令的默认行为:

# use GNU find if under a name other than "find"
if type gnufind >/dev/null 2>&1; then
  find() { gnufind "$@"; }
elif type gfind >/dev/null 2>&1; then
  find() { gfind "$@"; }
fi

答案 2 :(得分:0)

将此答案限制为echo部分。

这可能是使程序可移植的一种尝试,但这是徒劳的。

如果参数可以包含反斜杠或第一个参数为echo,则-n命令本身总是不可移植的。 POSIX表示,在这种情况下,行为将取决于实现。

来源:https://www.gnu.org/software/coreutils/manual/html_node/echo-invocation.html#echo-invocation

dashbash都声称符合POSIX,但是echo 'a\nb'会导致不同的结果。两者都是正确的。我不希望地球上所有独立的echo程序都恰好选择相同的实现。

使代码真正可移植为任何参数的最简单方法是使用printf而不是echo

如果您真的想调用命令echo而不是内置命令,因为您确信您的代码将永远不会在具有不同实现选择的系统上运行command echo是最好的的方法。