美文网首页
Linux基础篇-第十二章-Shell Scripts

Linux基础篇-第十二章-Shell Scripts

作者: Js_Gavin | 来源:发表于2021-07-22 11:21 被阅读0次

    常用指令

    seq : 是连续 (sequence) 的缩写之意
          seq 1 100 :表示输出1-100
          可以使用{1..100} 来取代 $(seq 1 100) ,中间以两个小数点来代表连续出现的意思!例如要持续输出 a, b, c...g 的话, 就可以使用『 echo {a..g} 』这样的表示方式
    
    sh [-nvx] scripts.sh
           -n :不要执行 script,仅查询语法的问题;若语法没有问题,则不会显示任何信息
           -v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
           -x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!
    
    whoami :打印用户id
    

    什么是 Shell scripts

    什么是 shell script (程序化脚本) 呢?就字面上的意义,我们将他分为两部份。 在『 shell 』部分,我们在 十章的 BASH 当中已经提过了,那是一个文字接口底下让我们与系统沟通的一个工具接口。那么『 script 』是啥? 字面上的意义, script 是『脚本、剧本』的意思。整句话是说, shell script是针对 shell 所写的『脚本!』

    shell script 是利用 shell 的功能所写的一个『程序 (program)』,这个程序是使用纯文本文件,将一些 shell 的语法与指令(含外部指令)写在里面, 搭配正规表示法、管线命令与数据流重导向等功能,以达到我们所想要的处理目的。

    shell script 就像是早期 DOS 年代的批处理文件 (.bat) ,最简单的功能就是将许多指令汇整写在一起, 让使用者很轻易的就能够 一键式 的方法去处理复杂的动作 (执行一个文件 "shell script" ,就能够一次执行多个指令)。 而且 shell script 更提供数组、循环、条件与逻辑判断等重要功能,让用户也可以直接以 shell 来撰写程序,而不必使用类似 C 程序语言等传统程序撰写的语法。

    shell script 可以简单的被看成是批处理文件, 也可以被说成是一个程序语言,且这个程序语言由于都是利用 shell 与相关工具指令, 所以不需要编译即可执行,且拥有不错的除错 (debug) 工具,所以,他可以帮助系统管理员快速的管理好主机

    script 的撰写与执行

    在 shell script 的撰写中还需要用到底下的注意事项:

    1. 指令的执行是从上而下、从左而右的分析与执行;
    2. 指令的下达就如同第四章内提到的: 指令、选项与参数间的多个空白都会被忽略掉;
    3. 空白行也将被忽略掉,并且 [tab] 按键所推开的空白同样视为空格键;
    4. 如果读取到一个 Enter 符号 (CR) ,就尝试开始执行该行 (或该串) 命令;
    5. 至于如果一行的内容太多,则可以使用『 [Enter] 』来延伸至下一行;
    6. 『 # 』可做为批注!任何加在 # 后面的资料将全部被视为批注文字而被忽略!

    如此一来,我们在 script 内所撰写的程序,就会被一行一行的执行。现在我们假设你写的这个程序文件名是 /home/dmtsai/shell.sh 好了,那如何执行这个文件?很简单,可以有底下几个方法:

    1. 直接指令下达: shell.sh 文件必须要具备可读与可执行 (rx) 的权限,然后:
    2. 绝对路径:使用 /home/dmtsai/shell.sh 来下达指令;
    3. 相对路径:假设工作目录在 /home/dmtsai/ ,则使用 ./shell.sh 来执行
    4. 变量『PATH』功能:将 shell.sh 放在 PATH 指定的目录内,例如: ~/bin/
    5. 以 bash 程序来执行:透过『 bash shell.sh 』或『 sh shell.sh 』来执行
      重点就是要让那个 shell.sh 内的指令可以被执行

    撰写 shell script 的良好习惯建立

    1、较仔细的将程序的设计过程给他记录下来,记录一些历史纪录,以及程序修改的理念与逻辑概念等等, 在维护上面是轻松很多。
    2、建议一定要养成良好的 script 撰写习惯,在每个 script 的文件头处记录好:
    script 的功能;
    script 的版本信息;
    script 的作者与联络方式;
    script 的版权宣告方式;
    script 的 History (历史纪录);
    script 内较特殊的指令,使用『绝对路径』的方式来下达;
    script 运作时需要的环境变量预先宣告与设定。

    3、除了记录这些信息之外,在较为特殊的程序代码部分,个人建议务必要加上批注说明,可以帮助你非常非常多! 此外,程序代码的撰写最好使用巢状方式,在包覆的内部程序代码最好能以 [tab] 按键的空格向后推,这样你的程序代码会显的非常的漂亮与有条理!在查阅与 debug 上较为轻松愉快喔!另外,使用撰写 script 的工具最好使用 vim 而不是 vi ,因为 vim 会有额外的语法检验机制,能够在第一阶段撰写时就发现语法方面的问题

    script 的执行方式差异 (source, sh script, ./script)

    当你利用bash (或 sh) 直接执行的方法来处理时,系统会给予一支新的 bash 让我们来执行 showname.sh 里面的指令,因此你的firstname, lastname 等变量其实是在下图中的子程序bash 内执行的。 当showname.sh 执行完毕后,子程序 bash 内的所有数据便被移除,

    利用 source 来执行脚本:在父程序中执行

    image.png

    因为 source 对 script 的执行方式可以使用底下的图示来说明! showname.sh会在父程序中执行的,因此各项动作都会在原本的 bash 内生效!这也是为啥你不注销系统而要让某些写入~/.bashrc 的设定生效时,需要使用『 source ~/.bashrc 』而不能使用『 bash ~/.bashrc 』是一样的

    image.png

    善用判断式

    利用 test 指令的测试功能

    测试的标志 代表意义
    1、 关于某个档名的『文件类型』判断,如 test -e filename 表示存在否
    -e 该『档名』是否存在?(常用)
    -f 该『档名』是否存在且为文件(file)?(常用)
    -d 该『文件名』是否存在且为目录(directory)?(常用)
    -b 该『档名』是否存在且为一个 block device 装置?
    -c 该『档名』是否存在且为一个 character device 装置?
    -S 该『档名』是否存在且为一个 Socket 文件?
    -p 该『档名』是否存在且为一个 FIFO (pipe) 文件?
    -L 该『档名』是否存在且为一个连结档?
    2、 关于文件的权限侦测,如 test -r filename 表示可读否 (但 root 权限常有例外)
    -r 侦测该档名是否存在且具有『可读』的权限?
    -w 侦测该档名是否存在且具有『可写』的权限?
    -x 侦测该档名是否存在且具有『可执行』的权限?
    -u 侦测该文件名是否存在且具有『SUID』的属性?
    -g 侦测该文件名是否存在且具有『SGID』的属性?
    -k 侦测该文件名是否存在且具有『Sticky bit』的属性?
    -s 侦测该档名是否存在且为『非空白文件』?
    3、 两个文件之间的比较,如: test file1 -nt file2
    -nt (newer than)判断 file1 是否比 file2 新
    -ot (older than)判断 file1 是否比 file2 旧
    -ef 判断 file1 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode
    4、 关于两个整数之间的判定,例如 test n1 -eq n2
    -eq 两数值相等 (equal)
    -ne 两数值不等 (not equal)
    -gt n1 大于 n2 (greater than)
    -lt n1 小于 n2 (less than)
    -ge n1 大于等于 n2 (greater than or equal)
    -le n1 小于等于 n2 (less than or equal)
    5、 判定字符串的数据
    test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
    test -n string 判定字符串是否非为 0 ?若 string 为空字符串,则为 false。注: -n 亦可省略
    test str1 == str2 判定 str1 是否等于 str2 ,若相等,则回传 true
    test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false
    6、 多重条件判定,例如: test -r filename -a -x filename
    -a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传true。
    -o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
    ! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true

    利用判断符号 [ ]

    因为中括号用在很多地方,包括通配符与正规表示法等等,所以如果要在 bash 的语法当中使用中括号作为 shell 的判断式时,必须要注意中括号的两端需要有空格符来分隔。 假设我空格键使用『□』符号来表示,那么,在这些地方你都需要有空格键:

    image.png

    在 bash 当中使用一个等号与两个等号的结果是一样的! 不过在一般惯用程序的写法中,一个等号代表『变量的设定』,两个等号则是代表『逻辑判断 (是与否之意)』。 由于我们在中括号内重点在于『判断』而非『设定变量』,因此建议您还是使用两个等号较佳!

    使用判断符号 [ ] 注意事项:
    1、在中括号 [] 内的每个组件都需要有空格键来分隔;
    2、在中括号内的变数,最好都以双引号括号起来;
    3、在中括号内的常数,最好都以单或双引号括号起来。

    中括号的使用方法与 test 几乎一模一样啊~ 只是中括号比较常用在条件判断式 if ..... then ..... fi的情况中

    Shell script 的默认变数($0, $1...)

    script 针对参数已经有设定好一些变量名称了!对应如下:


    image.png

    执行的脚本档名为 0 这个变量,第一个接的参数就是1 ~ 所以,只要我们在 script 里面善用 $1 的话,就可以很简单的立即下达某些指令功能了!除了这些数字的变量之外,我们还有一些较为特殊的变量可以在 script 内使用来呼叫这些参数:
    $# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
    $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
    $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字符,默认为空格键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。

    shift:造成参数变量号码偏移

    shift 会移动变量,而且 shift 后面可以接数字,代表拿掉最前面的几个参数的意思。

    image.png

    第一次进行 shift 后他的显示情况是『 one two three four five six』,所以就剩下五个啦!第二次直接拿掉三个,就变成『 two three four five six 』。

    条件判断式

    只要讲到『程序』的话,那么条件判断式,亦即是『 if then 』这种判别式肯定一定要学习的! 因为很多时候,我们都必须要依据某些数据来判断程序该如何进行。简单的方式可以利用 && 与 || ,但如果我还想要执行一堆指令呢?那真的得要 if then 来。

    利用 if .... then

    if .... then 是最常见的条件判断式了~简单的说,就是当符合某个条件判断的时候, 就予以进行某项工作就是了。这个 if ... then 的判断还有多层次的情况:

    单层、简单条件判断式

    如果只有一个判断式要进行,那么我们可以简单的这样看:

    image.png

    除了将多个条件写入一个中括号内的情况』之外, 我还可以有多个中括号来隔开喔!而括号与括号之间,则以 && 或 || 来隔开,他们的意义是:
    1、 && 代表 AND ;
    2、 || 代表 or ;
    所以,在使用中括号的判断式中, && 及 || 就与指令下达的状态不同了
    举例来说:

    [ "${yn}" == "Y" -o "${yn}" == "y" ]
    
    上式可替换为
    
    [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]
    

    利用 case ..... esac 判断

    image.png

    这样的方式对于需要某些固定字符串来执行的变量内容就显的更加的方便

    使用『 case $变量 in 』这个语法中,当中的那个『 $变量 』大致有两种取得的方式:

    1、直接下达式:例如上面提到的,利用『 script.sh variable 』 的方式来直接给予 $1 这个变量的内容,这也是在 /etc/init.d 目录下大多数程序的设计方式。

    2、交互式:透过 read 这个指令来让用户输入变量的内容。

    利用 function 功能

    简单的说,其实, 函数可以在 shell script 当中做出一个类似自定义执行指令的东西,最大的功能是,可以简化我们很多的程序代码

    要注意的是,因为 shell script 的执行方式是由上而下,由左而右, 因此在 shell script 当中的 function 的设定一定要在程序的最前面, 这样才能够在执行时被找到可用的程序段

    另外, function 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的~ 这里很容易搞错喔~因为『 function fname() { 程序段 } 』内的 $0, $1... 等等与 shell script 的 $0 是不同的以 show123-2.sh 来说,假如我下达:『 sh show123-2.sh one 』 这表示在 shell script 内的 $1 为 "one" 这个字符串。但是在 printit() 内的 $1 则与这个 one 无关

    循环 (loop)

    while do done, until do done (不定循环)

    一般来说,不定循环最常见的就是底下这两种状态了:


    image.png

    while 的中文是『当....时』,所以,这种方式说的是『当 condition 条件成立时,就进行循环,直到condition 的条件不成立才停止』的意思。还有另外一种不定循环的方式:

    image.png

    这种方式恰恰与 while 相反,它说的是『当 condition 条件成立时,就终止循环, 否则就持续进行循环的程序段。』是否刚好相反

    for...do...done (固定循环)

    相对于 while, until 的循环方式是必须要『符合某个条件』的状态, for 这种语法,则是『 已经知道要进行几次循环』的状态!他的语法是

    image.png

    以上面的例子来说,这个 $var 的变量内容在循环工作时:

    1. 第一次循环时, $var 的内容为 con1 ;
    2. 第二次循环时, $var 的内容为 con2 ;
    3. 第三次循环时, $var 的内容为 con3 ;
    4. ....

    for...do...done 的数值处理

    除了上述的方法之外,for 循环还有另外一种写法!语法如下:

    image.png

    这种语法适合于数值方式的运算当中,在 for 后面的括号内的三串内容意义为:
    1、 初始值:某个变量在循环当中的起始值,直接以类似 i=1 设定好;
    2、 限制值:当变量的值在这个限制值的范围内,就继续进行循环。例如 i<=100;
    3、 执行步阶:每作一次循环时,变量的变化量。例如 i=i+1。

    shell script 的追踪与 debug

    scripts 在执行之前,最怕的就是出现语法错误的问题了!那么我们如何 debug 呢?有没有办法不需要透过直接执行该 scripts 就可以来判断是否有问题呢?当然是有的!我们就直接以 bash 的相关参数来进行判断!


    image.png

    总结

    0、shell script 是利用 shell 的功能所写的一个『程序 (program)』,这个程序是使用纯文本文件,将一些 shell 的语法与指令(含外部指令)写在里面, 搭配正规表示法、管线命令与数据流重导向等功能,以达到我们所想要的处理目的

    1、 shell script 用在系统管理上面是很好的一项工具,但是用在处理大量数值运算上, 就不够好了,因为 Shellscripts 的速度较慢,且使用的 CPU 资源较多,造成主机资源的分配不良。

    2、 在 Shell script 的文件中,指令的执行是从上而下、从左而右的分析与执行;

    3、 shell script 的执行,至少需要有 r 的权限,若需要直接指令下达,则需要拥有 r 与 x 的
    限;

    4、 良好的程序撰写习惯中,第一行要宣告 shell (#!/bin/bash) ,第二行以后则宣告程序用途、版本、作者等

    5、 对谈式脚本可用 read 指令达成;

    6、 要建立每次执行脚本都有不同结果的数据,可使用 date 指令利用日期达成;

    7、 script 的执行若以 source 来执行时,代表在父程序的 bash 内执行之意!

    8、 若需要进行判断式,可使用 test 或中括号 ( [] ) 来处理;

    9、 在 script 内,$0, $1, $2..., $@ 是有特殊意义的!

    10、 条件判断式可使用 if...then 来判断,若是固定变量内容的情况下,可使用 case $var in ... esac 来处理

    11、 循环主要分为不定循环 (while, until) 以及固定循环 (for) ,配合 do, done 来达成所需任务!

    12、 我们可使用 sh -x script.sh 来进行程序的 debug

    相关文章

      网友评论

          本文标题:Linux基础篇-第十二章-Shell Scripts

          本文链接:https://www.haomeiwen.com/subject/apavpltx.html