• Linux shell 内建命令


    前言

    一、shell简介

    shell 是Linux系统中一个提供命名行的交互式工具,本质是一个c语言可执行程序,为用户提供了启动程序,管理文件系统中的文件以及运行在Linux系统上的进程的途径。命令行提示符是shell负责交互的部分,允许用户输入文本命令,然后解释命令,并在内核中执行。

    Linux系统上有多种shell可用,Linux发行版默认的shell都是bash shell,接下来主要介绍bash shell。

    系统中启动哪种类型的shell,取决用个人用户ID配置,在/etc/passwd文件中可见。只要用户登录到某个虚拟控制终端或是在GUI中启动终端仿真器,默认的shell程序就会开始运行。

    我在我的Ubuntu20.04上打开终端,这时候默认的shell程序就开始运行了,同时第一次登录是父shell,提供CLI提示符,等待命令输入。
    在这里插入图片描述

    在Linux shell中执行命令的过程如下:
    
    用户在终端中输入命令,并按下回车键。
    
    Shell解释器(例如bash)接收到命令并对其进行解析。解析过程包括去除命令中的空格和特殊字符,以及将命令拆分成单个单词或参数。
    
    Shell解释器检查命令是否是内置命令(例如cd、echo等),如果是则直接执行内置命令。否则,Shell解释器将尝试在系统中查找该命令的可执行文件。
    
    Shell解释器搜索路径($PATH环境变量中指定的一组目录)以查找命令的可执行文件。如果找到可执行文件,则Shell解释器将启动一个新的进程来运行该命令,否则将输出“command not found”错误信息。
    
    新进程被启动后,将执行相应的命令。这可能涉及到读取和写入文件、打印输出、调用其他程序等操作,具体操作取决于命令的功能。
    
    命令执行完毕后,新进程将终止并返回一个退出状态码。Shell解释器可以使用这个状态码来判断命令是否成功执行。
    
    Shell解释器在命令完成后等待用户输入下一个命令。如果用户按下Ctrl-C或Ctrl-D,则将中断当前命令或退出Shell。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    用户 yl 用 bash shell作为自己的默认程序,bash shell位于/bin目录下,/bin/bash是一个可执行的二进制程序,
    在这里插入图片描述

    x代表可执行,ls 加-F选项,会在可执行文件中的后面加一个 * 号,以便用户找出系统上可执行的文件。
    -F选项也可以区分文件夹和文件。
    在这里插入图片描述

    二、外部命令

    外部命令也被称为文件系统命令,是存在与 bash shell之外的程序,之前说过bash shell本质是也是一个二进制可执行程序。通常位于 /bin、/usr/bin、/sbin或/usr/sbin下。
    在这里插入图片描述

    在Linux shell中,外部命令是指由操作系统提供的可执行程序,可以通过在shell中输入命令来执行这些程序,完成各种任务。

    当执行外部程序时,父进程bash shell会执行 fork() 创建一个子程序,子程序调用exec() 执行当前的外部程序,执行完之后结束自己的生命,等待bash shell 父进程调用 wait() 进行回收子程序的资源。

    创建一个进程会有一定的开销,会打开文件,进行磁盘文件IO操作。

    外部命令比如,可以使用 type 来确定一个命令是否是外部程序。
    在这里插入图片描述
    $PATH 变量包含的目录中系统中绝大多数的可执行命令,它们都是外部命令:
    在这里插入图片描述
    我们可以用 bpftrace 来观测外部命令,执行外部命令时,会调用exec()函数:

    使用bpftrace来跟踪新进程和执行新进程时的参数,执行外部命令时,由于会执行exec()函数,因此会触发我们的 tracepoint :sys_enter_execve。

    yl@yl-virtual-machine:~/Desktop$ sudo bpftrace -l tracepoint:* | grep sys_enter_execve
    tracepoint:syscalls:sys_enter_execve
    tracepoint:syscalls:sys_enter_execveat
    
    • 1
    • 2
    • 3
    yl@yl-virtual-machine:~$ ls
    Desktop  Documents  Downloads  Music  Pictures  Public  snap  Templates  Videos
    yl@yl-virtual-machine:~$ ps
    
    • 1
    • 2
    • 3
    yl@yl-virtual-machine:~/Desktop$ sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { join(args->argv); }'
    Attaching 1 probe...
    ls --color=auto
    ps
    
    • 1
    • 2
    • 3
    • 4

    三、内建命令

    3.1 简介

    内建命令并不需要父进程bash shell创建一个子程序,内建命令是bash shell程序的一部分,执行内建命令等于调用bash shell程序的一个程序。可以使用 type 来确定一个命令是否是内建命令。
    在这里插入图片描述

    内建命令属于shell执行的一部分,因此执行内建命令不需要创建子进程,也不需要打开程序文件,这样不用操作文件IO,执行效率高,运行快。

    还有一些命令即属于外部命令也属于内建命令,用 type -a 进行查看,比如:
    在这里插入图片描述
    其中which命令只显示出外部命令文件。

    对于即属于外部命令也属于内建命令的,要想执行外部命令,输入指定文件:
    在这里插入图片描述

    我们依然可以用 bpftrace 来观测 内建命令:

    yl@yl-virtual-machine:~/Desktop$ cd ..
    yl@yl-virtual-machine:~$ pwd
    /home/yl
    
    • 1
    • 2
    • 3
    yl@yl-virtual-machine:~/Desktop$ sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { join(args->argv); }'
    Attaching 1 probe...
    
    
    • 1
    • 2
    • 3

    可以看到执行内建命令并不会执行exec函数,因为内建命令是bash shell程序的一部分,执行内建命令等于调用bash shell程序的一个程序,不会创建一个新的进程,因此也不会触发我们的 tracepoint :sys_enter_execve。

    3.2 source 和 .

    在Linux中,source命令用于在当前shell环境中执行指定的脚本文件,通常用于加载shell配置文件或其他一些需要在当前shell环境中生效的操作。
    source命令和 . 可以替代,效果一样。

    source命令是内置命令:

    $ type source 
    source is a shell builtin
    $ type .
    . is a shell builtin
    
    • 1
    • 2
    • 3
    • 4

    通过 source 执行脚本,用的当前终端的脚本解释器 bash pid :3382。

    $ ps
        PID TTY          TIME CMD
       3382 pts/0    00:00:00 bash
       3388 pts/0    00:00:00 ps
    $ source shell.sh 
    My script PID is 3382
    Please enter a string:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    因此,通过source 执行脚本不会产生新的进程来执行该脚本。

    通过其他脚本解释器执行脚本,就会产生新的进程来执行脚本:

    $ ps
        PID TTY          TIME CMD
       3382 pts/0    00:00:00 bash
       3414 pts/0    00:00:00 ps
    $ ./shell.sh 
    My script PID is 3416
    Please enter a string:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总结

    内建命令比外部命令,效率更高,执行更快,执行内建命令相当于调用当前 Shell 进程的一个函数。比如cd、exit 这些是内部命令,本质是函数调用,可以直接使用,内建命令并不是某个外部程序,而是bash shell该程序的组成部分,只要在 bash shell 中就可以运行这个命令。

    内建命令不会受到系统环境变化的影响。

    执行外部命令时,会打开文件,不但会产生磁盘 I/O,还需要调用 fork 创建一个进程来执行,执行完成后再退出。

    给出一个简单的测试用例,通过bpftrace也能判断一个命令是否是外部命令。

  • 相关阅读:
    bert 环境搭建之Pytorch&Transformer 安装
    IDEA中字符串怎么自动转义,双引号自动转义的小技巧
    Java教程:如何用控制台打印日历?
    Oracle数据库:序列sequence的创建,查询,修改,删除,increment by,start with等关键字
    面面面试三
    HTML的段落中怎么样显示出标签要使用的尖括号<>?
    Azure OpenAI 服务
    嵌入式Linux 开发经验:内核驱动静态编译与模块编译
    替代A4988的微型打印机驱动TMI8421国产电机驱动芯片
    国内外数据保护(灾备、备份、恢复、复制、归档)厂商
  • 原文地址:https://blog.csdn.net/weixin_45030965/article/details/126592737