本文是在学习《跟老男孩学Linux运维之shell编程实战》这本书时记录的知识点。看了这本书,我受益匪浅,当然这仅是我个人观点。下面我们言归正传,开始了解一下shell脚本吧!

    shell本身是一个命令解释器,它的作用是解释执行用户输入的命令及程序等。

    shell脚本语言的种类:sh、ksh、bash、csh、tcsh,Linux中主流的shell是bash,所以本文及后续shell脚本以bash为主。

    那我们如何查看Linux系统中默认的shell?

    [root@www ~]# cat /etc/redhat-release   ==>查看Linux系统版本  
    CentOS release 6.8 (Final)
    [root@www ~]# echo $SHELL          ==>查看系统默认的shel
    /bin/bash


  脚本的书写规范:

1. 脚本开头第一行

    一个规范的shell脚本在第一行会指出由哪个程序(解释器)来执行脚本中的内容。

    在Linux bash的编程中一般为:

    #!/bin/bash
    或
    #!/bin/sh

提示:

sh为bash的软连接,大多数情况下,脚本的开头使用“#!/bin/bash”和“#!/bin/sh”是没有区别  的, 但更为规范的写法是在脚本的开头使用“#!/bin/bash”。

由于老版本的bash中被暴露出存在较严重的安全漏洞,所以我们需要检测现有系统中的bash版本是否存在漏洞,那如何检测是否存在漏洞呢?方法如下:

[root@www ~]# env x='() { ;;}; echo be careful' bash -c "echo this is a test"
this is a test

如果返回如下两行,则表示需要尽快升级bash,不过,仅仅是用于学习和测试就无所谓了。

be  careful
this is a test

提示:升级方法:yum -y update bash

提示:

(1)不同语言的脚本的开头第一行有所不同,具体如下:

#!/bin/sh
#!/bin/bash
#!/usr/bin/awk
#!/bin/sed
#!/usr/bin/tcl
#!/usr/bin/expect              ==>expect解决交互式的语言开头解释器
#!/usr/bin/perl               ==>perl语言解释器
#!/usr/bin/env python            ==>python语言解释器

不同的脚本一般会保存为不同的扩展名,例如:

shell脚本:xxx.sh

Python脚本:xxx.py

expect脚本:xxx.exp

(2)查看bash的版本:

[root@www ~]# bash --version

2.脚本注释:

    在shell脚本中,“#”号开头的表示注释,用来对脚本进行注释说明。

3.脚本的执行:

        当shell脚本运行时,会先查找系统环境变量ENV,该变量指定了环境变量文件(加载顺序通常是/etc/profile、~/.bash_profile、

~/.bashrc、/etc/bashrc等),加载完上述环境变量后,shell就开始执行shell脚本中的内容。

    shell脚本是从上至下,从左至右一次执行每一行的命令及语句,即执行完一个命令后再执行下一个,如果在shell脚本中遇到子脚本,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令及语句。


提示:设置Linux的crond任务时,最好能在定时任务脚本中重新定义系统环境变量,否则,一些系统环境变量将不会被加载。


shell脚本执行的方法:

 (1)bash script-name或sh script-name :当脚本文件本身没有可执行权限时常使用的方法或脚本文件开头没有指定解释器时需要使用的方法。

 (2)path/script-name或./script-name:指在脚本的当前路径下执行脚本(前提是脚本需要有执行权限)

 (3)source script-name或 . script-name:这种方法通常是使用source或"."读入或加载指定的shell脚本文件(如san.sh)。依次执行脚本san.sh中的所有语句。这些语句将在当前父shell脚本father.sh进程中运行(其他几种模式都会启动新的进程执行子shell)。因此,使用source或“.”可以将san.sh脚本中的变量值或函数等的返回值传递到当前父shell脚本father.sh中使用,这是它与其他几种方法最大的区别。

    source或“.”命令的功能:在当前shell中执行source或“.”加载并执行的相关脚本文件中的命令及语句,而不是产生一个子shell来执行文件中的命令。

 (4)sh<script-name或 cat script-name|sh:同样适用于bash,这种方法使用的比较少。

结论:

通过source或“.”加载执行过的脚本,由于是在当前shell中执行脚本,因此在脚本结束后,脚本中的变量(包括函数)值在当前shell中依然存在,而sh和bash执行脚本都会启动新的子shell执行,执行完成后退回到父shell,因此变量(包括函数)值等无法保留。在进行shell脚本开发时,如果脚本中有引用或执行其他脚本的内容或配置文件的需求时,最好用source或“.”先加载该脚本或配置文件,处理完后,再将它加载到脚本的下面,就可以调用source或“.”加载的脚本及配置文件中的变量及函数等内容了。

4.shell脚本的基本规范及习惯:

(1)shell脚本的第一行是指定脚本解释器,通常为:

 #!/bin/bash
   或
 #!/bin/

(2)shell脚本的开头会加版本、版权等信息:

 #Date:2017-04-17
 #Author:Create  by  XiaoYu
 #Description:This script function is ...
 #Version:1.1
 可以修改~/.vimrc配置文件配置vim编辑文件时自动加上以上信息的功能。

(3)在shell脚本中尽量不用中文

      在shell脚本中尽量用英文注释,防止乱码问题,如果非要加载中文,请根据自身的客户端对系统进行字符集调整,如:export LANG="zh_CN.UTF-8",并在脚本中重新定义字符集设置,和系统保持一致。   

(4)shell脚本的命名应以.shw为扩展名。

(5)shell脚本应存放在固定的路径下,如:/server/scripts/

5.shell脚本代码书写的良好习惯:

(1)成对的符号应尽量一次性写出来,然后退格在符号里增加内容,以防止遗漏。

        成对的符号包括:{  }、[  ] 、‘ ’、` ` 、“ ”

(2)中括号[  ]两端至少要有1个空格。

(3)对于流程控制语句,应一次性将格式写完,再添加内容。 如:

if语句:

if  条件内容
    then
        内容
fi

for循环:

for
do
    内容
done

提示:while和until、case等语句也一样。

(4)通过缩进,让代码更易读。

(5)对于常规变量的字符串定义变量值应加双引号,并且等号前后不能有空格,需要所见即所得的字符引用,则用单引号,如果是命令的引用,则用反撇号。

(6)脚本中的单引号、双引号及反撇号必须为英文状态下的符号。



以上为本人在读《跟老男孩学Linux运维之shell编程实战》这本书时的笔记,如有任何版权问题,请留言。