在 bash 中运行“exec echo some;echo test”是否永远不会打印“some test”?

hum*_*ace 5 shell exec

exec echo "some "; echo "test"在 bash 中运行永远不会打印“一些测试”吗?

我会寻求对这个问题的确认,因为我正在编写一个小的 shell 脚本,并且我希望它exec在调用命令后不要继续执行任何操作。

我认为我不需要担心,根据我的理解,经过咨询:

  • man 3 exec
  • man 1p exec

shell 脚本,当由 shell 执行时,会生成

  1. shell 执行程序exec,其中
  2. 使用exec***家族系统调用来替换正在执行脚本的 shell/bash,这会阻止shell 的进一步操作(已被“替换”)

如前所述,这个问题的主要目标是为我的推理寻求确认,以防止在执行 exec (例如echo test)之后脚本中发生任何事情。

我希望尽可能提供一般性答案(POSIX),但以防万一,我对 GNU/Linux 和 GNU/Bash 最感兴趣

ilk*_*chu 6

对,如果exec成功了就替换当前的shell,所以下面的命令不会,err..执行。

但是,至少在 Bash 中,如果exec 失败,shell 也会退出:

exec [-cl] [-a name] [command [arguments]]

如果提供了命令,它将替换外壳而不创建新进程。[...] 如果由于某种原因无法执行命令,则会退出非交互式 shell,除非execfail启用了shell 选项。在这种情况下,它返回失败。

因此,即使是类似的内容bash -c 'exec /bin/nosuchfile; echo foo'也只会打印有关丢失程序文件的错误消息。要处理脚本中的错误,您需要类似

#!/bin/bash
shopt -s execfail
exec /someprogram
echo whoops, it failed
Run Code Online (Sandbox Code Playgroud)

但是,您仍然会从exec. 如果您在 上放置了重定向exec如果脚本在exec失败后继续,它会保持有效

  • 这也是 POSIX 的要求。`exec` 是一个 _special 内置函数,它的失败(至少在非交互式时)必须是致命的。 (2认同)

Gil*_*il' 5

exec内建(与命令argument¹)替换壳process²。不会执行 shell 进程中的后续代码。

因此,exec echo "some "; echo "test"打印的唯一方法some textecho在 PATH 中调用一个可执行命令,并且打印此可执行文件some text而不是some. 在正常情况下,echo可执行文件的行为与对名为echo.

如果echoPATH中没有调用可执行文件或执行失败,exec则会显示错误信息并退出shell。即使在这种情况下,echo "test"也不会执行。

¹没有命令参数是一个不同的野兽。它不会替换 shell 进程,它只是应用重定向。 ²在子shell中,只影响子shell,父shell保持正常运行。 exec


Hau*_*ing 3

exec如果脚本执行命令并且成功执行,则总是完成脚本(与命令的退出代码无关,但与启动它相关)。

exec可以在没有命令的情况下以非常有用的方式运行:永久重定向文件描述符:

exec 3>/path/to/file
Run Code Online (Sandbox Code Playgroud)

如果该命令无法启动,则 shell 行为取决于配置。bash默认退出。

您最好使用函数来代替:

safe_exec () {
    cmd="$1"
    if test -z "$cmd" || ! test -f "$cmd" || ! test -x "$cmd"; then
        exit 1
    else
        exec "$@"
    fi
}

safe_exec echo "some "; echo "test"
Run Code Online (Sandbox Code Playgroud)