第一章: shell快速入门:
一、运维简介:
1.运维简介以及企业中的那些事:
2、简单的运维知识
- 规划: 需要多少资源来支持项目的运行;
- 管理: 项目运行过程中的所有内容都管理起来;
- 流程规范: 所有操作都形成只读,提高工作效率;
- 平台: 大幅度提供工作效率;
- 监控: 实时查看项目运行状态指标;
- 告警: 状态指标异常,高职工作人员处理;
- 安全: 网站运营安全措施;
- 优化: 保证用户访问网站体验好;
2.1 自动化运维: 就是将所有的运维工作都是用自动化的方式来实现
- 实现自动化的方式很多,常见的方式:工具和脚本。
- 工作中常见的脚本是shell脚本 和 其他开发语言脚本
- shell脚本就是shell编程的一种具体实现;
二、shell简介:
1.什么是shell:
- shell的定义: 在计算机科学中,shell就是一个命令解释器;
- shell是位于操作系统和应用程序之间,是它们两者最重要的接口,shell负责把应用程序 的输入命令信息解释给操作系统,将操作系统指令处理后的结果解释给应用程序.
- shell位置图:
- 总结来说,shell就是操作系统和应用程序之间的一个命令翻译工具.
2.shell的分类:
- 基本上shell分两大类: 图形化界面shell和命令行shell
- 图形界面shell:图形界面shell就是常说的桌面
- 命令行shell:
- windows系统: cmd.exe命令提示符
- linux: sh / csh / ksh / bash / …
常说的shell是命令行式的shell,在工作中常用的是linux的bash.
- shell:https://baike.baidu.com/item/shell/99702
3.查看系统shell信息:
- 查看当前系统的shell类型:
echo $SHELL
/bin/bash
- 查看当前系统环境支持的shell:
cat /etc/shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
4.shell脚本:
-
shell使用方式:
- 手工方式: 手工敲击键盘,在shell的命令行输入命令,按Enter后,执行通过键盘输入的命令,然后shell返回并显示命令执行的结果, 逐行输入命令、逐行进行确认执行;
- 脚本方式: 就是说把手工执行的命令a,写到一个脚本文件b中,然后通过执行脚本b,达到执行命令a的效果.
-
shell脚本定义: 当可执行的Linux命令或语句不在命令行状态下执行,而是通过一个文件执行时,将这个文件为shell脚本。
5.shell脚本示例:
5.1 创建临时shell脚本文件test.sh, 注意以.sh结尾
#!/bin/bash
# 这是临时shell脚本
echo "nihao"
echo "test"
5.2 脚本执行效果:
6.shell的优缺:
shell的优点:
- 存在时间长.拥有较多的积累;
- 编写简单;
- 对环境依赖小;
shell的劣势: - 无法失效件复杂的功能;
- 不支持线代编程语言的高级特性: 面向对象;
第二章: shell基础知识:
一、shell脚本:
1.创建脚本
脚本创建工具:(命令行)
创建校本的常见编辑器是:vi/vim
笔者个人习惯使用:nano
脚本命名:
- shell脚本的命名简单来说就是要有意义,方便通过 脚本名,来知道这个文件是干什么用的;
- 文件名以.sh结尾;
脚本内容:
- 首行指定解释器: #!/bin/bash;
- 命令罗列和语法套用;
注释内容:
- 单行注释:
除了首行的#不是注释外,其他所有行内容,只要首个字符是#,那么就表示该行是注释
#!/bin/bash
echo '1'
# echo '2' # 这一行就表示注释
echo '3'
- 多行注释:
多行注释有两种方法::<<! … ! 和 :<<字符 … 字符
#!/bin/bash
echo '1'
:<<! echo '2'
echo '3'
echo '4'
!
echo '5'
2. 脚本执行:
shell执行大方式:
shell脚本的执行通常可以采用以下几种方式:
bash /path/to/script-name or /bin/bash /path/to/script-name
/path/to/script-name or ./script-name (注意是在当前目录下执行脚本)
source script-name or . 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后者点号(.)执行方式不会开启子进程,能共享当前终端定义的变量,其他执行方式会开启子进程.
执行机制:
3. 脚本开发规范:
- 脚本命名要有意义,文件后缀是.sh;
- 脚本文件首行是而且必须是脚本解释器;
#!/bin/bash
...
-
脚本文件解释器后面要有脚本的基本信息等内容;
-
脚本文件中尽量不用中文注释
尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰
常见的注释信息:脚本名称、脚本功能描述、脚本版本、脚本作者、联系方式等
-
脚本文件常见执行方式:bash 脚本名
-
脚本内容执行:从上到下,依次执行
-
代码书写优秀习惯
- 成对内容的一次性写出来,防止遗漏。
如:()、{}、[]、’’、``、""- []中括号两端要有空格,书写时即可留出空格[ ],然后再退格书写内容
- 流程控制语句一次性书写完,再添加内容
- 通过缩进让代码易读(即该有空格的地方就要有空格)
二、变量:
1.变量定义:
1.1 普通变量:
普通变量的定义方式有如下三种:
-
方式一:
变量名=变量值 重点:变量值必须是一个整体,中间没有特殊字符 -
方式二:
变量名=‘变量值’ 重点:不解析变量值的内容 -
方式三:
变量名=“变量值” 重点:如果变量值范围内,有可以解析的变量A,那么首先解析变量A,将A的结果和其他内容组合成一个整体,重新赋值给变量B
习惯:数字不加引号,其他默认加双引号
1.2 命令变量:
命令变量有两种定义方式:
- 方式一: 变量名=
命令
(注意:`是反引号) - 方式二: 变量名=$(命令)
执行流程:
- 执行`或者$()范围内的命令;
- 将命令执行后的结果,赋值给新的变量名A
2.变量访问:
2.1 查看变量:
- 方式一: $变量名
- 方式二: “$变量名”
- 方式三: ${变量名}
- 方式四: 标准使用方式"${变量名}"
2.2 取消变量:
unset 变量名
3. 变量分类:
**shell中变量分为三大类:**本地变量、全局变量、shell内置变量
3.1 本地变量:
本地变量是在当前系统的某个环境下草能生效的变量,最用范围小.
3.2 全局变量:
全局变量是什么:
全局变量是: 在当前系统的所有环境下都能生效的变量
环境是什么:
环境是每打开一个终端是一个shell环境,使用非source执行方式时,会开启子进程,也是一个shell环境,成为子shell环境
查看全局变量:
可以通过命令查看所有的全局变量
env # 只显示全局变量,主要是加载了~/.bashrc和/etc/profile文件
定义全局变量:
- 方法一:
变量名=值
export 变量 - 方法二(常用):
export 变量名=值
生效范围:
只对当前shell环境及子shell环境有效,shell退出后全局变量消失
全局变量演示:
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定义的全局变量
如果想要自己定义的全局变量在跟系统的全局变量一样在所有环境都有效,需要在~/.bashrc或/etc/profile文件中定义:
- 修改~/.bashrc后,直接打开新的终端,定义的全局变量就生效了,此方式只对当前用户有效
- 修改/etc/profile时,需要重启操作系统,定义的全局变量才生效,此方式对所有用户有效
- 上面两种方式在修改文件后,如果想让全局变量在当前终端生效,需要执行命令source ~/.bashrc或source /etc/profile
5.shell内置变量:
5.1 和脚本文件有关
符号 | 意义 |
---|---|
$0 | 获取当前执行的shell脚本文件名 |
$$ | 获取执行shell脚本的进程号 |
$n | 获取当前执行的shell脚本的第n个参数值,n=1…9,当n为0时表示脚本的文件名,如果n大于9就要用大括号括起来${10} |
$# | 获取当前shell命令行中参数的总个数 |
$? | 获取执行上一个指令的返回值(0为成功,非0为失败) |
示例:
- $0 获取脚本的名称
- $$ 获取执行shell脚本的进程号
./file.sh
#!/bin/bash
# 获取脚本名称
echo "我的脚本名称是: file.sh"
echo "我的脚本名称是: $0"
echo "我的脚本执行进程号是:$$"
- $# 获取当前脚本传入参数的数量
- $n 获取当前脚本传入的第n个位置的参数
./file_2.sh
#!/bin/bash
# 获取当前脚本传入的参数数量
echo "当前脚本传入的参数数量是: $#"
# 获取指定位置的参数
echo "第一个位置参数是: $1"
echo "第二个位置参数是: $2"
echo "第三个位置参数是: $3"
- $? 获取文件执行或者命令执行的返回状态值
5.2 字符串精确截取:
格式: ${变量名:起始位置:截取长度}
示例:
${file:0:5} 从第1个字符开始,截取5个字符
${file:5:5} 从第6个字符开始,截取5个字符
${file:0-6:3} 从倒数第6个字符开始,截取之后的3个字符
5.3 默认值设置:
- 场景一:
变量a如果有内容,那么久输出a的变量值; 否则输出默认值;
格式: ${变量名: -默认值}
#!/bin/bash
# 套餐选择示例:
# 参数接收.如果有参数,则"您选择的套餐是: 套餐n", 否则默认为1
a="$1"
echo "您选择的套餐是: 套餐${a:-1}"
- 场景二:
如果变量没有定义,将默认值赋值给变量
格式:${变量名:=默认值}
file_3.sh
#!/bin.bash
# 不管输入的年龄四多少,都输出国家的法定结婚年龄(男性)22岁
a="$1"
echo "国家的法定结婚年龄是${a:=22}岁"
echo "${a}"
- 场景三:
当变量存在的时候输出提示信息:
格式: ${变量名:+提示信息}
#!/bin/bash
当脚本获取到参数时提示已经获取参数
# 默认场景二
a="$1"
echo "${a:+已经获得第一个参数}"
第三章: shell进阶:
一、表达式:
1.测试语句
shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0表示成功,其他值表示失败. 使用专门的测试工具–test命令,可以对特定条件进行测试,并根据返回来判断条件是否成立.
测试语句的两种形式:
- test 条件表
- [条件]
格式注意:
- 以上两种方法的作用完全一样,后者为常用;
- [ ]与内部的条件表达式之间需要空格;
- test跟[ ]都用于测试条件表达式是否成立, 条件成立返回0,不成立则返回1;
2 数值比较:
主要根据给定的菱格数值, 判断大小关系:
表示 | 意义 |
---|---|
n1 -eq n2 | 相等 |
n1 -gt n2 | 大于 |
n1 -ge n2 | 大于等于 |
n1 - lt n2 | 小于 |
n1 -le n2 | 小于等于 |
n1 -ne n2 | 不等于 |
3.字符串比较:
表示 | 意义 |
---|---|
str1 == str2 | 内容一致 |
str1 != str2 | 内容不一致 |
示例: 判断字符串是否一致
root@ubuntu:~# [ a == a ]
root@ubuntu:~# echo $?
0
root@ubuntu:~# [ a != a ]
root@ubuntu:~# echo $?
1
4 逻辑表达式:
逻辑表达式一般用于判断多个条件之间的依赖关系.常见的逻辑表达式有:
- &&
- ||
&&符号:(与)
格式: 命令1 && 命令2
如果1执行成功,那么执行2; 如果1执行失败,那么不执行2
[ 1 = 1 ] && echo "条件成立"
条件成立
[ 1 = 2 ] && echo "条件成立"
||符号:(或)
格式: 命令1 || 命令2
如果1执行成功,不执行2;如果1执行失败,执行2
[ 1 == 2 ] || echo "条件不成立"
条件不成立
[ 1 == 1 ] || echo "条件不成立"
5.文件表达式:
-f 判断输入内容是否是一个文件
[ -f test.sh ] && echo "是一个文件"
是一个文件
[ -f hahah.dsdl ] || echo "不是一个文件"
不是一个文件
-d 判断输入的内容是否是一个目录
[ -d test.sh ] || echo "不是一个目录"
不是一个目录
mkdir hello
[ -d hello ] && echo "是一个目录"
-x 判断输入的内容是否是可执行的
[ -x age.sh ] || echo "文件没有权限"
文件美玉权限
[ -x test.sh ] && echo "文件可执行"
文件可执行
6.计算表达式:
定义:
计算表达式, 简单来说就是对具体的内容进行算术运算.
格式:
- $((计算表达式))
- 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
注意:
表达式必须是一个整体,中间不能出现空格等特殊符号
二、linux常见符号
1.重定向符号:
在shell脚本中有两种常见的重定向符号>和>>
">"符号的作用:
">"表示将符号左侧的内容或者输出结果,以覆盖的方式输入到右侧文件中;
">>"符号的作用:
">>"表示符号左侧的内容追加的方式输入到右侧文件的行尾;
2.管道符:
定义: | 这个是管道符,传递消息使用的
使用格式: 命令1 | 命令2
管道左侧命令1执行后的结果作为输入传递到右侧的命令2使用
示例:
fei@feivpc:~/Desktop$ env |grep SHELL
GNOME_SHELL_SESSION_MODE=ubuntu
SHELL=/bin/bash
3.其他符号:
1.后台展示符号 &
跟在任一条命令之后,将一个命令从前台转到后台执行
使用格式:在命令之后添加 &开启一个新的进程执行,不影响当前进程的操作
admin-1@ubuntu:~# sleep 10 &
[1] 4198
admin-1@ubuntu:~# ps aux | grep sleep
root 4198 0.0 0.0 9032 808 pts/17 S 21:58 0:00 sleep 10
root 4200 0.0 0.0 15964 944 pts/17 S+ 21:58 0
2.linux系统垃圾桶:
/dev/null 是linux下的一个设备文件,这个文件类似于一个垃圾桶,很多不重要的信息可以指向向其重定向
特点是:容量无限大
3.常见命令详解:
1.grep命令详解:
grep命令是常用的一个强大的文本搜索命令.
命令格式: grep [参数] [关键字] <文件名>
注意:
查看某个文件的内容的时候,是需要有<文件名> grep命令在结合|(管道符)使用的情况下,后面的<文件名>是没有的
参数详解:
- -c: 只输出匹配行的计数;
- -n: 显示匹配行及行号;
- -v: 显示不包含匹配文本的所有行;
模板文件
admin-1@ubuntu:~$ cat find.txt
nihao aaa
nihao AAA
NiHao bbb
nihao CCC
- -c: 输出匹配到aaa的个数
admin-1@ubuntu:~$ grep -c aaa find.txt
1
- -n: 输出匹配内容,同时显示行号
admin-1@ubuntu:~$ grep -n CCC find.txt
4:nihao CCC
- -v: 匹配到的内容部输出,输出不匹配的内容
admin-1@ubuntu:~$ grep -v ni find.txt
NiHao bbb
小技巧: 精确定位错误代码
grep -nr [错误关键字] *
2.sed命令详解:
3.awk命令详解:
第四章 shell控制流程:
1. 简单流程控制语句:
1.1 单分支if语句:
- 语法格式:
if [ 条件 ]
then
指令
fi
场景: 单一条件,只有一个输出
#!/bin/bash
# 但if语句的使用场景
if [ "$1" == "nan" ]
them
echo "性别是 男"
fi
1.2 双分支if语句:
- 语法格式:
if [ 条件 ]
them
指令1
else
指令2
fi
场景: 一个条件,两种结果
#!/bin/bash
# 双分支场景
if [ "$1" == "nan" ]
them
echo "性别是 男"
else
echo "性别是 女"
fi
1.3 多分支if语句
- 语法格式:
if [ 条件 ]
then
指令1
elif [ 条件2 ]
then
指令2
else
指令3
fi
场景: n个条件, n+1个结果
多分支if语句示例
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
echo "您的性别是 男"
elif [ "$1" == "nv" ]
then
echo "您的性别是 女"
else
echo "您的性别,我不知道"
fi
综合应用:
要求脚本执行需要有参数,通过传入参数来实现不同的功能:
参数和功能详情如下:
参数 | 执行效果 |
---|---|
start | 服务器启动中… |
stop | 服务器关闭中… |
restart | 服务器重启中… |
- 脚本X.sh使用方式: X.sh [start|stop|restart]
- 脚本内容:
python@ubuntu:# cat if.sh
#!/bin/bash
# 多if语句的使用场景
if [ "$1" == "start" ]
then
echo "服务启动中..."
elif [ "$1" == "stop" ]
then
echo "服务关闭中..."
elif [ "$1" == "restart" ]
then
echo "服务重启中..."
else
echo "$0 脚本的使用方式: $0 [ start | stop | restart ]"
fi
1.4 case选择语句
if语句使用的时候,代码量很多,而且整体看起来确实有那么一丁点乱,有没有办法更好的实现这种效果呢?就是Case语句。
- case格式:
case 变量名 in
值1)
指令1
;;
...
值n)
指令n
;;
*)
指令n+1
;;
esac
注意:首行关键字是case,末行关键字esac选择项后面都有 )每个选择的执行语句结尾都有两个分号;
case示例:
场景:在多if语句的基础上对脚本进行升级
需求:
要求脚本执行需要有参数,通过传入参数来实现不同的功能。
参数和功能详情如下:
参数 | 执行效果 |
---|---|
start | 服务器启动中… |
stop | 服务器关闭中… |
restart | 服务器重启中… |
- 脚本X.sh使用方式: X.sh [start|stop|restart]
- 脚本内容:
case.sh
#!/bin/bash
# case语句使用场景
case "$1" in
"start")
echo "服务启动中..."
;;
"stop")
echo "服务关闭中..."
;;
"restart")
echo "服务重启中..."
;;
*)
echo "$0 脚本的使用方式: $0 [ start | stop | restart ]"
;;
esac
1.5 for循环语句:
循环指定的所有元素,循环完毕之后退出
- 语法格式:
for 值 in 列表
do
执行语句
done
注意: for循环总是接收in语句之后的某种类型的字列表,执行次数和list列表中的常数或者字符串的个数相当,当循环的数量足够了,就自动退出
- 示例:
for.sh
#!/bin/bash
for i in $(ls /etc)
do
echo "${i}"
done
1.6 while循环语句:
- 语法格式:
while 条件
do
执行语句
done
注意:条件的类型: 命令、[[ 字符串表达式 ]]、((数字表达式));
注意:continue用于跳过循环, break用于退出循环;
- while语句示例:
while1.sh
#!/bin/bash
a=1
while [ "${a}" -lt 5 ]
do
echo "${a}"
a=$((a+1))
done
python@fei-vpc:~/Desktop$ /bin/bash while1.sh
1
2
3
4
while2.sh
#!/bin/bash
#!/bin/bash
a=5
while true
do
echo "${a}"
if [ "${a}" -lt 0 ]
then
break
fi
a=$((a-1))
done
python@fei-vpc:~/Desktop$ /bin/bash while2.sh
5
4
3
2
1
0
-1
1.7 until循环语句:
- 语法格式:
until 条件
do
执行语句
done
注意:条件的类型: 命令、[[ 字符串表达式 ]]、((数字表达式));
- 示例
until.sh
#!/bin/bash
#!/bin/bash
a=1
until [ "${a}" -eq 5 ]
do
echo "${a}"
a=$((a+1))
done
python@fei-vpc:~/Desktop$ /bin/bash until.sh
1
2
3
4
2.函数:
2.1 函数基础:
- 什么是函数:
函数就是将某些命令组合起来实现某一特殊功能的方式,是脚本编写中非常重要的一部分。
2.2 函数实践
简单函数定义和调用
#!/bin/bash
dayin(){
echo "wo de ming zi shi: 111"
}
# 函数调用
dayin
函数传参和参数体内调用参数
#!/bin/bash
dayin(){
echo "wo de ming zi shi: $1"
}
# 函数调用
dayin 111
脚本传参,函数调用
#!/bin/bash
dayin(){
echo "wo de ming zi shi: $1"
}
# 函数调用
dayin $1
脚本传参,函数调用(生产用)
#!/bin/bash
canshu="$1"
dayin(){
echo "wo de ming zi shi: ${canshu}"
}
# 函数调用
dayin $1
2.3 小结