• 【第十章】认识与学习BASH


    认识BASH这个Shell

    硬件、核心与Shell

    一、当你要计算机传输出来“音乐”的时候,你的计算机需要:

    1. 硬件:需要你的硬件有声卡芯片这个配备,否则怎么会有声音;
    2. 核心管理:操作系统的核心可以支持这个芯片组,当然还需要提供芯片的驱动程序啰;
    3. 应用程序:需要使用者 (就是你) 输入发生声音的指令啰!

    也就是说,你必须要“输入”一个指令之后, “硬件”才会通过你下达的指令来工作!那么硬件如何知道你下达的指令呢?那就是kernel(核心)的控制工作了!也就是说,我们必须要通过“Shell”将我们输入的指令与Kernel沟通,好让Kernel可以控制硬件来正确无误的工作!我们可以通过下面这张图来说明一下:
    在这里插入图片描述
    二、操作系统其实是一组软件,由于这组软件在控制整个硬件与管理系统的活动监测,如果这组软件能被使用者随意的操作,若使用者应用不当,将会使得整个系统崩溃!但是我们总是需要让使用者操作系统的,所以就有了在操作系统上面发展的应用程序啦!使用者可以通过应用程序来指挥核心,让核心达成我们所需要的硬件任务!
    三、其实shell的功能只是提供使用者操作系统的一个接口,因此shell需要可以调用其他软件才好。我们前面提到的指令man、chmod、chown、vi、fdisk、mkfs等,都是独立的应用程序,但是我们可以通过shell(就是命令行界面) 来操作这些应用程序,让这些应用程序调用核心来运行所需的工作哩!
    四、也就是说,只要能够操作应用程序的接口都能够称为shell。狭义的shell指的是命令行方面的软件,包括本章要介绍的bash等。 广义的shell则包括图形接口的软件!因为图形接口其实也能够操作各种应用程序来调用核心工作啊!

    系统的合法shell与/etc/shells功能

    一、目前Linux(以CentOS 7.x为例)有多少我们可以使用的shells呢? 你可以检查一下 /etc/shells 这个文件,至少就有下面这几个可以用的 shells (鸟哥省略了重复的 shell 了!包括 /bin/sh 等于 /usr/bin/sh 啰!):
    通过检查/etc/shells文件,可以查看Linux(以CentOS 7.x为例)中有多少我们可以使用的shells:

    /bin/sh (已经被 /bin/bash 所取代)
    /bin/bash (就是 Linux 默认的 shell)
    /bin/tcsh (整合 C Shell ,提供更多的功能)
    /bin/csh (已经被 /bin/tcsh 所取代)
    # 省略了重复的shell,包括/bin/sh等于/usr/bin/sh
    
    • 1
    • 2
    • 3
    • 4
    • 5

    为什么我们系统上合法的shell要写入/etc/shells这个文件?因为系统某些服务在运行过程中,会去检查使用者能够使用的shells,而这些shell的查询就是借由/etc/shells这个文件啰!某些FTP网站会去检查使用者的可用shell,而如果你不想要让这些使用者使用FTP以外的主机资源时,可能会给予该使用者一些怪怪的shell,让使用者无法以其他服务登陆主机。这个时候,你就得将那些怪怪的shell写到/etc/shells当中了。
    二、当我登陆的时候,系统就会给我一个shell让我来工作了。 而这个登陆取得的shell就记录在/etc/passwd这个文件内!这个文件的内容:

    [dmtsai@study ~]$ cat /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    .....(下面省略).....
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在每一行的最后一个数据,就是你登陆后可以取得的默认的shell啦!那你也会看到,root是/bin/bash,不过,系统帐号bin与daemon等等,就使用那个怪怪的/sbin/nologin

    Bash shell的功能

    一、bash主要相容于sh,其主要优点:

    1. 命令编修能力(history):他能记忆使用过的指令,我只要在命令行按上下键就可以找到前/后一个输入的指令!而在很多distribution里头,默认的指令记忆功能可以到达1000个,这么多的指令记录在你的主文件夹内的.bash_history啦!不过~/.bash_history 记录的是前一次登陆以前所执行过的指令,至于这一次登陆所执行的指令都被暂存在内存中,当你成功的登出系统后,该指令记忆才会记录到.bash_history当中!
    2. 命令与文件补全功能:([tab] 按键的好处)
      (1)[Tab] 接在一串指令的第一个字的后面,则为命令补全;
      (2)[Tab] 接在一串指令的第二个字以后时,则为“文件补齐”!
      (3)若安装bash-completion软件,则在某些指令后面使用[tab]按键时,可以进行“选项/参数的补齐”功能!
      例如:查看环境当中所有以c开头的指令:按下c[tab][tab]
    3. 命令别名设置功能(alias):假如我想用lm这个自定义的命令来取代ls -al,以查看本目录下面的所有文件及其属性(包含隐藏文件),也就是说,lm等同于ls -al。可以使用alias来实现!在命令行输入alias可查看目前的命令别名有哪些,也可以直接下达命令来设置别名:alias lm='ls -al'
    4. 程序化脚本(shell scripts):
    5. 万用字符(Wildcard):想要知道/usr/bin下面有多少以X为开头的文件:ls -l /usr/bin/X*

    查询指令是否为Bash shell的内置命令:type

    一、查看bash的说明文档:man bash。这个说明文档里面有其他的文件说明,因为为了方便shell的操作,bash内置了很多指令了。利用type指令可以知道某个指令是来自于外部指令(指的是其他非bash所提供的指令)或是内置在bash当中的:

    [root@www ~]type [-tpa] name
    # 选项与参数:
    # :不加任何选项与参数时,type会显示出name是外部命令还是bash内建命令
    # -t:当加入-t参数时,type会将name以底下这些字眼显示出他的意义:
    #      file:表示为外部命令;
    #      alias:表示该命令为命令别名所配置的名称;
    #      builtin:表示该命令为bash内建的命令功能;
    # -p  :如果后面接的name为外部命令时,才会显示完整文件名;
    # -a  :会由PATH变量定义的路径中,将所有含name的命令都列出来,包含alias
    
    # 范例一:查询一下ls这个命令是否为bash内建?
    [root@www ~]type ls
    ls is aliased to `ls --color=tty' <==未加任何参数,列出ls的最主要使用情况
    [root@www ~]type -t ls
    alias                             <==仅列出ls运行时的依据
    [root@www ~]type -a ls
    ls is aliased to `ls --color=tty' <==最先使用aliase
    ls is /bin/ls                     <==还有找到外部命令在/bin/ls
    
    # 范例二:cd呢?
    [root@www ~]type cd
    cd is a shell builtin             <==看到了吗?cd是shell内建命令
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    二、由于利用type搜寻后面的名称时,如果后面接的名称并不能以可执行文件的状态被找到,那么该名称是不会被显示出来的。也就是说,type主要在找出“可执行文件”而不是一般文件文件名喔!所以,typ 也可以用来作为类似which指令的用途啦!找指令用的!

    指令的下达与快速编辑按钮

    一、

    # 范例:如果命令串太长的话,如何使用两行来输出?
    [vbird@www ~]cp /var/spool/mail/root /etc/crontab \
    > /etc/fstab /root
    
    • 1
    • 2
    • 3

    上面这个指令将三个文件复制到/root目录下。不过,因为指令太长,可以利用[Enter]来将[Enter]这个按键“跳脱!”开来,让[Enter]按键不再具有“开始执行”的功能!好让指令可以继续在下一行输入。 需要特别留意,[Enter] 按键是紧接着反斜线(\)的,两者中间没有其他字符。 因为\仅跳脱“紧接着的下一个字符”而已!所以,万一我写成:\ [Enter],亦即[Enter]与反斜线中间有一个空格时,则\跳脱的是“空白键”而不是[Enter]按键!
    二、组合键

    组合键功能与示范
    [ctrl]+u/[ctrl]+k分别是从光标处向前删除指令串([ctrl]+u)及向后删除指令串([ctrl]+k)
    [ctrl]+a/[ctrl]+e分别是让光标移动到整个指令串的最前面([ctrl]+a)或最后面([ctrl]+e)

    Shell的变量功能

    管线命令 (pipe)

    一、管线命令|仅能处理经由前面一个指令传来的正确信息
    二、|后面接的第一个数据必定是指令,而且这个指令必须要能够接受standard input的数据才行

    撷取命令:cut, grep

    撷取命令是针对一行一行数据来分析的

    cut

    将讯息的某一段给他“切”出来

    [dmtsai@study ~]$ cut -d'分隔字符' -f fields #用于有特定分隔字符
    [dmtsai@study ~]$ cut -c 字符区间            #用于排列整齐的讯息
    选项与参数:
    -d  :后面接分隔字符。与 -f 一起使用;
    -f  :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思;
    -c  :以字符 (characters) 的单位取出固定字符区间;
    
    范例一:将 PATH 变量取出,我要找出第五个路径。
    [dmtsai@study ~]$ echo ${PATH}
    /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    #1 | 2 | 3 | 4 | 5 | 6 |
    
    [dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 5
    # 如同上面的数字显示,我们是以“:”作为分隔,因此会出现/home/dmtsai/.local/bin,那么如果想要列出第3与第5,就这样:
    [dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 3,5
    
    范例二:将 export 输出的讯息,取得第 12 字符以后的所有字串
    [dmtsai@study ~]$ export
    declare -x HISTCONTROL="ignoredups"
    declare -x HISTSIZE="1000"
    declare -x HOME="/home/dmtsai"
    declare -x HOSTNAME="study.centos.vbird"
    .....(其他省略).....
    # 注意看,每个数据都是排列整齐的输出!如果我们不想要“ declare -x ”时,就得这么做:
    [dmtsai@study ~]$ export | cut -c 12-
    HISTCONTROL="ignoredups"
    HISTSIZE="1000"
    HOME="/home/dmtsai"
    HOSTNAME="study.centos.vbird"
    .....(其他省略).....
    # -c 可以处理比较具有格式的输出数据!我们还可以指定某个范围的值,例如第 12-20 的字符,就是 cut -c 12-20 等等!
    
    范例三:用 last 将显示的登陆者的信息中,仅留下使用者大名
    [dmtsai@study ~]$ last
    root   pts/1    192.168.201.101  Sat Feb  7 12:35   still logged in
    root   pts/1    192.168.201.101  Fri Feb  6 12:13 - 18:46  (06:33)
    root   pts/1    192.168.201.254  Thu Feb  5 22:37 - 23:53  (01:16)
    # last 可以输出“帐号/终端机/来源/日期时间”的数据,并且是排列整齐的
    
    [dmtsai@study ~]$ last | cut -d ' ' -f 1
    # 由输出的结果我们可以发现第一个空白分隔的字段代表帐号,所以使用如上指令:
    # 但是因为 root   pts/1 之间空格有好几个,并非仅有一个,所以,如果要找出 
    # pts/1 其实不能以 cut -d ' ' -f 1,2 喔!输出的结果会不是我们想要的。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    常使用在分析一些数据或文字数据的时候!因为有时候我们会以某些字符当作分区的参数,然后来将数据加以切割,以取得我们所需要的数据。 ==尤其是在分析log文件的时候!==不过,cut在处理多空格相连的数据时,可能会比较吃力一点,所以某些时刻可能会使用awk

    grep

    grep是分析一行讯息, 若当中有我们所需要的信息,就将该行拿出来~支持正则表达式

    [dmtsai@study ~]$ grep [-acinv] [--color=auto] '搜寻字串' filename
    选项与参数:
    -a :将 binary 文件以 text 文件的方式搜寻数据
    -c :计算找到 '搜寻字串' 的次数
    -i :忽略大小写的不同,所以大小写视为相同
    -n :顺便输出行号
    -v :反向选择,亦即显示出没有 '搜寻字串' 内容的那一行!
    --color=auto :可以将找到的关键字部分加上颜色的显示喔!
    
    范例一:将 last 当中,有出现 root 的那一行就取出来;
    [dmtsai@study ~]$ last | grep 'root'
    
    范例二:与范例一相反,只要没有 root 的就取出!
    [dmtsai@study ~]$ last | grep -v 'root'
    
    范例三:在 last 的输出讯息中,只要有 root 就取出,并且仅取第一栏
    [dmtsai@study ~]$ last | grep 'root' | cut -d ' ' -f 1
    # 在取出 root 之后,利用上个指令 cut 的处理,就能够仅取得第一栏啰!
    
    范例四:取出 /etc/man_db.conf 内含 MANPATH 的那几行
    [dmtsai@study ~]$ grep --color=auto 'MANPATH' /etc/man_db.conf
    ....(前面省略)....
    MANPATH_MAP     /usr/games              /usr/share/man
    MANPATH_MAP     /opt/bin                /opt/man
    MANPATH_MAP     /opt/sbin               /opt/man
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    CentOS 7 当中,默认的grep已经主动加上--color=auto在alias内了喔!

  • 相关阅读:
    在C语言中,堆和栈是两种不同的内存分配机制
    申博|2024国内985院校申博时间参考
    Python面向对象 —— 类属性「二」(属性获取机制和陷阱、代码示例、执行流程分析)
    js + selenium 获取chatgpt的accessToken
    tkinter和Tkinter的区别
    前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— Web APIs(二)
    数据结构与算法_part_8_二叉树
    关于在Linux服务上安装nvm,踩坑步骤说明
    centos 8.2 配置 go 项目开发环境
    力扣经典题目之->移除值为val元素的讲解,的实现与讲解
  • 原文地址:https://blog.csdn.net/CaraYQ/article/details/127995730