1.运维
运维岗位----将项目部署上线,并且持续运行维护
自动化运维:就是将图里面所有的工作都使用自动化的方式来实现。
-
实现自动化的方式很多,常见的方式:工具和脚本。
-
工作中常见的脚本是shell脚本 和 其他开发语言脚本
-
shell脚本就是shell编程的一种具体实现
2.shell简介
既然我们是来学shell,首先第一个问题:shell是什么?
2.1 什么是shell
- shell的定义: 在计算机科学中,Shell就是一个命令解释器。
- shell是位于操作系统和应用程序之间,是他们二者最主要的接口,shell负责把应用程序的输入命令信息解释给操作系统,将操作系统指令处理后的结果解释给应用程序。
- shell位置图
总结:一句话,shell就是在操作系统和应用程序之间的一个命令翻译工具。**
2.2 shell的分类
- 基本上shell分两大类:图形界面shell和命令行shell
- 图形界面shell:图形界面shell就是我们常说的桌面
- 命令行式shell
- windows系统: cmd.exe 命令提示字符
- linux系统: sh / csh / ksh / bash / ...
- 我们常说的shell是命令行式的shell,在工作中常用的是linux系统下的bash。
2.3 查看系统shell信息
- 查看当前系统的shell类型
echo $SHELL
- 查看当前系统环境支持的shell
[root@linux-node1 ~]# cat /etc/shells
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
2.4 shell 脚本
-
shell使用方式
- 手工方式:手工敲击键盘,在shell的命令行输入命令,按Enter后,执行通过键盘输入的命令,然后shell返回并显示命令执行的结果, 逐行输入命令、逐行进行确认执行
- 脚本方式: 就是说我们把手工执行的命令a,写到一个脚本文件b中,然后通过执行脚本b,达到执行命令a的效果.
-
shell脚本定义: 当可执行的Linux命令或语句不在命令行状态下执行,而是通过一个文件执行时,我们将这个文件为shell脚本。
2.5 shell脚本示例现在我们来使用脚本的方式来执行以下
- 创建临时shell脚本文件 itcast.sh, 注意以
.sh
结尾
#!/bin/bash
# 这是临时shell脚本
echo 'nihao'
echo 'itcast'
- 脚本执行效果
[root@linux-node1 ~]# /bin/bash itcast.sh
nihao
itcast
2.6 shell与python在运维工作中的简单比较
- 习惯
shell历史悠久,使用时间长,Python时间短 - 执行方式
- shell命令------系统命令
特点:命令简介,功能强大 - python命令-----模块------系统命令
特点:可以编写复杂逻辑
- shell命令------系统命令
小结:
- shell 是 命令解释器
- shell 两分类图形+命令行(bash)
- 脚本 是可执行命令的组合
2.1.1 创建脚本
脚本创建工具:
创建脚本的常见编辑器是 vi/vim
脚本命名:
shell脚本的命名简单来说就是要有意义,方便我们通过脚本名,来知道这个文件是干什么用的
脚本内容:
各种可以执行的命令
注释内容:
- 单行注释:
除了首行的#不是注释外,其他所有行内容,只要首个字符是#,那么就表示该行是注释
#!/bin/bash
echo '1'
# echo '2' # 这一行就表示注释
echo '3'
- 多行注释:
多行注释有两种方法::<<! ... ! 和 :<<字符 ... 字符
#!/bin/bash
echo '1'
:<<! echo '2' 当然看不到
echo '3' 看不到
echo '4' 看不到
!
echo '5'
2.1.2 脚本执行
shell执行的方式:
Shell脚本的执行通常可以采用以下几种方式
bash /path/to/script-name 或 /bin/bash /path/to/script-name (强烈推荐使用)
/path/to/script-name 或 ./script-name (当前路径下执行脚本)
source script-name 或 . script-name (注意“.“点号后面有空格)
执行方式说明:
-
脚本文件本身没有可执行权限或者脚本首行没有命令解释器时使用的方法,我们推荐用bash执行。
使用频率:☆☆☆☆☆
-
脚本文件具有可执行权限时使用。
使用频率:☆☆☆☆
-
使用source或者.点号,加载shell脚本文件内容,使shell脚本内容环境和当前用户环境一致。
使用频率:☆☆☆
使用场景:环境一致性
区别:source或者.点号与其他执行方式的比较
test.sh 脚本内容如下:
#!/bin/bash
ps
终端执行命令如下:
python@ubuntu:~/Desktop$ ps # 返回当前终端运行的进程
PID TTY TIME CMD
34863 pts/1 00:00:00 bash # 当前终端开启的bash进程
34891 pts/1 00:00:00 ps
python@ubuntu:~/Desktop$ bash test.sh
PID TTY TIME CMD
34863 pts/1 00:00:00 bash # 当前终端开启的bash进程
34894 pts/1 00:00:00 bash # 执行bash test.sh命令时开启了一个子进程
34895 pts/1 00:00:00 ps
python@ubuntu:~/Desktop$ source test.sh
PID TTY TIME CMD
34863 pts/1 00:00:00 bash # 只有当前终端开启的bash进程,执行
34900 pts/1 00:00:00 ps
test.sh 脚本内容如下:
#!/bin/bash
echo $user
终端执行命令如下:
python@ubuntu:~/Desktop$ user=python # 当前终端定义变量
python@ubuntu:~/Desktop$ echo $user # 打印变量
python
python@ubuntu:~/Desktop$ bash test.sh # 使用bash方式会开子进程,不能使用当前终端定义的变量
python@ubuntu:~/Desktop$ source test.sh # 使用source方式不会开子进程,能使用当前终端定义的变量
python
总结:source或者.点号执行方式不会开启子进程,能共享当前终端定义的变量,其他执行方式会开启子进程
2.1.2 脚本开发规范
-
脚本命名要有意义,文件后缀是.sh
-
脚本文件首行是而且必须是脚本解释器
#!/bin/bash
-
脚本文件解释器后面要有脚本的基本信息等内容
-
脚本文件中尽量不用中文注释
尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰 常见的注释信息:脚本名称、脚本功能描述、脚本版本、脚本作者、联系方式等
-
脚本文件常见执行方式:bash 脚本名
-
脚本内容执行:从上到下,依次执行
-
代码书写优秀习惯
1. 成对内容的一次性写出来,防止遗漏。 如:()、{}、[]、''、``、"" 2. []中括号两端要有空格,书写时即可留出空格[ ],然后再退格书写内容 3. 流程控制语句一次性书写完,再添加内容
-
通过缩进让代码易读(即该有空格的地方就要有空格)
小结:
-
shell脚本命名:有意义,便于知道脚本的目的
-
shell脚本的注释:单行(#)、多行(:<<字符 ... 字符)
-
shell脚本标准执行方法: /bin/bash /path/to/script-name
-
shell脚本开发规范重点:2-4-5
-
shell脚本开发小技巧:6-7
2.2.1 变量介绍
变量定义
变量名=变量值
shell 中的变量分为三大类
本地变量、全局变量、shell内置变量
2.2.2 本地变量
本地变量是什么
本地变量是:在当前系统的某个环境下才能生效的变量,作用范围小。
本地变量包含两种:普通变量和命令变量
-
普通变量
普通变量的定义方式有如下三种,接下来我们就分别说一下这三种方式
-
方式一:
变量名=变量值
重点:
变量值必须是一个整体,中间没有特殊字符
-
方式二:
变量名='变量值'
重点:
不解析变量值的内容
-
方式三:
变量名="变量值"
重点:
如果变量值范围内,有可以解析的变量A,那么首先解析变量A,将A的结果和其他内容组合成一个整体,
重新赋值给变量B
习惯:数字不加引号,其他默认加双引号
-
-
命令变量
命令变量有两种定义方式,接下来我们就来介绍一下这两种方式
-
定义方式一:
变量名=\`命令\`
注意:`是反引号
-
定义方式二:
变量名=$(命令)
执行流程:
1、执行`或者$()范围内的命令
2、将命令执行后的结果,赋值给新的变量名A
-
2.2.3 全局变量
全局变量是什么
全局变量是:在当前系统的所有环境下都能生效的变量。
环境是什么
环境是:每打开一个终端是一个shell环境,使用非source执行方式时,会开启子进程,也是一个shell环境,称为子shell环境。
查看全局变量
可以通过命令查看所有全局变量
env # 只显示全局变量,主要是加载了~/.bashrc和/etc/profile文件
定义全局变量
-
方法一:
变量名=值
export 变量
-
方法二:(最常用)
export 变量名=值
全局变量演示:
python@ubuntu:~/Desktop$ env | grep user # 当前全局变量中没有user变量
python@ubuntu:~/Desktop$ export user=python3
python@ubuntu:~/Desktop$ env | grep user # 当前全局变量中有user变量
user=python3
打开新的终端执行env命令:
python@ubuntu:~/Desktop$ env | grep user # 当前全局变量中没有user变量
test.sh 脚本内容如下:
#!/bin/bash
echo $user
终端执行命令如下:
python@ubuntu:~/Desktop$ user=python3
python@ubuntu:~/Desktop$ echo $user
python3
python@ubuntu:~/Desktop$ bash test.sh # 当前shell环境有user变量,但是局部变量,子shell无法使用
python@ubuntu:~/Desktop$ export user
python@ubuntu:~/Desktop$ bash test.sh # user变为全局变量,子shell可以使用
python3
test.sh 脚本内容如下:
#!/bin/bash
export user=python3
echo $user
终端执行命令如下:
python@ubuntu:~/Desktop$ echo $user # 当前shell环境下没有user变量
python@ubuntu:~/Desktop$ bash test.sh # 在test.sh脚本中定义了全局变量
python3
python@ubuntu:~/Desktop$ echo $user # 在当前shell环境下没法使用子shell定义的全局变量
总结:在终端中定义全局变量时,只对当前shell环境及子shell环境有效,对新开的终端无效,当前终端关闭后,它定义的全局变量消失。
如果想要自己定义的全局变量在跟系统的全局变量一样在所有环境都有效,需要在~/.bashrc或/etc/profile文件中定义:
- 修改~/.bashrc后,直接打开新的终端,定义的全局变量就生效了,此方式只对当前用户有效
- 修改/etc/profile时,需要重启操作系统,定义的全局变量才生效,此方式对所有用户有效
- 上面两种方式在修改文件后,如果想让全局变量在当前终端生效,需要执行命令source ~/.bashrc或source /etc/profile
2.2.4 变量查看和取消
-
查看变量:
- 方式一:
$变量名
- 方式二:
"$变量名"
- 方式三:
${变量名}
- 方式四:标准使用方式
"${变量名}"
-
取消变量:
unset 变量名
2.2.5 shell内置变量
我们之前学习的本地变量,全局变量都是需要通过定义,然后才能实现相应功能的,那么有没有一些变量我们可以直接拿过来使用实现某种具体的功能呢?有,这就是shell内置变量
和脚本文件有关
符号 | 意义 |
---|---|
$0 | 获取当前执行的shell脚本文件名 |
$$ | 获取执行shell脚本的进程号 |
$n | 获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9就要用大括号括起来${10} |
$# | 获取当前shell命令行中参数的总个数 |
$? | 获取执行上一个指令的返回值(0为成功,非0为失败) |
内置变量演示效果:
- $0 获取脚本的名称
- $$ 获取执行shell脚本的进程号
示例:
脚本内容如下:
#!/bin/bash
# 获取脚本的名称
echo "我脚本的名称是: file.sh"
echo "我脚本的名称是:$0"
echo "我脚本执行的进程号的是:$"
-
$# 获取当前脚本传入参数的数量
-
$n 获取当前脚本传入的第n个位置的参数
示例:
脚本内容如下:
#!/bin/bash
# 获取当前脚本传入的参数数量
echo "当前脚本传入的参数数量是: $#"
# 获取指定位置的参数
echo "第一个位置的参数是: $1"
echo "第二个位置的参数是: $2"
echo "第三个位置的参数是: $3"
echo "第四个位置的参数是: $4"
- $? 获取文件执行或者命令执行的返回状态值
示例:
终端执行命令如下:
bash nihao # 不存在nihao文件
bash: nihao: No such file or directory
echo $?
127
ls
file1.sh num.sh test.sh weizhi.sh
echo $?
0
- 字符串精确截取
格式:${变量名:起始位置:截取长度}
示例:
${file:0:5} 从第1个字符开始,截取5个字符
${file:5:5} 从第6个字符开始,截取5个字符
${file:0-6:3} 从倒数第6个字符开始,截取之后的3个字符
默认值相关
- 场景一:
变量a如果有内容,那么就输出a的变量值
变量a如果没有内容,那么就输出默认的内容
格式:
${变量名:-默认值}
套餐示例:
如果我输入的参数为空,那么输出内容是 "您选择的套餐是: 套餐 1"
如果我输入的参数为n,那么输出内容是 "您选择的套餐是: 套餐 n"
脚本内容如下:
#!/bin/bash
# 套餐选择演示
a="$1"
echo "您选择的套餐是: 套餐 ${a:-1}"
- 场景二:
无论变量a是否有内容,都输出默认值
格式:
${变量名+默认值}
场景示例:
不管我说国家法定结婚年龄是多少岁,都输出国家法定结婚年龄(男性)是22岁
脚本内容如下:
#!/bin/bash
# 默认值演示示例二
a="$1"
echo "国家法定结婚年龄(男性)是 ${a+22} 岁"
小结:
-
shell三种变量: 本地+全局+内置
-
本地变量种类:
普通变量定义格式: 变量值 '变量值' "变量值"
命令变量定义格式: `命令` $(命令)
-
全局变量:
查看命令:env
标准定义格式:export 变量名=变量值
-
普通变量查看方法:$变量名 "$变量名" ${变量名} "${变量名}"
-
变量取消专用命令:unset
-
shell内置变量三种类:
文件相关: $0 $n $# $?
字符串相关: ${变量名:起始位置:截取长度}
默认值相关: ${变量名:-默认值} ${变量名+默认值}
3.表达式
3.1.1 测试语句
Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0表示成功,值为其他时表示失败。使用专门的测试工具---test命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立。
测试语句的两种形式:
- test 条件表达式
- [ 条件表达式 ]
格式注意:
- 以上两种方法的作用完全一样,后者为常用。
- [ ]与内部的条件表达式之间需要有空格。
- test跟 [ ] 都是用于测试条件表达式是否成立,条件成立,状态返回值是0,条件不成立,状态返回值是1
不添加空格进行操作报错如下(该命令后面就会学到):
root@ubuntu:~# [-x /bin/bash ]
[-x: command not found
可以看到: 两侧没有空格,就会报错,报错原因是shell将[-x当做了一条可执行的命令,但是在path环境路径下找报道名为[-x的可执行文件
3.1.2 条件表达式
我们这部分内容主要是介绍,测试语句 [ 条件表达式 ] 中条件表达式这一部分,测试的结果可以使用 echo $? 来查看
- 逻辑表达式 逻辑表达式一般用于判断多个条件之间的依赖关系。 常见的逻辑表达式有:
- &&
- ||
&&符号
命令1 && 命令2
如果命令1执行成功,那么执行命令2
如果命令1执行失败,那么不执行命令2
示例:[ 1 = 1 ] && echo "条件成立" 条件成立 [ 1 = 2 ] && echo "条件成立"
||符号
命令1 || 命令2
1 如果命令1执行成功,那么不执行命令2
2 如果命令1执行失败,那么执行命令2
示例:[ 1 = 2 ] || echo "条件不成立" 条件不成立 [ 1 = 1 ] || echo "条件不成立"
- 文件表达式
-f 判断输入内容是否是一个文件
示例:[ -f weizhi.sh ] && echo "是一个文件" 是一个文件 [ -f weizhi.sddh ] || echo "不是一个文件" 不是一个文件
-d 判断输入内容是否是一个目录
示例:[ -d weizhi.sddh ] || echo "不是一个目录" 不是一个目录 mkdir nihao [ -d nihao ] && echo "是一个目录" 是一个目录
-x 判断输入内容是否可执行
示例:[ -x age.sh ] || echo "文件没有执行权限" 文件没有执行权限 [ -x test.sh ] && echo "文件有执行权限" 文件有执行权限
-
数值操作符 主要根据给定的两个值,判断第一个与第二个数的关系,如是否大于、小于、等于第二个数。常见选项如下:
-
n1 -eq n2 相等
-
n1 -gt n2 大于
-
n1 -gte n2 大于
-
n1 -lt n2 小于
-
n1 -lte n2 小于
-
n1 -ne n2 不等于
-
字符串比较
str1 == str2 str1和str2字符串内容一致
str1 != str2 str1和str2字符串内容不一致,!表示相反的意思
实践
判断字符是否内容一致
root@ubuntu:~# [ a == a ]
root@ubuntu:~# echo $?
0
root@ubuntu:~# [ a != a ]
root@ubuntu:~# echo $?
1
3.1.3 计算表达式
定义: 计算表达式,简单来说就是对具体的内容进行算数计算
格式:
- $(( 计算表达式 ))
- let 计算表达式
注意:$(())中只能用+-*/和()运算符,并且只能做整数运算
$(())使用示例
root@ubuntu:~# n=100
root@ubuntu:~# echo $(($n/5))
20
let使用示例
注意:
表达式必须是一个整体,中间不能出现空格等特殊字符
root@ubuntu:~# i=1
root@ubuntu:~# let i=i+7
root@ubuntu:~# echo $i
8
3.1小结:
- 了解 常用的两种测试语句
- 掌握 标准测试语句的格式和特点
- 说出 常用条件表达式种类
- 掌握 2种逻辑表达式的特点和使用场景
- 掌握 3种文件表达式的特点和使用场景
- 了解 4种数字表达式和2种字符串表达式的特点和使用场景
- 应用 2种计算表达式