谁能用简单的例子解释exec命令在shell脚本中的用途吗?
-
linux.about.com/od/commands/l/blcmdln_exec.htm这将使您更好地理解
-
指向linux.about.com的链接没有帮助。 他们并没有使远程了解使用exec执行命令或命令管道与仅正常执行命令有何不同。 因此,OP的问题是" exec的用途是什么"?
-
堆栈溢出是一个用于编程和开发问题的站点。 这个问题似乎与主题无关,因为它与编程或开发无关。 请在帮助中心中查看我可以询问哪些主题。 也许超级用户或Unix&Linux Stack Exchange是一个更好的选择。
内置命令exec反映了内核中的功能,其中有一系列基于execve的功能,通常从C调用。
exec替换当前进程中的当前程序,而无需fork新建一个进程。并不是您在编写的每个脚本中都会使用它,但有时会派上用场。这是我使用过的一些场景;
我们希望用户在不访问外壳的情况下运行特定的应用程序。我们可以在/ etc / passwd中更改登录程序,但是也许我们希望从启动文件中使用环境设置。因此,在(例如).profile中,最后一条语句表示如下内容:
所以现在没有外壳可以回去了。即使appln-program崩溃,最终用户也无法进入shell,因为它不存在-exec替换了它。
我们要使用与/ etc / passwd中不同的shell。看起来很愚蠢,有些网站不允许用户更改其登录外壳。我知道有一个站点,每个人都以csh开头,并且每个人都将对ksh的调用放入其.login(csh启动文件)中。在此过程中,它留下了一个迷离的csh进程,并且注销是两个阶段,可能会引起混淆。因此,我们将其更改为exec ksh,后者仅用korn shell替换了c-shell程序,并使一切变得更简单(与此相关的还有其他问题,例如ksh不是登录shell)。
只是为了节省流程。如果我们调用prog1 -> prog2 -> prog3 -> prog4等并且从不回退,则使每个调用都执行一次。这样可以节省资源(当然,除非重复,否则可以节省很多资源),并且使关机更加简单。
您显然已经看到exec在某处使用过,也许如果您显示的代码有问题,我们可以证明其使用是合理的。
编辑:我意识到我上面的答案是不完整的。在像ksh和bash这样的shell中,exec有两种用法-用于打开文件描述符。这里有些例子:
1 2 3 4 5 6 7 8
| 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还原为原始含义:
1
| exec 3 < thisfile # oops, overwrite the current program with command"3" |
有几种方法可以使用它们,例如,在ksh上,在bash上使用read -u或print -u。
1 2
| read <&3
echo stuff >&4 |
-
还有另一种用法,我在这里发现很方便,值得一提,因为它与python Web应用程序有关,并且似乎在您的(真棒)答案2和3之间存在某些问题。我通常通过主管调用wsicorn的主管来运行wsgi Web应用程序(例如django或flask)应用程序:后者臭名昭著地需要大量环境变量,它的运行方式更简单,更易于维护,它可以通过shell脚本来设置所有内容,并最终通过exec gunicorn将正确的pid返回给主管。
-
文档确实说exec可用于重定向:>如果未指定command,则任何重定向都会在当前shell中生效,并且返回状态为0。如果存在重定向错误,则返回状态为1。但是exec实际如何更改文件描述符?为什么为此任务选择此特定命令? (Markdown现在失败了吗?)
-
@Ray:尽我所能:pubs.opengroup.org/onlinepubs/009604599/utilities/exec.html。如果您需要了解方法,请查看shell源代码。
-
另一个用途:将所有脚本输出重定向到日志文件exec >.\logfilename.log 2>&1
-
是的,这意味着执行命令行上指定的命令。在man bash中查找@变量。 exec用新的程序替换当前程序,再次在手册页中查找exec。
-
尼斯和整洁的解释。
-
相关后续问题:stackoverflow.com/questions/41603122/understanding-exec-in-bash
-
与文件描述符一起使用时很好并且整洁地解释了!!
-
当后面跟yum install等其他命令时,您能否解释exec &> varloguserdata.log?在我看来,这导致命令被输出到日志文件而不是被执行
-
@Carmageddon:&>是bash扩展名(请参见man bash),您的示例等效于exec >varloguserdata.log 2>&1。换句话说,它将stdout和stderr重定向到该文件。除非重置它们,否则后面的命令将继承这些重定向,但它们将被执行。
只需使用简短的新手友好的简短答案来增加已接受的答案,您可能不需要exec。
如果您仍在这里,则以下讨论将有望揭示原因。跑步时说
您运行sh实例,然后将command作为该sh实例的子代启动。 command完成时,sh实例也完成。
运行一个sh实例,然后将该sh实例替换为command二进制文件,然后运行它。
当然,在这种有限的情况下,这两者都是无用的。你只是想要
在某些情况下,您希望外壳程序读取其配置文件,或者以其他方式设置环境以作为运行command的准备。这是exec command有用的唯一情况。
1 2 3
| #!/bin/sh
ENVIRONMENT=$(some complex task)
exec command |
这会做一些事情来准备环境,使其包含所需的内容。完成此操作后,就不再需要sh实例了,因此,将(x1>实例替换为command进程,而不是让sh作为子进程运行,并且是一个(次要)优化)等待它,然后在完成时退出。
同样,如果您想在shell脚本的末尾释放尽可能多的资源来执行繁琐的命令,则可能需要exec作为优化。
如果某些因素迫使您运行sh,但您确实想运行其他东西,则exec something else当然是一种替代方法,用于替换不需要的sh实例(例如,如果您确实想运行自己的精美gosh而不是sh,但您的用户不在/etc/shells中,因此您不能将其指定为登录外壳程序)。
exec操纵文件描述符的第二个用途是一个单独的主题。公认的答案很好地涵盖了这一点。为了使它自成一体,对于exec后跟重定向而不是命令名称的任何内容,我将只参考本手册。
-
感谢Tripleee的出色回答并投票。想知道我可以执行的两种方式-(1)bash -c"",(2)bash -c"exec ",然后在执行后,我使用$?检查返回状态,想知道是否有任何区别吗?在两种情况下,$?是否都跟踪是否成功?还是跟踪外壳本身是否正常?
-
抵制诱惑来调用自己的Spiffy Shell bush。当然,这适用于bash或通常也适用于任何流行的Unix shell。尽管如@anishsane所述,Bash通过实际执行exec command秘密地优化了bash -c command。
-
Shell的退出代码通常是它执行的最后一个命令的退出代码。当然,如果外壳无法运行或无法执行命令,则外壳退出状态将以适当的错误代码反映出来。
-
感谢Tripleee,为两个帖子投票,并想知道exec是否了解bash条件执行,例如||和&&?谢谢。
-
应避免跟进切线问题。谢谢。稍作试验,就会发现您尝试bash -c exec nonesvch || echo still here时会发生什么(提示:它没有echo且退出代码为127)。
-
我的书中sh -c command没有意义;您也可以编写command,它的效果基本上相同,只需要一个较少的过程。因此,此答案的第一部分确实没有帮助-继续承认。您可以使用exec终止脚本并将其替换为您执行的任何命令;这样可以减少进程数量,并在报告退出状态时使Shell脱离循环。
-
@JonathanLeffler我在故意记录一个反模式,我在新手问题中都会看到它。此副本是由此副本提示的,但我以前见过,所以我想专门介绍一下。
-
然后,您需要澄清第一段-很多。目前还不是这样。当前显示为"您不需要exec command,因为您可以使用sh -c command"。如果那不是您想要说的话,则必须修改语言以使其100%明确。 Lemme知道您何时对其进行修改。
-
@JonathanLeffler次要措辞调整;您认为这足够了吗?感谢您的反馈。
-
更好,但是……好吧,当命令是脚本中的最后一条语句时,您可能想使用exec command而不是仅仅使用command。我想我更喜欢重写。
-
谢谢-我添加了关于此优化的另一简短段落。如果您还有其他异议,或者您只是想以不同的角度解释事情,对我来说还不是很清楚。