277

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

4

2 回答 2

305

exec内置命令镜像内核中的函数,有一个基于 的家族,通常execve从 C 中调用。

exec在当前进程中替换当前程序,而不fork创建新进程。您不会在编写的每个脚本中都使用它,但它有时会派上用场。以下是我使用过的一些场景;

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

     exec appln-program
    

    所以现在没有shell可以回去了。即使appln-program崩溃,最终用户也无法访问 shell,因为它不存在 - 被exec替换了。

  2. 我们想使用与 /etc/passwd 中的不同的 shell。尽管看起来很愚蠢,但有些网站不允许用户更改他们的登录 shell。我知道的一个网站让每个人csh.loginksh. 虽然这有效,但它留下了一个杂散的csh进程运行,并且注销是两个阶段,这可能会让人感到困惑。因此我们将其更改为exec ksh仅用 korn shell 替换了 c-shell 程序,并使一切变得更简单(这还有其他问题,例如它ksh不是登录 shell)。

  3. 只是为了节省流程。如果我们调用prog1 -> prog2 -> prog3 -> prog4etc. 并且永远不会返回,那么让每个调用都成为一个 exec。它节省了资源(不可否认,除非重复)并使关机更简单。

您显然已经exec在某处看到使用过,也许如果您展示了困扰您的代码,我们可以证明它的使用是合理的。

编辑:我意识到我上面的答案是不完整的。在 shell中有两种用法,例如和- 用于打开文件描述符。这里有些例子:execkshbash

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

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

  exec 3 < thisfile       # oops, overwrite the current program with command "3"

有几种方法可以使用它们,在 ksh 上使用read -uprint -u, on bash,例如:

read <&3
echo stuff >&4
于 2013-08-21T07:40:28.050 回答
49

只是用一个对新手友好的简短答案来增加接受的答案,您可能不需要exec.

如果您还在这里,那么下面的讨论应该有望揭示原因。当你跑步时,说,

sh -c 'command'

您运行一个sh实例,然后command作为该sh实例的子级启动。完成command时,sh实例也完成。

sh -c 'exec command'

运行一个sh实例,然后用二进制文件替换sh实例,然后运行它。command

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

command

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

#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command

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

类似地,如果您想在 shell 脚本末尾为繁重的命令释放尽可能多的资源,您可能希望exec将该命令作为优化。

如果某些东西迫使您运行sh,但您确实想运行其他东西,那么exec something else当然是替换不需要的实例的一种解决方法sh(例如,如果您真的想运行自己的 spiffygosh而不是sh但您的没有列出,/etc/shells那么您可以'不要将其指定为您的登录外壳)。

exec操作文件描述符的第二个用途是一个单独的主题。接受的答案很好地涵盖了这一点;为了保持这种独立性,我将按照手册来处理exec后面跟着重定向而不是命令名的任何内容。

于 2016-07-26T05:01:42.207 回答