我最近想运行命令pkexec
,但却意外地成功运行了该命令exec
本身,没有任何选项或参数。我在man
页面中查找了 的描述exec
,但我仍然不知道它是什么意思:
DESCRIPTION
The exec() family of functions replaces the current process image with
a new process image. The functions described in this manual page are
front-ends for execve(2). (See the manual page for execve(2) for fur‐
ther details about the replacement of the current process image.)
实际上描述还在继续……但其余的描述也没有给我带来太大的帮助……所以这真的是我的问题,这个exec
命令有什么作用?我是否通过不带任何选项或参数直接执行它来做任何事情exec
?它与命令有什么关系吗pkexec
?
答案1
“exec()
函数族”……嗯,功能。它们用于源代码。它们不是用户要执行的命令1。它们通常由需要执行另一个程序的程序使用(例如,shell 本身、、sudo
等pkexec
)。直接调用的程序exec
会发现自己被 'd 程序替换exec
,因此典型用法通常是fork
和exec
。
一个设计的例子如下:
$ cat foo.c
#include <unistd.h>
int main()
{
const char * path = "/bin/echo";
char * args[] = {"echo", "Hello", "World!", NULL};
execv(path, args);
}
$ gcc -o foo foo.c
$ ./foo
Hello World!
你可以在各种程序中看到实际exec
使用实例,包括它自己:strace
strace
$ strace -e execve ./foo
execve("./foo", ["./foo"], [/* 52 vars */]) = 0
execve("/bin/echo", ["echo", "Hello", "World!"], [/* 52 vars */]) = 0
Hello World!
+++ exited with 0 +++
注意strace
它本身如何使用exec
来调用程序,然后程序又如何调用exec
。
1 ...除了shellexec
内置命令,这是一个 shell 特性。
exec
shell 内置命令与函数类似exec
,使用程序名调用exec
会导致 shell 被替换。但是,它的常见用法exec
通常是修改或添加文件描述符。
另一个人为的例子:
$ exec 3</dev/urandom
$ read -u 3 -n 10
$ echo "$REPLY" | base64
oZN5Qsn3nAs+1GFUCg==
您可能认为我们可以直接从中读取/dev/urandom
。是的,我们可以。但是,这在以下情况下很有用:
- 我们需要读取/写入多个文件描述符
- 我们需要替换一个或多个标准文件描述符(例如,发送
stdout
到整个 shell 会话的文件)。
答案2
在执行此操作时,man exec
您会遇到exec()
基本上是execve(2)
系统调用包装器的函数系列。
您exec
执行的是 shell 内置的:
$ type -a exec
exec is a shell builtin
现在来自help exec
:
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.
通常,新进程是通过系统调用的组合来创建的fork(2)-exec()
。这里fork()
将通过复制父进程创建一个具有新 PID 的子进程,然后用exec()
我们想要运行的可执行文件替换子进程。例如,当我们想要运行一个可执行文件时top
,shell 会调用,从而创建一个与 shell 完全相同但具有新 PID 的子进程,然后使用调用fork(2)
替换这个新创建的进程。/usr/bin/top
exec()
现在在 shell 内置命令中exec
,fork()
不再调用,而是exec()
直接调用,因此 shell 直接被可执行文件替换,新进程将继承 shell 的 PID。
请注意,仅exec
在没有任何参数或重定向时才不会执行任何操作。
答案3
除了muru所说的,exec是bash的内置命令。下面的描述是从bash man page复制而来的(你可以使用'man bash'来查看它):
exec [-cl] [-a 名称] [命令 [参数]] 如果指定了命令,它将替换 shell。不会创建新进程。参数变为 命令的参数。如果提供了 -l 选项,shell 会在开头放置一个破折号 传递给命令的第零个参数。这就是 login(1) 所做的。-c 选项导致 com- 要求在空环境中执行。如果提供了 -a,shell 将传递 name 作为 执行命令的第零个参数。如果由于某种原因命令无法执行,则非 交互式 shell 退出,除非启用了 shell 选项 execfail,在这种情况下它会返回 失败。如果文件无法执行,交互式 shell 将返回失败。如果命令未 指定,任何重定向都会在当前 shell 中生效,返回状态为 0。如果没有 是重定向错误,返回状态为1。