目录

前言

一. shell 概述

1.1 shell 和 shell 脚本

1.1.1 什么是shell

1.1.2 shell的作用

1.1.3 shell脚本是什么

1.1.4 shell脚本能干什么

1.1.5 shell脚本使用场景

1.1.6 如何学习shell脚本

1.1.7 Linux 中的 shell 类型

二. shell 脚本编程基础

2.1 shell脚本的构成

2.2 Shell脚本执行方法

2.3 命名要求

2.4脚本错误

2.4.1 命令错误

2.4.2 语法错误

2.4.3 逻辑错误

2.4.4 查找代码的正确

三. 管道与重定向

3.1 管道

3.2重定向

3.2.1 交互式硬件设备

3.2.2 重定向操作

四、Shell脚本变量

4.1 Shell变量的作用

4.2 Shell变量的类型

4.2.1自定义变量

4.2.3 整数变量的算术计算 

4.2.4 环境变量 

4.2.5 只读变量

4.2.6 位置变量

4.2.7 预定义变量 

4.2.8 使用awk提取IP地址

五、总结


前言

Shell 脚本就是将要执行的命令按顺序保存到一个文本中,并给该文件可执行权限,方便一次性执行的一个程序文件。主要是方便管理员进行设置或管理,可结合各种 Shell 控制语句以完成更复杂的操作

一. shell 概述

1.1 shell 和 shell 脚本

1.1.1 什么是shell

Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户进行对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕反馈给用户。这种对话方式可是交互也可以是非交互式的,我们所输入的命令计算机是不识别的,这时就需要一种程序来帮助我们进行翻译,变成计算机能识别的二进制程序,同时又把计算机生成的结果返回给我们。

1.1.2 shell的作用

Linux系统中的Shell是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。
常见的 Shell 解释器程序有很多种,使用不同的 Shell 时,其内部指令、命令行提示符等方面会存在一些区别。通过/etc/shells 文件可以了解当前系统所支持的 Shell 脚本种类。

1.1.3 shell脚本是什么

shell脚本就是说我们把原来 linux 命令或语句放在一个文件中,然后通过这个程序文件去执行时,我们就说这个程序为 shell 脚本或 shell 程序;我们可以在脚本中输入一系统的命令以及相关的语法语句组合,比如变量,流程控制语句等,把他们有机结合起来就形成了一个功能强大的 shell 脚本

总结:将需要执行的命令保存到一个文件中,按照顺序执行,它不需要编译,它是解释型的

1.1.4 shell脚本能干什么

自动化完成软件的安装部署,如安装部署LAMP架构服务
自动化完成系统的管理,如批量添加用户
自动化完成备份,如数据库定时备份
自动化的分析处理,如网站访问量

1.1.5 shell脚本使用场景

重复性操作

交互性任务

批量事务处理

服务运行状态监控

定时任务执行

1.1.6 如何学习shell脚本

熟悉掌握各种linux命令
掌握脚本的标准格式
掌握脚本的基本语法

1.1.7 Linux 中的 shell 类型

以 CentOS 7 为例

[root@localhost ~]#cat /etc/shells
/bin/sh            #/bin/sh 是 bash 命令的软链接(已经被 /bin/bash 所替换)
/bin/bash        #基准于 GNU 的框架下发展出的 shell
/usr/bin/sh        #己经被 bash 所替换
/usr/bin/bash    #centos 和 redhat 系统默认使用 bash shell
/bin/tcsh        #csh 的增强版,与 csh 完全兼容,提供更多的功能
/bin/csh        #已经被 /bin/bash 所替换(整合 c shell,提供更多的功能)
/sbin/nologin    #奇怪的 shel1,这个 shell 可以让用户无法登录主机

二. shell 脚本编程基础

2.1 shell脚本的构成

第一行为“#!/bin/bash”,脚本申明(默认解释器):表示此行以下的代码语句是通过/bin/bash程序来执行。还有其他类型的解释器,
比如#!/usr/bin/python、#!/usr/bin/expect
注释信息:以“#”开头的语句表示为注释信息,被注释的语句在脚本运行时不会被执行
可执行语句:如echo命令,用于输出“ ”之间的字符串

如果想要把文本字符串和命令输出显示在同一行中,可以使用echo语句的 -n 参数。

示例:

[root@localhost ~]#vim first.sh   #使用vim编辑器编辑
 
#!/bin/bash                       #脚本解释器声明
#this is my first shell-script    #注释
echo 当前目录位于:                 #linux输出命令
pwd                               #linux命令

#不换行写法
echo -n 当前目录位于:
pwd

2.2 Shell脚本执行方法

#法一:指定路径的命令,要求文件必须有x权限
[root@localhost ~]#chmod +x /root/first.sh
[root@localhost ~]#cd /root/
[root@localhost ~]#./zhangao.sh
当前目录位于:
/root
#法二:指定Shell来解释脚本,不要求文件必须有x权限。
[root@localhost ~]#bash zhangao.sh
当前目录位于:
/root
#法三:source 脚本路径执行shell脚本
[root@localhost ~]#source zhangao.sh
当前目录位于:
/root

2.3 命名要求

    区分大小写

    不能使程序中的保留字和内置变量:如: if, for, hostname

    只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线“-",和主机名相反

    不要使用内置的变量,使用英文尽量使用词义通俗易懂,PATH

2.4脚本错误

2.4.1 命令错误

命令出错不会影响接下来的命令继续

2.4.2 语法错误

会影响接下来的命令继续

2.4.3 逻辑错误

只能自己去筛查

2.4.4 查找代码的正确

bash -n 脚本名称 (不在当前目录下加绝对路径)   检查语法错误
bash -x 脚本名称 (不在当前目录下加绝对路径)   检查逻辑错误

三. 管道与重定向

由于Shell脚本“批量处理”的特殊性,其大部分操作过程位于后台,不需要用户进行干预,因此要学会提取、过滤执行信息变得十分重要,所以我们需要重定向和管道。

3.1 管道

1.管道操作符:“|”: 将管道符号“|"左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。

[root@localhost ~]#ps aux |wc -l   #查看进程数
224
[root@localhost ~]#echo "123456"|passwd --stdin zhangsan #给张三设置密码

3.2重定向

3.2.1 交互式硬件设备

类型设备文件文件描述编号默认设备
标准输入/dev/stdin0键盘
标准输出/dev/stdout1显示器
标准错误输出/dev/stderr2显示器

3.2.2 重定向操作

类型操作符用途
重定向输入<从指定文件读取数据
重定向输出>将标准输出结果保存到指定的文件,并且覆盖原有文件
>>将标准输出追加到指定的文件的尾部,不覆盖原有内容
标准错误输出2>将错误信息保存到指定文件,并且覆盖原有文件
2>>将错误信息追加到指定文件的尾部,不覆盖原有内容
混合输出&>和2>&1

将标准输出,标准错误保存到同—文件中

示例1:

将123456重定向输出到pass.txt文件中,然后将pass.txt的内容重定向输入给用户张三的密码,从pass.txt 文件中取密码,需要注意SELinux 会影响此命令执行,若执行失败可尝试关闭SELinux(setenforce 0)。

[root@localhost ~]#useradd lili
[root@localhost ~]#echo "123abc" > pass.txt
[root@localhost ~]#passwd --stdin lili < pass.txt
更改用户 lili 的密码 。
passwd:所有的身份验证令牌已经成功更新。

示例2:

#将12345678输入到文件log.txt中
[root@localhost ~]#echo "12345678" > log.txt
[root@localhost ~]#cat log.txt
12345678

#再将112234写入log.txt中,这个时候会覆盖原来的数据
[root@localhost ~]#echo "112234" > log.txt
[root@localhost ~]#cat log.txt
112234

#继续将12345678写入log.txt中,使用>>,这个时候会追加原来的数据
[root@localhost ~]#echo "12345678" >> log.txt
[root@localhost ~]#cat log.txt
112234
12345678

示例3:

ls -lh > log.txt 2>&1 等同于 ls -lh &> log.txt > (将标准输出结果保存到指定的文件) 2>&1(将标准错误输出重定向到标准输出) &>(将标准输出、标准错误输出保存到同一文件)

四、Shell脚本变量

4.1 Shell变量的作用

(1)用来存放系统和用户需要使用的特定参数(值)

(2)变量名:使用固定的名称,由系统预设或用户定义

(3)变量值:能够根据用户设置、系统环境的变化而变化

4.2 Shell变量的类型

(1)自定义变量:由用户自己定义、修改和使用;

(2)特殊变量:环境变量,只读变量,位置变量,预定义变量。

4.2.1自定义变量

1.定义新的变量:

格式:变量名=变量值
示例:
[root@localhost ~]#abc=123

2.查看定义的变量的值:

格式echo $变量名
示例:
[root@localhost ~]#echo $abc
123

3.赋值时使用引号

(1)双引号:允许通过$符号引用其他变量值

(2)单引号:禁止引用其他变量值, $视为普通字符

(3)反撇号:命令替换,提取命令执行后的输出结果,``和$(…)作用相同

4.从键盘输入内容为变量赋值

#法一: read命令获取输入内容
格式:
read -p 提示信息 变量名
echo $变量名
###示例:
[root@localhost ~]#resault=`echo ${abc}3.3`
[root@localhost ~]#echo $resault
1233.3
[root@localhost ~]#read -p "请输入家庭住址:" address
请输入家庭住址:xuzhou

#法二:在脚本中编写,在命令行实现read获取
##示例:
[root@localhost ~]#vim address.sh
#!/bin/bash
read -p “请输入家庭地址” address
echo "xuzhou"
read -p “请输入你的家庭地址” address1
echo "suzhou"
echo "家庭地址是"
echo $address
echo "你的家庭地址是"
echo $address1

4.2.2变量作用范围

(1)默认情况下,新定义的变量只在当前的Shell环境中有效,因此称为局部变量。当进入子程序或新的子Shell环境时局部变量将无法再使用。

(2)可以通过内部命令export将指定的变量导出为全局变量,使用户定义的变量在所有的子Shell环境中能够继续使用。

变量名设置格式:变量名=变量值
全局变量格式:export 变量名=变量值

示例1:临时设置变量

示例2:永久设置变量,需要在/etc/profile文件里面添加

vim /etc/profile
export PATH+=:/mnt

[root@localhost ~]#source /etc/profile
[root@localhost ~]#echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/data:/mnt

4.2.3 整数变量的算术计算 

运算符:+ 加法、- 减法、\* 乘法、/除法、% 取余

常见表达式:

expr 变量1 运算符 变量2
var=$(expr 变量1 运算符 变量2)
var=$((变量1 运算符 变量2))
var=$[变量1 运算符 变量2]
let var=变量1 运算符 变量2
 
i++相当于i=$[$i + 1],i++是先赋值,再运算
i--相当于i=$[$i - 1],++i是先运算再赋值
i+=1相当于i=$[$i + 1]

示例1:使用管道符

[root@localhost data]#echo 1 + 2|bc
3

示例2:expr不可计算小数,并且变量和运算符之间需要空格分隔

示例3:计算乘法时,需要使用“\”转义符

示例4:取余只需要除后的余数

#法一
[root@localhost data]#expr 3 % 2
1

#法二:定义变量,使用反撇号
[root@localhost data]#shu=`expr 3 % 3`
[root@localhost data]#echo $shu

示例5:随机取余

示例5:使用let

示例6:i++和++i

4.2.4 环境变量 

使用 env 命令可以查看到当前工作环境下的环境变量

变量USER表示用户名称,HOME表示用户的宿主目录,LANG表示语言和字符集,PWD表示当前所在的工作目录,变量PATH表示可执行程序的默认搜索路径

配置文件:/etc/profile(全局生效)、~/.bash_profile(当前用户环境)

示例:将文件所在目录添加路径,可以执行脚本

4.2.5 只读变量

readonly命令用于定义只读shell变量和shell函数。readonly命令的选项-p可以输出显示系统中所有定义的只读变量。

格式:readonly 【选项】【参数】

[root@localhost data]#readonly abc=111
[root@localhost data]#abc=222  
bash: abc: 只读变量  #再想修改只读变量就无法修改了

4.2.6 位置变量

(1)当执行命令行操作时,第一个字段表示命令名或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量。 

(2)$n:n为数字,$0代表命令本身,1~9代表第一个到第九个参数,十以上的参数需要使用大括号表示,比如第十个参数为 ${10}

示例1:

 示例2:

 示例3:

4.2.7 预定义变量 

$* 和 $@:都会表示命令或脚本要处理的参数。

(1)$* :把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"$1 $2 $3 $4 "

(2)$@:把各个参数加上双引号分隔成n份的参数列表,每个参数作为一个字符串返回,代表“$1” “$2” “$3” “$4”

预定义变量    表示的意思
$*    把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"$1 $2 $3 $4 "
$@    把各个参数加上双引号分隔成n份的参数列表,每个参数作为一个字符串返回,代表“$1” “$2” “$3” “$4”
$0    表示当前执行的脚本或命令的名称
$#    表示命令或者脚本要处理的参数的个数
$?    表示前一条命令或脚本执行后的返回状态码,返回值为0表示执行正确,返回任何非0值均表示执行出现异常,也常被用于shell脚本中return退出函数并返回的退储值

预定义变量表示的意思
$*把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"$1 $2 $3 $4 "
$@把各个参数加上双引号分隔成n份的参数列表,每个参数作为一个字符串返回,代表“$1” “$2” “$3” “$4”
$0表示当前执行的脚本或命令的名称
$#表示命令或者脚本要处理的参数的个数
$?表示前一条命令或脚本执行后的返回状态码,返回值为0表示执行正确,返回任何非0值均表示执行出现异常,也常被用于shell脚本中return退出函数并返回的退储值

 示例:

 示例  (for循环)

 

4.2.8 使用awk提取IP地址

五、总结

重定向与管道操作是 Shell 环境中十分常用的功能,如果能够熟练的掌握并灵活的运用,将有助于编写代码简洁但功能强大的 Shell 脚本程序。

在使用 expr 进行计算的时候,变量必须是整数,不能是字符串,也不能含小数,否则会出错。

更多推荐

SHELL 脚本编程基础