关于"sudo cd"的讨论

Sunday, December 1, 2019

~ $ sudo cd somedir
sudo: cd: command not found

sudo 会在环境变量($PATH)中搜索 cd , 找到后以root身份执行, 没找到则输出错误信息”command not found“。

因为 cd 是shell内建命令(built-in command), 并不像其他大多数命令或程序那样以文件形式包含在环境变量中, 所以切换目录时遇到”Permission denied“的情况正确的做法是先以root身份新建一个shell, 然后再切换目录, 完成工作后 exitCtrl-D 退回原shell

~ $ sudo -s
~ $ cd somedir
...do some work
~ $ exit

补充知识

判断命令类型可以使用 type

~ $ type cd
cd is a shell builtin

~ $ type find
find is /usr/bin/find

~ $ type ll
ll is aliased to `ls -lh'

type 本身也是shell内建命令

~ $ type type
type is a shell builtin

列出所有shell内建命令

~ $ compgen -b | column 

为什么不把”cd“设计成外部命令来避免“command not found"?

所谓的外部命令(external command)实际上是一个个独立程序(可以由任何编程语言编写),存放在环境变量所指定的目录中。shell执行这些程序时先创建一个子进程,在子进程内执行程序,执行完毕后退回原shell进程。由于子进程的环境与父进程shell的环境是互相独立的,在子进程内对环境修改父进程是感受不到的,如果 cd 作为外部命令执行,在子进程内改变了当前工作目录,退回原shell后又会回到原来的目录,这个过程相当相当迅速,对使用者来说仅仅是执行了一条指令并且看起来什么都没发生。整个过程可以用下面几条命令模拟:

~ $ bash		#创建一个子进程,该进程也是一个shell,所以可以执行”cd“
~ $ cd /tmp		#进入"/tmp"
tmp $ exit		#当前目录为“/tmp”, exit结束子进程,退回原shell
~ $ pwd			#在原shell执行”pwd“查看当前目录是否改变

例外——上述都是放屁

实际上上面所讲并不十分准确,先来看看下面两条命令的执行结果

~ $ type pwd
pwd is a shell builtin

~ $ which pwd
/usr/bin/pwd

可以看到 pwd 是shell内建命令,但又有文件形式存在的独立程序。这种与内建命令同名且实际运行结果相同的外部命令存在的意义我不是很清楚,在网上看到的说法是

It serves primarily as making sure the POSIX tool-chest is available both inside and outside a shell .

翻译:确保POSIX工具箱在shell内外都可用。

以及

for the observation about side effects and error messages.

翻译:用于观察副作用和错误信息。

所谓”副作用“是指执行该命令所造成的一些其他影响,比如 touch 命令实际上是用来改变文件时间戳(timestamps)的,执行 touch filename 时如果 filename 不存在,创建空文件 filename 即是该命令的一个副作用。

甚至在一些Linux发行版(distribution)中, cd 也有对应的外部命令,比如我安装在服务器上的 Centos7 ,执行 sudo cd /root 不会报错, 也不会改变当前工作目录。


参考: https://unix.stackexchange.com/questions/50058/what-is-the-point-of-the-cd-external-command

linux

基本正则表达式(BRE)和扩展正则表达式(ERE)

转载:提问的智慧(How To Ask Questions The Smart Way)