如何防止 bash 使用内置命令?
How do I prevent bash to use a builtin command?
我正在尝试修复使用 echo
的脚本,即使用内置命令而不是命令,我该如何防止它?
我知道我可以 /bin/echo
强制使用它,但我不想硬编码路径(为了便携性)。
我想使用一些东西作为:
$ECHO=`which echo`
$ECHO -e "text\nhere"
但 which echo
returns: "echo: shell built-in command".
我最终定义了一个使用 env
的 echo
函数,正如@Kenster 所推荐的那样。这样我就不需要修改脚本中对 echo 的调用。
echo() {
env echo $*
}
# the function is called before the built-in command.
echo -en "text\nhere"
使用env
程序。 Env 是启动另一个程序的命令,该程序可能修改了环境。因为 env 是一个程序,所以它无法访问 shell 内置函数、别名和诸如此类的东西。
此命令将 运行 回显程序,在您的命令路径中搜索它:
$ env echo foo
您可以通过使用 strace
监控系统调用来验证这一点,而 运行ning echo
vs env echo
:
$ 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) = ?
您可以禁用内置回显:
enable -n echo
现在只需执行 echo anything
即可 运行 外部版本。它只影响当前的脚本进程,因此您可以安全地在您的脚本中执行此操作。
我正在尝试修复使用 echo
的脚本,即使用内置命令而不是命令,我该如何防止它?
我知道我可以 /bin/echo
强制使用它,但我不想硬编码路径(为了便携性)。
我想使用一些东西作为:
$ECHO=`which echo`
$ECHO -e "text\nhere"
但 which echo
returns: "echo: shell built-in command".
我最终定义了一个使用 env
的 echo
函数,正如@Kenster 所推荐的那样。这样我就不需要修改脚本中对 echo 的调用。
echo() {
env echo $*
}
# the function is called before the built-in command.
echo -en "text\nhere"
使用env
程序。 Env 是启动另一个程序的命令,该程序可能修改了环境。因为 env 是一个程序,所以它无法访问 shell 内置函数、别名和诸如此类的东西。
此命令将 运行 回显程序,在您的命令路径中搜索它:
$ env echo foo
您可以通过使用 strace
监控系统调用来验证这一点,而 运行ning echo
vs env echo
:
$ 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) = ?
您可以禁用内置回显:
enable -n echo
现在只需执行 echo anything
即可 运行 外部版本。它只影响当前的脚本进程,因此您可以安全地在您的脚本中执行此操作。