问题描述
我不明白bash命令exec
。我已经看到它在内部脚本中使用将所有输出重定向到文件(如this中所示)。但我不明白它是如何工作的或一般的。我已阅读手册页但我不理解它们。
最佳解决办法
man bash
说:
exec [-cl] [-a name] [command [arguments]]
If command is specified, it replaces the shell. No new process
is created. The arguments become the arguments to command. If
the -l option is supplied, the shell places a dash at the
beginning of the zeroth argument passed to command. This is
what login(1) does. The -c option causes command to be executed
with an empty environment. If -a is supplied, the shell passes
name as the zeroth argument to the executed command. If command
cannot be executed for some reason, a non-interactive shell
exits, unless the execfail shell option is enabled. In that
case, it returns failure. An interactive shell returns failure
if the file cannot be executed. If command is not specified,
any redirections take effect in the current shell, and the
return status is 0. If there is a redirection error, the return
status is 1.
最后两行是重要的:如果你自己运行exec
,没有命令,它只会使重定向适用于当前的shell。您可能知道,当您运行command > file
时,command
的输出将写入file
而不是您的终端(这称为重定向)。如果您改为运行exec > file
,则重定向将应用于整个shell:shell生成的任何输出都将写入file
而不是终端。例如这里
bash-3.2$ bash
bash-3.2$ exec > file
bash-3.2$ date
bash-3.2$ exit
bash-3.2$ cat file
Thu 18 Sep 2014 23:56:25 CEST
我首先启动一个新的bash
shell。然后,在这个新shell中运行exec > file
,以便将所有输出重定向到file
。实际上,之后我运行date
但没有输出,因为输出被重定向到file
。然后我退出我的shell(以便重定向不再适用),我看到file
确实包含我之前运行的date
命令的输出。
次佳解决办法
exec
是一个具有两个非常不同的行为的命令,具体取决于是否使用了至少一个参数,或者根本不使用任何参数。
-
如果至少传递一个参数,则将第一个参数作为命令名称,
exec
尝试将其作为命令执行,将其余参数(如果有)传递给该命令并管理重定向(如果有)。 -
如果作为第一个参数传递的命令不存在,则当前shell(不仅是exec命令)退出时出错。
-
如果命令存在且可执行,则它将替换当前shell。这意味着如果
exec
出现在脚本中,则永远不会执行exec调用之后的指令(除非exec
本身在子shell中)。exec
永不退货。 -
如果未传递参数,则
exec
仅用于重新定义当前的shell文件描述符。与前一种情况不同,shell在exec
之后继续,但标准输入,输出,错误或任何已重定向的文件描述符生效。 -
如果某些重定向使用
/dev/null
,则其中的任何输入都将返回EOF,并且将丢弃对其的任何输出。 -
您可以使用
-
作为源或目标来关闭文件描述符,例如exec <&-
。随后的读取或写入将失败。
这是两个例子:
echo foo > /tmp/bar
exec < /tmp/bar # exec has no arguments, will only affect current shell descriptors, here stdin
cat # simple command that read stdin and write it to stdout
此脚本将输出”foo”作为cat命令,而不是等待用户输入,因为在通常情况下它将从包含foo的/tmp /bar文件中获取其输入。
echo foo > /tmp/bar
exec wc -c < /tmp/bar # exec has two arguments, the control flow will switch to the wc command
cat
此脚本将显示4
(/tmp /bar中的字节数)并立即结束。不会执行cat
命令。
第三种解决办法
要了解exec
,您需要先了解fork
。我试图保持简短。
-
当你来到路边的 fork 时,你通常有两种选择。 Linux程序在遇到
fork()
系统调用时会到达这个分支。 -
普通程序是系统上以编译形式存在的系统命令。执行此类程序时,将创建一个新进程。此子进程与其父进程具有相同的环境,只有进程ID号不同。此过程称为分叉。
-
Forking为现有流程提供了一种启动新流程的方法。但是,可能存在子进程不是与父进程相同的程序的一部分的情况。在这种情况下,使用
exec
。exec
将使用程序二进制文件中的信息替换当前正在运行的进程的内容。 -
在分叉过程之后,子进程的地址空间被新的进程数据覆盖。这是通过对系统的exec调用完成的。
第四种办法
在bash
中,如果您执行help exec
:
$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
Replace the shell with the given command.
Execute COMMAND, replacing this shell with the specified program.
ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified,
any redirections take effect in the current shell.
Options:
-a name pass NAME as the zeroth argument to COMMAND
-c execute COMMAND with an empty environment
-l place a dash in the zeroth argument to COMMAND
If the command cannot be executed, a non-interactive shell exits, unless
the shell option `execfail' is set.
Exit Status:
Returns success unless COMMAND is not found or a redirection error occurs.
相关位:
If COMMAND is not specified, any redirections take effect in the current shell.
exec
是shell builtin,它是system calls的exec
家族的壳等效物(G_P speaks of(以及您看过的其他人阅读的内容))。如果没有指定命令,它只具有影响当前shell的POSIX mandated功能。