Linux命令分为 内部命令、外部命令和别名。
标题内部命令
是集成在特定shell,当用户登录时自动启动shell,他所以集成的工具也就加载于内存,执行效率最快。
比如在bash中通过enable可以查看当前的内部命令
[root@oracle ~]# enable
enable .
enable :
enable [
enable alias
enable bg
enable bind
enable break
enable builtin
enable caller
enable cd
enable command
enable compgen
enable complete
enable compopt
enable continue
... 省略 ...
通过type命令来鉴别命令的类别
[root@oracle ~]# type echo
echo is a shell builtin --> 表示内部命令
而有些shell类型中的命令是不同的,以下可以看到原来type命令就无法识别了。
[root@oracle ~]# /bin/csh
[root@oracle ~]# type
type: Command not found.
[root@oracle ~]# type enable
type: Command not found.
外部命令
一般是独立的可执行文件,保存在系统磁盘上。
[root@oracle ~]# type ping
ping is /bin/ping --> 表示外部命令,表示了对应的可执行文件的所在路径
而且,当我们执行了外部命令后,系统通过$PATH环境变量中定义的可执行文件的可能的路径来检索,找到后
会被系统缓存起来,以便未来最快匹配执行速度。
[root@oracle ~]# ping www.baidu.com
PING www.wshifen.com (104.193.88.77) 56(84) bytes of data.
64 bytes from 104.193.88.77: icmp_seq=1 ttl=50 time=253 ms
^C
--- www.wshifen.com ping statistics ---
2 packets transmitted, 1 received, 50% packet loss, time 1085ms
rtt min/avg/max/mdev = 253.153/253.153/253.153/0.000 ms
[root@oracle ~]# type ping
ping is hashed (/bin/ping) --> 提示已经被缓存
而内部命令hash本身可以查看当前缓存下来的外部命令的路径。
[root@oracle ~]# hash
hits command
2 /bin/ping
有些命令在系统中可能同时存在外部命令,通过type -a 显示出来
[root@oracle ~]# type -a echo
echo is a shell builtin
echo is /bin/echo
别名命令
简化冗长的命令行,通过简单容易记忆的别名来提高效率。通过alias定义
[root@oracle ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=auto'
打印出当前定义的别名,如果在命令行定义的别名仅对当前shell进程起效。
测试1:
我们故意将/bin/hostname这个外部命令移走 放到 /usr/bin目录,会出现什么情况?
[root@oracle ~]# whereis hostname
hostname: /bin/hostname /usr/share/man/man7/hostname.7.gz /usr/share/man/man1/hostname.1.gz
[root@oracle ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@oracle ~]# mv /bin/hostname /usr/bin /* 故意移走 */
[root@oracle ~]# hostname
-bash: /bin/hostname: No such file or directory
[root@oracle ~]# hash
hits command
2 /bin/hostname /*还在依靠历史缓存在检索 当然失败 */
1 /bin/mv
2 /usr/bin/whereis
2 /bin/ping
[root@oracle ~]# hash -d hostname /* 删除历史缓存 */
[root@oracle ~]# hash
hits command
1 /bin/mv
2 /usr/bin/whereis
2 /bin/ping
[root@oracle ~]# hostname
oracle
[root@oracle ~]# type hostname
hostname is hashed (/usr/bin/hostname) /* 通过$PATH重新匹配后缓存*/
当然,如果可执行文件的所在路径并未定义在$PATH,那么系统是无法自动匹配到。
测试2
给内部命令echo起别名叫做hostname
[root@oracle ~]# hostname
oracle
[root@oracle ~]# alias echo=hostname
这时如果输入echo, 那么得到的是hostname的执行结果,也就是当前主机名
[root@oracle ~]# echo
oracle
[root@oracle ~]# alias
alias echo='hostname'
如果这时候要让真正的echo命令执行、或禁用这别名,就要在别名前添加 \
[root@oracle ~]# \echo hello
hello
或者输入echo对应的外部命令路径来执行
[root@oracle ~]# /bin/echo hello
hello
也可以用’echo’ 或 “echo” 来实现相同效果。
老王的总结:
系统执行命令时的优先级:
- 系统先判断是否是别名,如果是则立刻执行;
- 如果不是别名,判断是否内部命令,如果是则立刻执行;
- 如果不是内部命令,将查询当前hash缓存区是否存在待执行命令的路径,如果匹配则从磁盘查找并执行;如果找不到就报错;
- 如果hash缓存没有匹配到,最后将按照$PATH系统环境变量指定的所有可能的路径逐个搜索,直到找到对应待执行命令的可执行文件;
- 如果还是没有找到,就报错