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重启一下脚本使修改成效,不必重启系统。
所以有时候要定义的东西在所有脚本里面都要用到就可以在/etc/profile中定义。
3.5 shell脚本执行的三种方式
(1)bash.script-name 和 sh.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)全局变量定义
全局变量也成环变量,他的定义应全部为大写,如APACHEERR或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
do
echo "do"
done
}
(3)变量的引用规范
在引用变量的时候,如果变量前后都有字符,则需要使用${APACHE_ERR}(加大括号的方式)引用变量,以防止产生歧义;当变量内容为字符串时,需要使用"${APACHE_ERR}"(外面加双引号的方式)引用变量;当变量内容为整数时,则最好直接用$APACHE_ERR符号引用变量。全局变量、局部变量、函数变量和数组变量也是如此。