有人能用简单的例子解释一下exec命令在shell脚本中的用途吗?
当前回答
只是为了用一个简短的新手友好的简短答案来扩大已接受的答案,您可能不需要exec。
如果你还在这里,下面的讨论有望揭示原因。当你跑步的时候,说,
sh -c 'command'
运行一个sh实例,然后启动命令作为该sh实例的子命令。当命令结束时,sh实例也结束了。
sh -c 'exec command'
运行一个sh实例,然后将该sh实例替换为命令二进制,并运行该sh实例。
当然,这两种方法在这个有限的上下文中都是无用的;你只是想要
command
在一些边缘情况下,您希望shell读取其配置文件或以其他方式设置环境作为运行命令的准备。这几乎是exec命令有用的唯一情况。
#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command
这做了一些准备环境的工作,以便它包含所需的内容。一旦完成了这一步,sh实例就不再需要了,因此简单地用命令进程替换sh实例,而不是让sh作为子进程运行并等待它,然后在它完成时立即退出,这是一个(次要的)优化。
类似地,如果希望为shell脚本末尾的重量级命令释放尽可能多的资源,则可能希望执行该命令作为优化。
如果有什么东西强迫你运行sh,但你真的想运行其他东西,exec something else当然是一个替代不需要的sh实例的变通方法(比如,如果你真的想运行你自己的漂亮的gosh而不是sh,但你的没有列在/etc/shell中,所以你不能指定它作为你的登录shell)。
使用exec操作文件描述符的第二种方法是另一个主题。公认的答案很好地涵盖了这一点;为了保持它的自成体系,对于任何exec后面跟着重定向而不是命令名的地方,我都将遵循手册。
其他回答
exec内置命令镜像内核中的函数,有一系列基于execve的函数,通常从C调用。
Exec替换当前进程中的当前程序,而不产生新的进程。这不是您在编写的每个脚本中都会用到的东西,但有时会很方便。以下是我使用它的一些场景;
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: 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. 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). 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.
很明显,您在某个地方看到过exec的使用,也许如果您展示了让您感到困扰的代码,我们就可以证明它的使用是正确的。
编辑:我意识到我上面的答案不完整。exec在shell(如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
注意这里的间距非常重要。如果在fd数和重定向符号之间放置空格,则exec恢复到原始含义:
exec 3 < thisfile # oops, overwrite the current program with command "3"
有几种方法可以使用这些,在ksh上使用read -u或print -u,在bash上,例如:
read <&3
echo stuff >&4
只是为了用一个简短的新手友好的简短答案来扩大已接受的答案,您可能不需要exec。
如果你还在这里,下面的讨论有望揭示原因。当你跑步的时候,说,
sh -c 'command'
运行一个sh实例,然后启动命令作为该sh实例的子命令。当命令结束时,sh实例也结束了。
sh -c 'exec command'
运行一个sh实例,然后将该sh实例替换为命令二进制,并运行该sh实例。
当然,这两种方法在这个有限的上下文中都是无用的;你只是想要
command
在一些边缘情况下,您希望shell读取其配置文件或以其他方式设置环境作为运行命令的准备。这几乎是exec命令有用的唯一情况。
#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command
这做了一些准备环境的工作,以便它包含所需的内容。一旦完成了这一步,sh实例就不再需要了,因此简单地用命令进程替换sh实例,而不是让sh作为子进程运行并等待它,然后在它完成时立即退出,这是一个(次要的)优化。
类似地,如果希望为shell脚本末尾的重量级命令释放尽可能多的资源,则可能希望执行该命令作为优化。
如果有什么东西强迫你运行sh,但你真的想运行其他东西,exec something else当然是一个替代不需要的sh实例的变通方法(比如,如果你真的想运行你自己的漂亮的gosh而不是sh,但你的没有列在/etc/shell中,所以你不能指定它作为你的登录shell)。
使用exec操作文件描述符的第二种方法是另一个主题。公认的答案很好地涵盖了这一点;为了保持它的自成体系,对于任何exec后面跟着重定向而不是命令名的地方,我都将遵循手册。
推荐文章
- 在命令行中使用Firefox截取完整页面的截图
- 文件中最长的一行
- 如何在父进程退出后使子进程死亡?
- [: shell编程中的意外操作符
- 如何在变量中存储标准错误
- Unix列表命令'ls'可以输出数值chmod权限吗?
- 在Unix中,我可以在一个目录中运行'make'而不首先cd'到该目录吗?
- 如何在Python中实现常见的bash习语?
- 如何通过docker运行传递参数到Shell脚本
- 快速unix命令显示文件中间的特定行?
- fork(), vfork(), exec()和clone()的区别
- 如何从查找“类型d”中排除此/ current / dot文件夹
- 只使用md5sum获取哈希值(没有文件名)
- 如何生成一个核心转储在Linux上的分段错误?
- 在Python中如何在Linux和Windows中使用“/”(目录分隔符)?