我正在阅读exec
以及如何使用该-a
标志。SS64文档似乎准确;他们说:
执行:
执行命令
句法:
exec [-cl] [-a name] [command [arguments]]
选项:
-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.
为了测试这一点,我编写了两个脚本,一个名为foo/baz
,一个名为foo/buzz
:
#!/usr/bin/env bash
# foo/baz
exec -a blah ./foo/bar 1 2
#!/usr/bin/env bash
# foo/buzz
exec ./foo/bar 1 2
这些脚本中的每一个都运行相同的子脚本 ,foo/bar
它执行以下操作:
#!/usr/bin/env bash
echo "Hello world"
echo "0: $0"
echo "1: $1"
echo "2: $2"
我的目标是看看-a
对第 0 次和随后的论点有什么影响。如果-a
导致第 0 个参数更改为您传递给-a
标志的参数,那么当我运行时我希望第 0 个参数foo/baz
是blah
,因为这就是我传递给-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
难道我做错了什么?还是我的期望不正确?
另外,一个相关的问题——覆盖第 0 个参数的用例是什么,而不是仅仅通过 $1、$2、$3 等访问任何传入的参数?
一些程序会根据调用方式改变它们的行为。例如,
busybox
是一个以这种方式运行的多调用二进制文件。根据第零个参数的值,使用exec -a
我们会得到不同的行为:这也表明其
exec -a <something>
行为与记录的一样。这里的问题是您正在使用 shell 脚本。当您
./foo/baz
在命令行上输入时,您实际上并没有运行名为 的命令./foo/baz
:您正在运行类似/bin/bash /path/to/foo/baz
. 虽然exec -a
影响传递给外壳的第零个参数......外壳不在乎,它在设置对外壳脚本可见的变量时使用自己的逻辑,包括$0
(包含脚本名称)和位置参数$1
,$2
...(其中包含脚本的参数)。(这并不特定于 shell 脚本——几乎任何解释代码都是如此。)
这是因为您正在调用解释脚本而不是本机二进制文件。编译这个 C 程序,把结果放在
./foo/bar
你的脚本原来的位置:一旦你这样做了,你就会看到你所期望的行为。差异的原因是在调用解释脚本时,
argv[0]
被劫持告诉解释器脚本的名称。通常这不会被注意到,因为在大多数情况下,无论如何都是这样。你只是注意到它,因为你不遗余力地让它与众不同。关键是它将为该命令行上的命令
exec
设置唯一。$0
试试,例如:
恰好由于 exec 替换了 shell,shell 关闭了,当它结束时,shell 进程也结束了。
bash
这就是为什么您需要使用该命令请求一个新的 shell 。如果没有,shell 将关闭并且也将关闭终端。如果您想遵循 exec 命令的功能,请尝试以下操作:
这对于在调用名称更改时进行一些可执行更改很有用: