1.shell脚本简介

1.1 shell是什么?

shell是一个命令解释器,它在操作系统的最外层负责直接与用户对话,把用户的输入解释给操作系统;并处理各种各样的操作系统的输入,将结果输出到屏幕返回给用户,这种对话可以是交互式的(从键盘输入命令可以立即得到shell的回应)或非交互式的(脚本的方式)。

下图中黄颜色的部分就是shell处于操作系统的位置。

1.2 什么是shell脚本

当linux命令或语句不在命令行下执行(严格的说命令行执行的语句也是shell脚本),而是通过一个程序文件执行时,该程序就被成为shell脚本或shell程序。shell程序很类似DOS系统下的批处理程序(扩展名 *.bat)严格的说命令行下执行的语句也是shell ,如for循环。

范例1.清除/var/log下的messages日志文件的简单命令脚本

把所有命令放在一个文件里堆积起来就形成了脚本,下面是最简单的命令堆积起来的脚本,清空日志脚本。

cd /var/log
cat /dev/null > messages
Echo “Logs cleaned up.”

拓展:清空日志及文件内容的三种方法

[root@localhost ~]# echo >test.log 
[root@localhost ~]# >test.log 
[root@localhost ~]# cat /dev/null >test.log

应用场景:保留文件,清空内容。

2.Shell语言及种类介绍

2.1脚本语言的种类

在UNIX和LINUX中主要有两大类

(1)Bourne shell 包括(sh、ksh和 bash)

Bourne shell (sh)

Kor n shell (ksh)

Bourne Again shell(bash)

POSIX shell (sh)

(2)C shell 包括(csh和tcsh)

C shell (csh)

TENEC/TOPS C shell (tcsh)

Shell脚本是弱类型语言目前最常用的shell有标准的Bourne shell(sh)和C shell(csh).其中Bourne shell(sh)已经被bash shell取代。但是我们还是习惯称之为sh。

在linux中可以在/etc/shells下查看系统支持的shell,前三个是比较常用的,最常用的是/bin/sh,在工作中执行脚本用/bin/sh搞不定的我们可以用第一个。/sbin/nologin表示登录。

2.2 Shell与python|perl|php语言的区别和优势

Shell的优势在于处理操作系统底层的业务,因为有大量的系统命令做支撑。Python,php的优势在于开发运维工具,web界面的管理工具以及web业务的开发等。

2.3 常用操作系统的默认shell

Linux是Bourne Again shell(bash)可以用echo $SHELL查看

Salaris和Free BSD 缺省的是Bourne shell(sh)

AIX下是korn shell(ksh)

HP-UX缺省的是POSIX Shell(sh)

3.Shell脚本的建立与执行

3.1 Shell脚本的建立

shell脚本通常在shell编辑器中完成(推荐使用vim编辑器),脚本第一行会指出由哪个程序(解释器)来执行脚本中的内容,通常会用#!/bin/bash或#!/bin/sh,如果不写第一行就会用系统默认的shell解释器。

3.2 sh和bash的区别

用ls –l /bin/sh查看会发现sh为bash的软连接

推荐使用标准的写法#!/bin/bash, 可以用bash –-version查看shell版本

3.3 bash漏洞(破壳漏洞)##

漏洞是控制Linux计算机命令提示符的软件中存在的漏洞。

bash是一个为GNU计划编写的Unix shell。它的名字是一系列缩写:Bourne-Again SHell ,Bourne shell是一个早期的重要shell,由史蒂夫·伯恩在1978年前后编写,并同Version 7 Unix一起发布。 网络安全专家警告称,开源软件Linux中一个频繁使用的片段“Bash”,发现存在安全漏洞,其对计算机用户造成的威胁可能要超过2014年4月爆出的“心脏出血”(Heartbleed)漏洞。以上来自官方,大家可以在百度搜索“破壳漏洞”查看,下面为查看地址.

https://baike.baidu.com/item/bash%E6%BC%8F%E6%B4%9E/15843234?fr=aladdin&fromid=15848205&fromtitle=%E7%A0%B4%E5%A3%B3%E6%BC%8F%E6%B4%9E

3.4 shell脚本的执行

当shell脚本以非交互的方式(文件方式)运行时会先找到环境变量ENV,该变量指定了一个环境文件(.bashrc bash_profile /etc/bashrc /etc/profile)然后从该环境变量开始执行,再执行shell脚本的内容。

提示:系统环境变量不需要定义,但是用crond定时任务时要把系统环境变量在脚本中重新定义,因为crond能识别的系统环境变量很少。

拓展:如果有时候要定义的变量在所有脚本里面都要用到,就可以在/etc/profile全局环境变量文件中中定义。添加后所有用户就可以直接在开发的脚本中引用了。例如在/etc/profile最下面添加export NAME=zhangsan,注意这里的name要大写。添加完了我们用source重启一下脚本使修改成效,不必重启系统。

3.5 shell脚本执行的三种方式

(1)bash.script-namesh.script-name (推荐使用),注意在编写定时任务时要带shell全路径。

(2)path/script-name全路径加脚本或 ./script-name(当前路径下执行脚本)用第二种必须的有执行权限。

(3)source script-name./script-name(注意是“.”点号)

3.6 source和sh、bash的区别

source 或 “.”点号加载执行过的脚本,在脚本结束后脚本中的变量(包括函数)值,在当前shell中依然存在可以继续引用,而sh和bash则不行。因此在做shell脚本开发时,如果脚本中有需求引用其他脚本中的内容或者配置文件是最好用“.”点号或source在脚本开头加载该脚本或配置文件然后下面的内容就可以调用source加载的脚本及文件中的变量及函数等内容。

(1)用source和sh执行脚本的区别举例说明

以sh执行脚本为例,如下图:

这里echo $user 输出的内容为空,因为用sh执行脚本后user变量没有保存下来。

再以source执行脚本为例,如下图:

我们也可以在脚本中引用source 和“.”号

(2)“.”点号和source在系统函数库中的应用

一些服务的启动脚本,在调用系统函数库的时候也会用的“.”点号和source,我们查看一下系统函数库/etc/init.d/functions中用“.”点号执行脚本的例子,如下图:

(3)action结合source的使用

可以用source调用函数库结合action打印出很炫的效果,如下图:

上图中的action其实是在/etc/init.d/functions中定义了的函数,如下图:

我们也可以自己在functions中定义函数,然后就可以在脚本中直接调用自定义函数了。如下图:

也可以传参,如下图:

4.Shell脚本开发基本规范及习惯

4.1 开头指定脚本解释器

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

4.2 开头加版权信息

#Date: 2018-01-03 时间
#Author: Create by linzhongniao谁创作的
#Mail: xxxxxxxxxx@163.com 邮箱地址
#Function:This scripts function is ... 脚本是干啥的
#Version: 1.1  版本

4.3 脚本中不要用中文注释(可以用,最好别用)

尽量用英文注释防止本机或切换系统环境后中文乱码的困扰。如果必须要加中文,可以根据自身的客户端对系统进行字符集的调整,如:export LANG="zh_CN.UTF-8",并在脚本中重新定义字符集,使其和系统的字符集一致。

4.4 脚本以.sh扩展名

例如:script-name.sh,还应该将开发的脚本放到固定的路径下,例如:/server/scripts/

4.5 成对内容一次写出来防止遗漏

[]中括号、{}大括号、‘’单引号、“”双引号和``反引号的两端要有空格,例如:中括号[]两端要有空格,先打中括号[]将光标移到中括号里,空两个空格再回退一个,然后再写代码。

4.6 流程控制语句书写方法

流程控制语句一次书写完成再添加内容如:if 语句,for循环。

如if语句一次完成应为:

if 条件内容
then
   内容
fi

4.7 shell脚本变量名及引用变量规范

(1)全局变量定义

全局变量也成环变量,他的定义应全部为大写,如APACHE_ERR或APACHEERR,名字对应的语义要尽量清晰,能够正确表达变量内容的含义,对于过长的英文单词用前几个字符替代,多个单词建用“_”连接,全局变量一般放在系统的全局路径中,并最好用export来定义,全局变量一般可以在任意的shell中直接使用,但是定时脚本中执行shell的时候最好在shell脚本中重新定义这些全局变量。

全局变量定义示例:

[root@yunweijichu ~]# tail -1 /etc/profile
export APACHEERR="hello"
[root@yunweijichu ~]# source /etc/profile 
[root@yunweijichu ~]# echo $APACHEERR
hello

(2)局部变量定义

局部变量定义也称普通变量,在常规shell脚本中,普通变量的命名要尽可能统一,可以使用驼峰语法即第二个单词首字母大写,或者每个单词首字母大写如CheckUrl。

提示:函数中定义变量可以使用local方式进行定义,使之只在本函数作用域内有效,防止函数中的与外部程序中的变量相同,从而导致程序异常,如下实现函数中定义变量的例子:

function CheckUrl(){
local i
for((i=0;i<n;i++))
do
echo "do"
done
}

(3)变量的引用规范

在引用变量的时候,如果变量前后都有字符,则需要使用${APACHE_ERR}(加大括号的方式)引用变量,以防止产生歧义;当变量内容为字符串时,需要使用“${APACHE_ERR}”(外面加双引号的方式)引用变量;当变量内容为整数时,则最好直接用$APACHE_ERR符号引用变量。全局变量、局部变量、函数变量和数组变量也是如此。