为什么 `exec -a` 没有按我预期的方式工作?

Ric*_*mas 4 bash

我正在阅读exec以及如何使用该-a标志。SS64 文档看起来很准确;他们说:

执行:

执行命令

句法:

exec [-cl] [-a name] [command [arguments]]
Run Code Online (Sandbox Code Playgroud)

选项:

-c   Causes command to be executed with an empty environment.

-l   Place a dash at the beginning of the zeroth arg passed to command.
     (This is what the login program does.)

-a   The shell passes name as the zeroth argument to command.
Run Code Online (Sandbox Code Playgroud)

为了测试这一点,我编写了两个脚本,一个名为 name foo/baz,一个名为 name foo/buzz

#!/usr/bin/env bash
# foo/baz

exec -a blah ./foo/bar 1 2
Run Code Online (Sandbox Code Playgroud)
#!/usr/bin/env bash
# foo/buzz

exec ./foo/bar 1 2
Run Code Online (Sandbox Code Playgroud)

这些脚本中的每一个都运行相同的子脚本 ,foo/bar该子脚本执行以下操作:

#!/usr/bin/env bash

echo "Hello world"
echo "0: $0"
echo "1: $1"
echo "2: $2"
Run Code Online (Sandbox Code Playgroud)

我的目标是看看-a对第 0 个和后续参数有什么影响。如果-a导致第 0 个参数更改为您传递给标志的参数,那么当我运行-a时我期望第 0 个参数是,因为这就是我传递给 的参数。但是,当我运行脚本时,两种情况的输出是相同的:foo/bazblah-a

~/Workspace/OpenSource (master)  $ ./foo/baz 
Hello world
0: /Users/richiethomas/Workspace/OpenSource/foo/bar
1: 1
2: 2
~/Workspace/OpenSource (master)  $ ./foo/buzz
Hello world
0: /Users/richiethomas/Workspace/OpenSource/foo/bar
1: 1
2: 2
Run Code Online (Sandbox Code Playgroud)

难道我做错了什么?或者我的期望在某种程度上是不正确的?

另外,一个相关的问题 - 覆盖第 0 个参数的用例是什么,而不是仅通过 $1、$2、$3 等访问任何传入的参数?

lar*_*sks 13

覆盖第 0 个参数的用例是什么......?

有些程序根据它们的调用方式来改变它们的行为。例如,busybox一个多调用二进制文件就是这样表现的。根据exec -a第零个参数的值,我们会得到不同的行为:

$ bash -c 'exec -a date /usr/sbin/busybox'
Sat Sep 17 20:22:14 EDT 2022
$ bash -c 'exec -a uptime /usr/sbin/busybox'
 20:22:17 up 23:48,  load average: 0.10, 0.20, 0.15
Run Code Online (Sandbox Code Playgroud)

这也表明其exec -a <something>行为如记录的那样。

难道我做错了什么?或者我的期望在某种程度上是不正确的?

这里的问题是您正在使用 shell 脚本。当您./foo/baz在命令行上输入时,您实际上并没有运行名为 的命令./foo/baz:您正在运行类似 的命令/bin/bash /path/to/foo/baz。虽然exec -a影响传递给 shell 的第 0 个参数... shell 并不关心,它在设置 shell 脚本可见的变量时使用自己的逻辑,包括$0(包含脚本名称)和位置参数$1$2...(其中包含脚本的参数)。

(这并不是特定于 shell 脚本——这同样适用于几乎任何解释的代码。)