linux命令执行的类别判断


很多人都知道命令是什么,但是对于刚接触linux的朋友来说,还是对命令有很多困惑。 我们在linux shell命令行下敲的命令,最终会被计算机执行,这中间发生了什么?背后的原理是什么?这是很多初学者在开始学习linux的时候最困扰的问题。 当然这些问题不是一篇文章就可以解释的了的,这需要对计算机原理、linux内核有深入的了解。

我们在linux命令行下敲命令的时候,其实是在跟一个叫shell的程序打交道,所以我们也经常说shell命令行。 shell会根据用户敲的命令名字,在环境变量PATH指定的路径下寻找和命令名字匹配的一个可执行文件, 找到后shell会创建一个子进程,在子进程中加载并执行该可执行文件。所以我们平时敲的大部分命令都是一个已经存在的可执行文件,那么这个可执行文件放在哪里呢, 通过whereis就可以看到命令所对应的可执行文件的路径了,例如要看看ls这个命令在哪里,就执行whereis ls就可以看到ls的路径了。如果你把这个文件删掉, 那么shell就会告诉你找不到这条命令。大部分命令都是一个可执行文件,但是我们在用whereis查看cd命令的可执行文件路径的时候, shell的输出是这个样子的:“cd:”,竟然没有路径名, 这是什么鬼?这是因为cd是shell的一个内置命令,不以可执行文件的形式存在。通过type可以查看命令的类型。
所以咱们平时敲的命令主要分为两种,一种是以可执行文件存在的外部命令,一种是没有可执行文件的内置命令。 这里的外部和内置是从shell的角度说的。那么怎么判断一条命令是shell内置命令还是外部命令呢,用type查看就可以了,比如查看cd,在命令行下敲type cd,shell的输出是 cd is a shell builtin。那么cd就是一条shell内置命令。
说了这么多,好像还没有解释shell是什么东西,简单来讲,shell就是一个命令解释器,shell和咱们敲的这些命令都是一样的,都是运行在linux内核之上的应用程序, 在内核的眼里都是内核要调度执行的进程。这些进程在运行之前,都是一个一个的可执行文件。只是shell是在linux启动之后就会由init进程自动加载执行的。 他也对应着一个可执行文件。可以通过查看/etc/passwd文件中每条记录的最后一个字段查看每个用户在启动后执行的shell可执行文件路径, 也可以通过SHELL环境变量查看当前启动的shell。

              echo $SHELL
            

那么上面提到的环境变量又是什么东西呢?可执行文件是什么?他从哪里来?是怎么被加载到内核中变成一个可调度的进程的呢? shell是怎么创建子进程的呢?进程又是什么鬼?
shell是被init进程启动,init(systemd)进程又是什么?linux的启动流程是怎么样的?进程是如何被内核调度的?
说到这里,好像问题越来越多了,本来只是一个命令的问题,现在又引出这么多问题。技术就是这样,知道的越多,不知道的也就越多。
在initroot linux学习网站,这些问题您都可以找到答案。

用type查看命令是否为Bash shell的内置命令
bash的内置命令就相当于是bash的一个内部功能。例如cd、umask等。 直接在命令行下输入help可以查看bash提供的所有内置命令。 我们在使用man bash查看bash的帮助说明的时候,也会看到一堆命令的说明,这些命令都是bash的内置命令。
可以通过type命令查看命令是bash内置命令还是外置命令!

            [peter@study ~]$ type [-tpa] name
          
选项与参数:
-t:当加入-t参数时,type会将name显示为以下几种类型:
file: 表示为外部命令;
alias: 表示该命令为命令别名;
builtin: 表示该命令为bash的内置命令功能;
-p :如果后面接的name为外部命令时,会显示命令的完整文件名;
-a :会由PATH变量定义的路径中,将所有含name的命令都列出来,包含alias;
不加任何选项与参数时,type会显示出name是外部命令还是bash内置命令
用type命令查看ls命令和cd命令:
            [peter@initroot ~]$ type ls
            ls is aliased to `ls --color=auto'
            peter@initroot:~$ type -t ls
            alias
            peter@initroot:~$ type -p ls
            peter@initroot:~$ type -a ls
            ls is aliased to `ls --color=auto'
            ls is /bin/ls
            peter@initroot:~$ 
            peter@initroot:~$ type cd
            cd is a shell builtin
          
我们看到ls其实是一条命令别名,而cd是shell的内置命令。
透过 type 这个命令我们可以知道每个命令是否为bash的内置命令。 此外,由于利用 type 搜寻后 面的名称时,如果无法找到与命令匹配的可执行文件后面接的名称并不能以执行文件的状态被找到, 那么该名称是不会被显示出来的。
也就是说, type 主要在找出可执行文件而不是一般文件名! type类似which命令的用途!

type命令显示命令的类型信息,比如是内部命令还是外部命令:

常见用法示例:
type cd

                peter@peter-VirtualBox:~$ type cd
                cd is a shell builtin
                peter@peter-VirtualBox:~$ type ls
                ls is aliased to `ls --color=auto'
                peter@peter-VirtualBox:~$ type tree
                tree is hashed (/usr/bin/tree)
              

二.命令类别type

回到顶部

shell会将命令解释为以下几种类型: 1.shell外置命令,外置命令都有对应的二进制可执行文件或者shell脚本文件,执行命令的时候可直接输入命令文件路径;
2.shell内置命令,shell自身的内置功能;
3.命令别名alias,内置或者外置命令的别名;
4.shell函数;
一种是shell内置命令,属于shell功能的一部分。例如cd命令;
另一种是以可执行文件形式单独存在的shell外置命令。例如pwd命令;
到目前位置,我们知道在bash命令行执行的命令分为bash内置命令和bash外置命令,命令除了内置和外置之分外, 也有可能是命令别名。命令可能是外置命令可执行程序文件、命令别名、内置命令、bash函数。 另外外置命令都有对应的可执行文件,可执行程序文件包括位二进制可执行程序文件、shell脚本等。 可以直接在命令行输入可执行文件的相对路径或者绝对路径来执行命令。 那么当你在命令行输入一条命令的时候,bash会按照一定的顺序判断并执行这条命令。bash执行命令的顺序如下:

1. 如果命令是绝对路径或者相对路径,那么直接执行路径指定的文件;
2. 如果没有提供命令路径,那么先判断该命令是否是alias命令别名,如果是命令别名,按照命令别名执行;
3. 如果不是命令别名,继续判断该命令是否是bash的内置builtin命令,如果是内置命令,则按照内置命令执行;
4. 如果不是内置命令,那么在$PATH环境变量指定的路径中寻找匹配的命令文件,只要找到就停止继续搜索并立即执行命令文件。 所以如果有多个同名文件,那么就执行找到的第一个二进制可执行文件.

1.用type命令查看命令类别

回到顶部
当然我们也可以通过type -a追踪命令的搜索顺序,例如我们查看ls命令:
            [peter@study ~]$ type -a ls
            ls is aliased to `ls --color=auto'
            ls is /bin/ls
          
设置echo为echo -n的命令别名,然后观察echo执行的顺序:
            [peter@study ~]$ alias echo='echo -n'
            [peter@study ~]$ type -a echo
            echo is aliased to `echo -n'
            echo is a shell builtin
            echo is /bin/echo
          
通过上面的输出我们发现,我们设置了echo为echo -n的命令别名,所以在命令行输入echo后,bash实际执行的是echo -n,而echo既是shell的内置命令,也有对应的二进制可执行文件. bash会先检查是否是内置命令,如果是内置命令,bash就按照内置命令执行. 如果不是内置命令,bash就在PATH命令中寻找匹配的二进制可执行文件并执行.有上面的输出可知,bash最终执行的是bash自己的内置命令.

1.内置命令和外置命令

回到顶部
刚才提到linux的命令有两种存在形式:一种是shell内置命令,另一种是shell外置命令,那么到底什么是内置命令什么是外置命令呢?
我们前面提到linux命令其实就是计算机软件程序, 以可执行程序文件的形式存放在磁盘的某个目录中。
那么如何知道一个命令的可执行文件存放在哪个目录下呢? 可以通过whereis命令查看命令的可执行文件存放目录:
            root@peter-VirtualBox:~# whereis ls
            ls: /bin/ls /usr/share/man/man1/ls.1.gz
            root@peter-VirtualBox:~# whereis rm
            rm: /bin/rm /usr/share/man/man1/rm.1.gz
          
whereis命令不仅列出命令的可执行文件,同时也列出了命令的帮助文档manpage的路径。 我们把以可执行程序文件形式存在的linux命令称为linux shell外置命令。 而不以单独可执行文件形式存在的命令称为linux shell内置命令。由于内置命令没有可执行程序文件, 所以通过whereis命令是查不到内置命令的可执行文件存放路径的。 例如我们知道cd是内置命令,我们用whereis cd命令查看结果如下:
            peter@peter-VirtualBox:~$ whereis cd
            cd:
          
并没有列出cd的可执行文件路径,因为cd是内置命令,根本就不存在cd的可执行程序文件。 但是我们知道命令就是计算机程序软件,肯定需要存放在可执行程序文件中,那么内置命令到底存在哪里了呢? 其实内置命令存放在shell的可执行程序文件中了,有上面我们知道bash shell的可执行程序文件为/bin/bash, 也就是所有的内置命令都存放在/bin/bash中,相当于bash的内置功能。 这也就是为什么我们说内置命令和外置命令的时候,前面总是喜欢加个shell的原因.因为内置和外置是相对shell的角度来说的。
如何看出一条命令是内置命令还是外置命令呢?可通过type命令查看命令的类型,例如:
            root@peter-VirtualBox:~# type cd
            cd is a shell builtin
            root@peter-VirtualBox:~# type pwd
            pwd is a shell builtin
            root@peter-VirtualBox:~# type rm
            rm is /bin/rm
            root@peter-VirtualBox:~# type ls
            ls is aliased to `ls --color=auto'
          
通过命令的输出可以看出,cd和pwd命令都是shell内置命令, 如果输出中没有'shell builtin',则表明命令是一条外置命令。 例如,rm命令是一条外置命令,可执行文件名为/bin/rm,ls命令也是一条外置命令,是`ls --color=auto'的命令别名。
如何查看shell有哪些内置命令呢?help命令可以打印出shell的所有内置命令。

2.$PATH环境变量

回到顶部
我们在前面讲过,每个外置命令都有对应的可执行程序文件,这些可执行程序文件可能分布在不同的磁盘目录中。 对于shell内置命令,因为内置命令本身就是shell功能的一部分,所以可以很顺利的执行内置命令的功能。 但是对于shell外置命令来说,因为外置命令的可执行程序文件分布在不同的磁盘目录中,那么当在shell命令行下执行一条外置命令的时候,shell是怎么找到命令相对应的可执行程序文件呢? 这就要借助$PATH环境变量了。我们通过echo命令打印$PATH环境变量的值:
            peter@initroot:~$ echo $PATH
            /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
          
通过上面的输出可以看出,$PATH环境变量的值为一堆路径的集合,路径之间用:分隔。 在执行命令的时候,shell按顺序到这些目录中寻找和命令名匹配的可执行程序文件名,然后将找到的第一个匹配的可执行程序文件加载到内存中执行。 如果没有找到,就会给出提示:"command not found".
更多关于shell变量和环境变量的内容可参考:
linux shell变量与环境变量

initroot编辑整理,转载请注明www.initroot.com

100次点赞 100次阅读