有人能用简单的例子解释一下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。
如果你还在这里,下面的讨论有望揭示原因。当你跑步的时候,说,
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
推荐文章
- 如何从查找“类型d”中排除此/ current / dot文件夹
- 只使用md5sum获取哈希值(没有文件名)
- 如何生成一个核心转储在Linux上的分段错误?
- 在Python中如何在Linux和Windows中使用“/”(目录分隔符)?
- 使用sh shell比较字符串
- 在Bash中测试非零长度字符串:[-n "$var"]或["$var"]
- 如何创建Bash别名?
- 如何设置ssh超时时间?
- 将所有变量从一个shell脚本传递到另一个?
- 只列出UNIX中的目录
- 如何删除shell脚本中文件名的扩展名?
- 如何限制从grep返回的结果的数量?
- 'find -exec'是Linux中的shell函数
- 如何管道列表的文件返回的找到命令到猫查看所有文件
- 以相对于当前目录的路径递归地在Linux CLI中列出文件