我一直想知道为什么cd
不是程序,但从未设法找到答案。
有谁知道为什么会这样?
在Unix中,每当我们想要创建一个新进程时,我们会fork当前进程,创建一个与父进程完全相同的新子进程;然后我们执行 exec 系统调用以将来自父进程的所有数据替换为新进程的所有数据。
为什么我们首先创建父进程的副本而不是直接创建新进程?
在 bash 子 shell 中,运行 cd 时出现以下错误
sudo: cd: command not found
Run Code Online (Sandbox Code Playgroud)
这是意料之中的,因为我没有路径。通常要解决这个问题,我只提供完整路径,如下所示:(/usr/local/bin/foo)
令我惊讶的是,cd
它似乎不在任何正常的地方。
which cd
whereis cd
ls /bin | grep cd
Run Code Online (Sandbox Code Playgroud)
相比之下,ls
正是我所期望的。
which ls
/bin/ls
Run Code Online (Sandbox Code Playgroud)
cd
命令位于何处?为什么与所有其他命令不同?
更新
另一个有趣的花絮,cd 没有出现在 hash
hash
0 /bin/ls
2 /usr/bin/find
2 /sbin/ip
1 /usr/bin/updatedb
1 /usr/bin/apt-get
Run Code Online (Sandbox Code Playgroud) 试图了解 Linux(具体是 Ubuntu 13.04)中环境的行为,我发现在不同的情况下,在不同的上下文中使用或定义了设置环境变量。例如,如果我检查, locale
,我会得到:
$ locale
LANG=en_US.UTF-8
LANGUAGE=es_ES:es_HN:es_EC:en
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=es_ES.UTF-8
// more output
Run Code Online (Sandbox Code Playgroud)
但是,如果我发现,例如,LC_CTYPE
使用env | grep "LC_CTYPE"
,它不会发送任何输出。一般来说,locale
向我展示了 13 个LC_*
变量,但env
只有 9 个:
$ locale | grep "LC_*" | wc -l
13
$ env | grep "LC_*" | wc -l
9
Run Code Online (Sandbox Code Playgroud)
其他具有不同“性质”的变量是PS1
. 例如:
$ env | grep "PS1" # No output, but...
$ set | grep "PS1" | head -n 1
PS1=$'\\[\\033[1;33m\\][\\t][\\W]\342\230\233\\[\\033[0m\\] '
Run Code Online (Sandbox Code Playgroud)
当然,PS1
在我当前的环境中是一个定义明确的变量,因为我看到我的提示相应地改变了。
在其他上下文中查看 …
这个问题与“当我们在 shell 上输入一个简单的命令时会发生什么?”的问题相关。我之前发过。(我认为分开发布会更好。但如果没有,请告诉我。)
我从上一个问题中了解到,shell 内置命令被特殊处理,正常的外部命令在子进程上执行。
这一次,我想跟踪系统调用,例如 fork、clone 或 execve,以监视键入命令后真正发生的情况。但是execve("bin/ls",,,) = 0
当我这样执行时,我只能跟踪一个 execve 调用strace
。
strace -etrace=execve,clone ls
Run Code Online (Sandbox Code Playgroud)
这意味着,正如我猜的那样,我只能监视在创建子进程后调用的系统调用。
要监视与创建新进程相关的所有系统调用,我必须做什么? 在这种情况下,使用bash -c
like调用命令strace -etrace=execve,clone bash -c '{ ls; }'
会有所帮助吗?
shell ×4
process ×3
cd-command ×2
architecture ×1
bash ×1
command ×1
fhs ×1
fork ×1
locale ×1
subshell ×1