【问题标题】:How do I prevent bash to use a builtin command?如何防止 bash 使用内置命令?
【发布时间】:2015-06-14 22:32:42
【问题描述】:

我正在尝试修复使用 echo 的脚本,即使用内置命令而不是命令,我该如何防止这种情况发生?

我知道我可以通过 /bin/echo 强制使用它,但我不想硬编码路径(为了可移植性)。

我认为使用以下内容:

$ECHO=`which echo`
$ECHO -e "text\nhere"

但which echo 返回:“echo: shell 内置命令”。


我最终定义了一个echo 函数,该函数使用@Kenster 推荐的env。这样我就不需要在脚本中修改调用 echo 了。

echo() {
  env echo $*
}

# the function is called before the built-in command.
echo -en "text\nhere"

【问题讨论】:

  • '内置命令而不是命令'WTF?
  • 我相信某些命令(如echo)可以相当可靠地硬编码路径。
  • 如果您关心可移植性,请使用printf,而不是任何形式的echo。
  • @MichaelJaros 非内置 echo 支持 -e 添加转义序列和 -n 以防止尾随新行。
  • 已删除(且不正确)的答案建议使用 command 内置函数:command echo ...。这不起作用,因为command 绕过了 shell 函数,但没有绕过内置命令。我在这里提到这一点是为了那些无法阅读已删除答案并可能尝试使用command的人。

标签: bash sh built-in


【解决方案1】:

您可以禁用内置回声:

enable -n echo

现在只需执行echo anything 即可运行外部版本。它只影响当前的脚本进程,因此您可以在脚本中安全地执行此操作。

【讨论】:

  • 酷,我不知道。 enable 是内置命令吗?它在sh 中有效吗?
  • enable 是 bash 内置的(当然,除非你是 enable -n enable!)。它在 POSIX sh 中不起作用,因为 POSIX 没有内置与外部的真正概念。
  • 当我和builtin 和enable 在一起时,首先想到的是enable -n enable :D。
【解决方案2】:

使用env 程序。 Env 是一个命令,它启动另一个可能修改过的环境的程序。因为 env 是一个程序,所以它无法访问 shell 内置函数、别名等。

这个命令将运行 echo 程序,在你的命令路径中搜索它:

$ env echo foo

您可以通过在运行echo 与env echo 时使用strace 来监控系统调用来验证这一点:

$ strace -f -e trace=process bash -c 'echo foo'
execve("/bin/bash", ["bash", "-c", "echo foo"], [/* 16 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f153fa14700) = 0
foo
exit_group(0)                           = ?

$ strace -f -e trace=process bash -c 'env echo foo'
execve("/bin/bash", ["bash", "-c", "env echo foo"], [/* 16 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f474eb2e700) = 0
execve("/usr/bin/env", ["env", "echo", "foo"], [/* 16 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f60cad15700) = 0
execve("/usr/local/sbin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/local/bin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/sbin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory)
execve("/usr/bin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory)
execve("/sbin/echo", ["echo", "foo"], [/* 16 vars */]) = -1 ENOENT (No such file or directory)
execve("/bin/echo", ["echo", "foo"], [/* 16 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f0146906700) = 0
foo
exit_group(0)                           = ?

【讨论】:

  • 我最终使用了您的解决方案,但使用了一个函数来简化实现:echo() { env echo $* } 效果很好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多