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

时间:2021-07-02 21:34:19

Can anyone explain what are the uses of the exec command in shell scripting with simple examples?

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

2 个解决方案

#1


235  

The exec built-in command mirrors functions in the kernel, there are a family of them based on execve, which is usually called from C.

exec内置命令镜像内核中的函数,它们有一个基于execve的系列,通常从C语言调用。

exec replaces the current program in the current process, without forking a new process. It is not something you would use in every script you write, but it comes in handy on occasion. Here are some scenarios I have used it;

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

  1. We want the user to run a specific application program without access to the shell. We could change the sign-in program in /etc/passwd, but maybe we want environment setting to be used from start-up files. So, in (say) .profile, the last statement says something like:

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

     exec appln-program
    

    so now there is no shell to go back to. Even if appln-program crashes, the end-user cannot get to a shell, because it is not there - the exec replaced it.

    所以现在没有贝壳可以回去了。即使appln-program崩溃,最终用户也无法访问shell,因为它不在那里 - exec取代了它。

  2. We want to use a different shell to the one in /etc/passwd. Stupid as it may seem, some sites do not allow users to alter their sign-in shell. One site I know had everyone start with csh, and everyone just put into their .login (csh start-up file) a call to ksh. While that worked, it left a stray csh process running, and the logout was two stage which could get confusing. So we changed it to exec ksh which just replaced the c-shell program with the korn shell, and made everything simpler (there are other issues with this, such as the fact that the ksh is not a login-shell).

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

  3. Just to save processes. If we call prog1 -> prog2 -> prog3 -> prog4 etc. and never go back, then make each call an exec. It saves resources (not much, admittedly, unless repeated) and makes shutdown simplier.

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

You have obviously seen exec used somewhere, perhaps if you showed the code that's bugging you we could justify its use.

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

Edit: I realised that my answer above is incomplete. There are two uses of exec in shells like ksh and bash - used for opening file descriptors. Here are some examples:

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

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

Note that spacing is very important here. If you place a space between the fd number and the redirection symbol then exec reverts to the original meaning:

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

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

There are several ways you can use these, on ksh use read -u or print -u, on bash, for example:

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

read <&3
echo stuff >&4

#2


27  

Just to augment the accepted answer with a brief newbie-friendly short answer, you probably don't need exec.

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

If you're still here, the following discussion should hopefully reveal why. When you run, say,

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

sh -c 'command'

you run a sh instance, then start command as a child of that sh instance. When command finishes, the sh instance also finishes.

你运行一个sh实例,然后启动命令作为该sh实例的子项。命令完成后,sh实例也会完成。

sh -c 'exec command'

runs a sh instance, then replaces that sh instance with the command binary, and runs that instead.

运行一个sh实例,然后用命令binary替换该sh实例,然后运行它。

Of course, both of these are useless in this limited context; you simply want

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

command

There are some fringe situations where you want the shell to read its configuration file or somehow otherwise set up the environment as a preparation for running command. This is pretty much the sole situation where exec command is useful.

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

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

This does some stuff to prepare the environment so that it contains what is needed. Once that's done, the sh instance is no longer necessary, and so it's a (minor) optimization to simply replace the sh instance with the command process, rather than have sh run it as a child process and wait for it, then exit as soon as it finishes.

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

Similarly, if you want to free up as much resources as possible for a heavyish command at the end of a shell script, you might want to exec that command as an optimization.

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

If something forces you to run sh but you really wanted to run something else, exec something else is of course a workaround to replace the undesired sh instance (like for example if you really wanted to run your own spiffy gosh instead of sh but yours isn't listed in /etc/shells so you can't specify it as your login shell).

如果有什么东西强迫你运行sh但是你真的想要运行别的东西,那么执行其他东西当然是一种解决方法来替换不需要的sh实例(例如,如果你真的想要运行自己的spiffy gosh而不是sh但是你的isn isn在/ etc / shells中列出,因此您无法将其指定为登录shell)。

The second use of exec to manipulate file descriptors is a separate topic. The accepted answer covers that nicely; to keep this self-contained, I'll just defer to the manual for anything where exec is followed by a redirect instead of a command name.

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

#1


235  

The exec built-in command mirrors functions in the kernel, there are a family of them based on execve, which is usually called from C.

exec内置命令镜像内核中的函数,它们有一个基于execve的系列,通常从C语言调用。

exec replaces the current program in the current process, without forking a new process. It is not something you would use in every script you write, but it comes in handy on occasion. Here are some scenarios I have used it;

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

  1. We want the user to run a specific application program without access to the shell. We could change the sign-in program in /etc/passwd, but maybe we want environment setting to be used from start-up files. So, in (say) .profile, the last statement says something like:

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

     exec appln-program
    

    so now there is no shell to go back to. Even if appln-program crashes, the end-user cannot get to a shell, because it is not there - the exec replaced it.

    所以现在没有贝壳可以回去了。即使appln-program崩溃,最终用户也无法访问shell,因为它不在那里 - exec取代了它。

  2. We want to use a different shell to the one in /etc/passwd. Stupid as it may seem, some sites do not allow users to alter their sign-in shell. One site I know had everyone start with csh, and everyone just put into their .login (csh start-up file) a call to ksh. While that worked, it left a stray csh process running, and the logout was two stage which could get confusing. So we changed it to exec ksh which just replaced the c-shell program with the korn shell, and made everything simpler (there are other issues with this, such as the fact that the ksh is not a login-shell).

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

  3. Just to save processes. If we call prog1 -> prog2 -> prog3 -> prog4 etc. and never go back, then make each call an exec. It saves resources (not much, admittedly, unless repeated) and makes shutdown simplier.

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

You have obviously seen exec used somewhere, perhaps if you showed the code that's bugging you we could justify its use.

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

Edit: I realised that my answer above is incomplete. There are two uses of exec in shells like ksh and bash - used for opening file descriptors. Here are some examples:

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

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

Note that spacing is very important here. If you place a space between the fd number and the redirection symbol then exec reverts to the original meaning:

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

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

There are several ways you can use these, on ksh use read -u or print -u, on bash, for example:

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

read <&3
echo stuff >&4

#2


27  

Just to augment the accepted answer with a brief newbie-friendly short answer, you probably don't need exec.

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

If you're still here, the following discussion should hopefully reveal why. When you run, say,

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

sh -c 'command'

you run a sh instance, then start command as a child of that sh instance. When command finishes, the sh instance also finishes.

你运行一个sh实例,然后启动命令作为该sh实例的子项。命令完成后,sh实例也会完成。

sh -c 'exec command'

runs a sh instance, then replaces that sh instance with the command binary, and runs that instead.

运行一个sh实例,然后用命令binary替换该sh实例,然后运行它。

Of course, both of these are useless in this limited context; you simply want

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

command

There are some fringe situations where you want the shell to read its configuration file or somehow otherwise set up the environment as a preparation for running command. This is pretty much the sole situation where exec command is useful.

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

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

This does some stuff to prepare the environment so that it contains what is needed. Once that's done, the sh instance is no longer necessary, and so it's a (minor) optimization to simply replace the sh instance with the command process, rather than have sh run it as a child process and wait for it, then exit as soon as it finishes.

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

Similarly, if you want to free up as much resources as possible for a heavyish command at the end of a shell script, you might want to exec that command as an optimization.

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

If something forces you to run sh but you really wanted to run something else, exec something else is of course a workaround to replace the undesired sh instance (like for example if you really wanted to run your own spiffy gosh instead of sh but yours isn't listed in /etc/shells so you can't specify it as your login shell).

如果有什么东西强迫你运行sh但是你真的想要运行别的东西,那么执行其他东西当然是一种解决方法来替换不需要的sh实例(例如,如果你真的想要运行自己的spiffy gosh而不是sh但是你的isn isn在/ etc / shells中列出,因此您无法将其指定为登录shell)。

The second use of exec to manipulate file descriptors is a separate topic. The accepted answer covers that nicely; to keep this self-contained, I'll just defer to the manual for anything where exec is followed by a redirect instead of a command name.

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