【问题标题】:difference between "exec" and "exit" in bashbash中“exec”和“exit”的区别
【发布时间】:2012-01-16 00:21:43
【问题描述】:

我已经看到 bash 脚本中使用“exit”和“exec”来在发生错误时停止脚本执行。例如:

if [ ! -f file ]; then
echo "no file"
exit 1
fi

和:

if [ ! -f file ]; then
exec echo "no file"
fi

这里的最佳做法是什么?为什么?也欢迎有关“执行”和“退出”的更广泛讨论/解释:)

【问题讨论】:

    标签: bash exec exit


    【解决方案1】:

    exit 只是退出 shell,将指定的数字退出代码(如果省略,则返回 0)返回给父进程。它相当于 C 库例程也称为 exit,或从 main 返回。

    exec 用新的可执行映像替换 shell(仍在同一进程中运行),该映像将在适当的时候退出并将一些代码或其他代码返回给父进程。大致相当于C库例程execvp

    您的第一个示例几乎是但不完全是在发生错误时停止脚本的正确方法。它应该是

    if [ ! -f file ]; then
        echo "no file" >&2
        exit 1
    fi
    

    您的示例中缺少>&2,导致错误消息转到它所属的stderr,而不是不属于它的stdout

    你的第二个例子是错误。除了错误信息出现在错误的地方之外,exec echo 将停止脚本(因为/bin/echo 将执行它的操作然后退出)但它会将退出代码 0 返回给父进程。退出代码 0 表示成功。在 Unix 环境中运行的程序必须始终确保在失败时返回一个非零退出代码。

    exec 的正确用法是在 shell 脚本中进行一些设置工作,然后调用用另一种语言编写的长期存在的程序,之后没有任何事情可做,因此保留shell进程挂在身边。例如:

    #! /bin/sh
    PATH=/special/directory/for/foo:$PATH
    export PATH
    exec foo
    

    【讨论】:

    • 扎克,谢谢你的回答!所以你的意思是 exec 主要用于在 shell 脚本为这个长期存在的程序完成一些内务和/或配置工作后执行一个长期存在的程序?并且使用 exec 调用的程序将采用包含 exec 的脚本的 PID?另外,bash exec还有其他流行的用途吗?
    • 好的,但是如果在没有 exec 的情况下从脚本调用这个长期存在的程序有什么缺点/区别?我的意思是在这种情况下会有两个 PID,并且在脚本中设置的变量可能对长期运行的程序没有影响?还有什么?
    • 在任何一种情况下,环境变量都会继承到长生命周期的程序;唯一重要的是你是否记得export他们。如果没有exec,则有两个PID,shell 挂起占用RAM,你必须记住在下一行写exit $? 以获取传播到祖父进程的退出代码。就是这样。
    • 扎克,谢谢你的解释!但是,看起来不需要使用exit $? 吗?检查这两个示例:pastebin.com/Sax5SVGa 如您所见,在第二个示例中,我没有使用 exec,但仍然得到了正确的退出代码。还是我误会了你?
    • 有时 shell 脚本中最后一个命令的退出代码会传播到 shell 的父级,但它不是可以依赖的东西,即使标准说吧。
    【解决方案2】:

    命令exit 使用给定的退出代码退出当前shell。命令exec 用参数定义的新进程替换当前shell。这也有效地在进程终止后终止脚本,退出代码是新进程的退出代码。

    第一个代码 sn-ps 调用内部 shell 命令echo,然后以退出代码 1 终止 shell。第二个代码用外部程序 echo 替换 shell,它可能会以退出代码终止0.

    我肯定会推荐第一个变体。它节省了启动外部命令/bin/echo 并正确指示退出代码的错误。

    【讨论】:

      【解决方案3】:

      指示错误的正确方法是让脚本返回一个非零代码,例如 1。 在您的情况下,最好的方法是使用“exit 1”。

      使用“exec”将简单地执行它之后的代码。也许您看到的示例是使用“#!/bin/bash -e”或“set -e”,然后使用“exec”调用失败的代码,从而导致“exec”本身返回非零代码,并且“-e”表示如果任何命令返回非零代码或计算结果为假,则立即退出脚本。

      【讨论】:

      • exec 用新进程替换当前 shell,有效地终止脚本,不管 set -e 或类似的。
      猜你喜欢
      • 2012-03-14
      • 1970-01-01
      • 2023-04-02
      • 2016-12-08
      • 2011-09-23
      • 2011-07-22
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多