来自 Bash 手册
exec [-cl] [-a name] [command [arguments]]
如果提供命令,它将替换 shell,而不创建新进程。
如果
-l
提供了该选项,shell 会在传递给 的第 0 个参数的开头放置一个破折号command
。这就是登录程序的作用。如果
-a
提供,shell 将name
作为第 0 个参数传递给command
。
没有传递给 的第 0 个参数-l
或-a
传递给 的第 0 个参数是什么command
?
-l
在第零个参数的开头放置破折号的目的是什么?
作为第零个参数的开头-a
传递的目的是什么?name
我尝试进行实验。为什么第一个实验没有输出任何内容,而第二个实验却输出任何内容bash
?
$ bash; exec echo $0
$ bash;
$ exec 'echo' $0
bash
答案1
没有
-l
或者-a
传递给命令的第 0 个参数是什么?
在这种情况下,第零个参数就是command
它本身。
-l 在第零个参数的开头放置破折号的目的是什么?
这是大多数(所有?) shell 都遵守的约定。当登录会话启动时,shell 会在其第 0 个参数前面添加一个连字符(由login
启动会话的任何参数放置在那里),并且 shell 将此解释为启动新登录会话的信号。
作为第零个参数的开头
-a
传递的目的是什么?name
这是设置与实际启动进程所使用的路径名或文件名[显着]不同的第零个参数的唯一方法。您可能想要这样做的原因是一些命令检查它们的第零个参数以了解它们应该如何表现。您还可以使用它来欺骗程序,使其认为它是从与实际不同的路径名启动的(例如,这可能有助于它找到其数据文件)。
$ bash; exec echo $0
这是一个有点奇怪的命令。肯定会echo
输出一些内容(然后立即终止您的会话),但直到您首先启动的子 shell 终止为止。您到底想在这里测试/实现什么?
如果您想测试该功能,您可以这样做:
$ strace -fe execve bash -c 'exec -a foo echo test'
execve("/bin/bash", ["bash", "-c", "exec -a foo echo test"], [/* 56 vars */]) = 0
execve("/bin/echo", ["foo", "test"], [/* 56 vars */]) = 0
test
+++ exited with 0 +++
$ strace -fe execve bash -c 'exec -l echo test'
execve("/bin/bash", ["bash", "-c", "exec -l echo test"], [/* 56 vars */]) = 0
execve("/bin/echo", ["-echo", "test"], [/* 56 vars */]) = 0
test
+++ exited with 0 +++
$ (exec -a uname busybox)
Linux
$ (exec -l bash -c 'echo "$0"')
-bash
$ (exec -l ksh -c '[ -o login ] && echo yes')
yes
(使用exec -l bash -c ...
(或bash -lc ...
),bash 会读取~/.bash_profile
,但否则不认为自己是登录 shell)。