Shell - 内部命令和外部命令,以及下载bash shell的源码

概念

Linux命令有内部(内建)(内置)命令和外部命令之分,内部命令和外部命令功能基本相同,但有些细微差别。

所谓的内部和外部其实是相对Shell自身来讲。Linux系统为了提高系统运行效率,将经常使用的轻量的命令在系统启动时一并加载这些命令到内存中供Shell随时调用,这部分命令即为内部命令。

反之,系统层调用的较重的命令只有当被调用时才会硬盘加载的这部分命令即为外部命令。

内部命令

内部命令实际上是Shell程序的一部分,由 Shell 软件内部进行实现的命令,其中包含的是一些比较简单的linux系统命令,这些命令由shell程序识别并在shell程序内部完成运行,通常在linux系统加载运行时shell就被加载并驻留在系统内存中。内部命令是Shell本身的重要组成部分。内部命令嵌入在Shell程序中,并不单独以磁盘文件的形式存在于磁盘上。内部命令是写在bashy源码里面的,其执行速度比外部命令快,因为解析内部命令shell不需要创建子进程,它们都运行在 Shell 进程当中。比如:exit,history,cd,echo,fg,cd、source、export、time等。

外部命令

外部命令是linux系统中的实用程序部分,是一个独立的外部可执行程序,因为实用程序的功能通常都比较强大,所以其包含的程序量也会很大,在系统加载时并不随系统一起被加载到内存中,而是在需要时才将其调用内存。通常外部命令的实体并不包含在Shell中,但是其命令执行过程是由Shell程序控制的。当外部命令被调用时,本质就是调用了另外一个程序,首先 Shell 会创建子进程,然后在子进程当中运行该程序。Shell程序管理外部命令执行的路径查找、加载存放,并控制命令的执行。外部命令是在bash之外额外安装的,通常放在/bin,/usr/bin,/sbin,/usr/sbin……等等。可通过“echo $PATH”命令查看外部命令的存储路径。常见外部命令比如:/bin/ls、vi、tee、tar等。

为什么要分内部命令和外部命令

内部命令其实是SHELL程序的一部分,其中包含的是一些比较简练和日常经常会被用到的命令。这些命令通常系统启动时就调入内存,且常驻内存的,由SHELL程序识别并在SHELL程序内部运行,之所以这样做的原因只有一个就是:为了最大化执行效率,提升系统性能。而外部命令通常是系统的软件功能,该部分程序功能通常较为强大,但包括的程序量也很大,因此并不随系统启动一并加载,只在用户需要时才从硬盘中读入内存。

内部命令和外部命令的执行过程和顺序

因为内部命令是SHELL内置,所以该命令调用时直接使用,无需查找环境变量,而外部命令则有很大区别,因为外部命令若希望被用户所使用,要通过SHELL程序来调用,所以多了一层执行路径的问题,即我们常讲到的环境变量。

外部命令就是由Shell副本(新的进程)所执行的命令,基本的过程如下:

* a. 建立一个新的进程。此进程即为Shell的一个副本。

* b. 在新的进程里,在PATH变量内所列出的目录中,寻找特定的命令。

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:为PATH变量典型的默认值。 当命令名称包含有斜杠(/)符号时,将略过路径查找步骤。

* c. 在新的进程里,以所找到的新程序取代执行中的Shell程序并执行。

* d. 程序完成后,最初的Shell会接着从终端读取下一条命令,和执行脚本里的下一条命令。

通常情况下,脚本中的Bash内建命令在运行的时候是不会fork出一个子进程的。但是脚本中的外部或者过滤命令通常会fork出一个子进程。 一个内建命令通常会与一个系统命令(外部命令)同名,但是Bash在内部重新实现了这些命令。比如,Bash的echo命令与/bin/echo就不尽相同,虽然它们的行为在绝大多数情况下都是一样的。

同理,如果我们内部命令对应的外部命令移动到系统环境变量之外的其它目录下或者删除掉。该命令其实仍然可以被执行的,因为其查找的顺序是内部命令->外部命令。

shell命令解释器在执行命令时,先尝试按照内部命令来执行,如果要执行的命令不是内部命令,则按照外部命令去查找对应的执行文件所在的目录,并执行。当要执行的命令不是内部命令时(例如ls),如果有两个ls指令分别在不同的目录中(例如/usr/local/bin/ls和/bin/ls),shell命令解释器就根据PATH里面哪个目录先被查询到,则那个目录下的命令就先被执行。

常见内部命令

SHELL中的内置命令约有60个,通过内置的enable命令即可查看所有的内部命令。

$ 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

enable declare

enable dirs

enable disown

enable echo

enable enable

enable eval

enable exec

enable exit

enable export

enable false

enable fc

enable fg

enable getopts

enable hash

enable help

enable history

enable jobs

enable kill

enable let

enable local

enable logout

enable mapfile

enable popd

enable printf

enable pushd

enable pwd

enable read

enable readarray

enable readonly

enable return

enable set

enable shift

enable shopt

enable source

enable suspend

enable test

enable times

enable trap

enable true

enable type

enable typeset

enable ulimit

enable umask

enable unalias

enable unset

enable wait

禁用(关闭)内置命令

enable -n cd 表示禁用命令cd在SHELL中的内置功能。

 查看内部命令源代码

查看系统当前使用的shell:

$ env | grep SHELL

SHELL=/bin/bash

GNOME_SHELL_SESSION_MODE=ubuntu

当前shell用的是bash,查看bash的版本:

$ bash --version

GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)

Copyright (C) 2019 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

Software- GNU Project - Free Software Foundation上,可以找到bash package。点开后进入bash的页面,里面有源码的下载链接。

bash源码路径:Index of /gnu/bash,从该路径中下载指定版本下来。源码均是使用C语言编写。

注:

1,使用type命令,可以用来显示可执行命令的类型,来区分是shell内部命令还是外部命令。

参考:

1,Linux Shell 内部命令与外部命令

Linux Shell 内部命令与外部命令 - 知乎

猜你喜欢

转载自blog.csdn.net/guoqx/article/details/131041505