exec命令在shell脚本中有什么用处?

use*_*564 241 unix shell exec

谁能用简单的例子解释shell脚本中exec命令的用途是什么?

cda*_*rke 271

exec内核中的内置命令镜功能,还有他们家的基础上execve,这通常是由被称为C.

exec无需fork新流程即可替换当前流程中的当前程序.在你编写的每个剧本中都不会使用它,但它偶尔会派上用场.以下是我使用过的一些场景;

  1. 我们希望用户在不访问shell的情况下运行特定的应用程序.我们可以在/ etc/passwd中更改登录程序,但也许我们希望从启动文件中使用环境设置.所以,在(比方说)中.profile,最后一个声明说:

     exec appln-program
    
    Run Code Online (Sandbox Code Playgroud)

    所以现在没有贝壳可以回去了.即使appln-program崩溃,最终用户也无法进入shell,因为它不存在 - exec取而代之.

  2. 我们想在/ etc/passwd中使用不同的shell.看起来很愚蠢,有些网站不允许用户更改他们的登录shell.我知道一个网站每个人都开始csh,每个人都只是在他们的.login(csh启动文件)中调用ksh.虽然这样做有效,但它会导致一个流浪的csh进程,并且注销是两个阶段,可能会让人感到困惑.所以我们将它更改为exec ksh刚刚用korn shell替换c-shell程序,并使一切变得更简单(还有其他问题,例如ksh不是登录shell 的事实).

  3. 只是为了保存流程.如果我们打电话prog1 -> prog2 -> prog3 -> prog4等等并且永远不会回去,那么让每个电话都成为一名执行官.它节省了资源(不可否认,除非重复),并使关闭更加简单.

你显然已经看到exec过在某个地方使用过,也许如果你展示了那些烦扰你的代码,我们可以证明它的使用是合理的.

编辑:我意识到我上面的答案是不完整的.有2只的使用exec在像炮弹kshbash-用于打开文件描述符.这里有些例子:

exec 3< thisfile          # open "thisfile" for reading on file descriptor 3
exec 4> thatfile          # open "thatfile" for writing on file descriptor 4
exec 8<> tother           # open "tother" for reading and writing on fd 8
exec 6>> other            # open "other" for appending on file descriptor 6
exec 5<&0                 # copy read file descriptor 0 onto file descriptor 5
exec 7>&4                 # copy write file descriptor 4 onto 7
exec 3<&-                 # close the read file descriptor 3
exec 6>&-                 # close the write file descriptor 6
Run Code Online (Sandbox Code Playgroud)

请注意,间距在这里非常重要.如果在fd编号和重定向符号之间放置一个空格,则exec恢复为原始含义:

  exec 3 < thisfile       # oops, overwrite the current program with command "3"
Run Code Online (Sandbox Code Playgroud)

有几种方法可以使用这些,在ksh上使用read -u或者print -u,bash例如:

read <&3
echo stuff >&4
Run Code Online (Sandbox Code Playgroud)

  • 另外还有一个用途,我发现这里非常方便,值得一提,因为它与python web应用程序有关,看起来介于你的(真棒)答案2和3之间.我通常通过[主管]运行wsgi web应用程序(比如django或flask)( http://supervisord.org/running.html)调用[gunicorn](http://gunicorn.org/)应用程序:后者出了名地需要相当多的环境变量,从shell运行gunicorn更方便,更易维护设置一切的脚本,最终`exec gunicorn`将正确的pid返回给主管. (21认同)
  • 另一个用途:将所有脚本的输出重定向到日志文件`exec>.\ logfilename.log 2>&1` (6认同)

tri*_*eee 40

只是为了通过一个简短的新手友好的简短答案来增加接受的答案,你可能不需要exec.

如果你还在这里,下面的讨论应该有希望揭示原因.当你跑步时,比方说,

sh -c 'command'
Run Code Online (Sandbox Code Playgroud)

你运行一个sh实例,然后command作为该sh实例的孩子开始.当command完成后,该sh实例也结束.

sh -c 'exec command'
Run Code Online (Sandbox Code Playgroud)

运行一个sh实例,然后二进制替换sh实例command,然后运行它.

当然,在这种有限的背景下,这两者都是无用的; 你只是想要

command
Run Code Online (Sandbox Code Playgroud)

在某些边缘情况下,您希望shell读取其配置文件,或以某种方式将环境设置为运行准备command.这几乎是唯一exec command有用的情况.

#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command
Run Code Online (Sandbox Code Playgroud)

这做了一些准备环境的东西,以便它包含所需的东西.一旦完成,sh实例就不再需要了,因此只需用进程替换sh实例就可以进行(次要)优化command,而不是将sh其作为子进程运行并等待它,然后在完成后立即退出.

同样,如果要在shell脚本结束时为尽可能多的命令释放尽可能多的资源,您可能希望exec将该命令作为优化.

如果有什么东西迫使你运行,sh但你真的想要运行别的东西,exec something else当然是一种替代不需要的sh实例的解决方法(例如,如果你真的想运行自己的漂亮gosh而不是sh你的,/etc/shells那么你就可以了不要将它指定为您的登录shell.

exec操纵文件描述符的第二个用法是一个单独的主题.接受的答案很好地涵盖了; 为了保持这种自包含,我只是按照手册中的任何地方exec,然后是重定向而不是命令名称.

  • 抵制诱惑,称自己的漂亮贝壳`bush`.当然,这适用于`bash`或者通常也适用于任何流行的Unix shell; 虽然作为@anishsane [notes](http://stackoverflow.com/a/37851568/874188),Bash通过实际执行`exec命令'秘密优化`bash -c'命令'. (2认同)
  • @JonathanLeffler我故意记录了我在新手问题中看到的反模式.这个是由[这个副本](http://stackoverflow.com/questions/38580978/difference-between-running-a-bash-command-with-and-without-exec)提示的,但我之前看过它,所以我想特别介绍一下. (2认同)
  • @JonathanLeffler轻微的措辞调整; 这是否足够,你觉得呢?感谢您的反馈. (2认同)
  • 谢谢 - 我添加了另一个关于此优化的简短段落.如果你有其他异议,或者你只想从不同的角度解释事情,我不是很清楚. (2认同)
  • `exec` 的另一个有用用途是修补参数。让我举个例子。libvirt/xapi 使用一些标准参数调用 qemu。如果我想动态修补一些参数,我会将 `/path/to/qemu` 移动到 `/path/to/qemu.bin` ;在 `/path/to/qemu` 中创建一个 shell 脚本,内容为:`a=("$@"); add_remove_modify_arguments_in_array_a;exec /path/to/qemu.bin "${a[@]}"` (2认同)