第1章 shell脚本

1.1 shell 简介

shell 的定义

1. 在计算机科学中,Shell就是一个命令解释器。
2. shell是位于操作系统和应用程序之间,是他们二者最主要的接口,shell负责把应用程序的输入命令信息解释给操作系统,将操作系统指令处理后的结果解释给应用程序。

**总结:**shell就是在操作系统和应用程序之间的一个命令翻译工具。

1.2 shell的分类

shell分两大类

1. 图形界面:就是我们常说的桌面
2. 命令行:windows系统:cmd.exe     命令提示字符linux系统:sh / csh / ksh / bash / ...

查看系统shell 信息

  1. 查看当前系统的shell类型
root@instance-nl5v4j4n:/home/kungs# echo $SHELL
/bin/bash
  1. 查看当前系统环境支持的shell
root@instance-nl5v4j4n:/home/kungs# cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/tmux
/usr/bin/screen

1.3 shell脚本

1. shell 使用方式

1. 手工方式:手工敲击键盘,在shell的命令行输入命令,按Enter后,执行通过键盘输入的命令,然后shell返回并显示命令执行的结果.
重点:逐行输入命令、逐行进行确认执行2. 脚本方式:就是说我们把手工执行的命令a,写到一个脚本文件b中,然后通过执行脚本b,达到执行命令a的效果.

2. shell 脚本定义

当可执行的Linux命令或语句不在命令行状态下执行,而是通过一个文件执行时,称文件为shell脚本。

3. shell 脚本示例

# 1. 手工方法
root@instance-nl5v4j4n:/home/kungs# echo 'kungs'
kungs# 2. 脚本方法
root@instance-nl5v4j4n:/home/kungs# cat kungs.sh
#!/bin/bash
# 这是一个临时测试脚本
echo 'kungs'
echo 'kungs love you'

第2章 SHELL基础知识

2.1 shell脚本

2.1.1 创建脚本

创建工具:vi/vim
脚本命名:shell脚本的命名要有意义,方便我们通过脚本名,来知道此文件用途
脚本内容:各种可执行的命令
注释内容:1.单行注释:除了首行的'#'不是注释外,其他行内容的首个字符是'#',2.多行注释:多行注释有两种方法:':<<! ... !' 和 ':<<字符 ... 字符'

实例:

root@instance-nl5v4j4n:/home/kungs# cat zhushi.sh
#!/bin/bash
# 单行注释echo '下一行是多行注释'
:<<!
echo '1'
echo '2'
echo '3'
!
echo '4'
root@instance-nl5v4j4n:/home/kungs# bash zhushi.sh
下一行是多行注释
4

2.1.2 脚本执行

shell 执行方式

bash/path/to/script-name 或  /bin/bash /path/to/script-name    (强烈推荐使用)
/path/to/script-name  或  ./script-name    (当前路径下执行脚本)
source script-name  或  . script-name    (注意“.“点号)

执行说明:

1、脚本文件本身没有可执行权限或者脚本首行没有命令解释器时使用的方法,我们推荐用bash执行。使用频率:☆☆☆☆☆
2、脚本文件具有可执行权限时使用。使用频率:☆☆☆☆
3、使用source或者.点号,加载shell脚本文件内容,使shell脚本内容环境和当前用户环境一致。使用频率:☆☆☆使用场景:环境一致性

2.1.3 脚本开发规范

1、脚本命名要有意义,文件后缀是.sh
2、脚本文件首行是而且必须是脚本解释器#!/bin/bash
3、脚本文件解释器后面要有脚本的基本信息等内容- 脚本文件中尽量不用中文注释;尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰- 常见的注释信息:脚本名称、脚本功能描述、脚本版本、脚本作者、联系方式等
4、脚本文件常见执行方式:bash 脚本名
5、脚本内容执行:从上到下,依次执行
6、代码书写优秀习惯;1)成对内容的一次性写出来,防止遗漏。如:()、{}、[]、''、``、""2)[]中括号两端要有空格,书写时即可留出空格[    ],然后再退格书写内容。3)流程控制语句一次性书写完,再添加内容
7、通过缩进让代码易读;(即该有空格的地方就要有空格)

2.2 变量

2.2.1 什么是变量

变量名  : 不变的
变量值 : 变化的

2.2.2 本地变量

本地变量是什么?

本地变量:在当前系统的某个环境下才能生效的变量,作用范围小。

本地变量包含两种:普通变量命令变量

1. 普通变量:

普通变量的定义方式有如下三种:

方式一:变量名=变量值重点:变量值必须是一个整体,中间没有特殊字符
方式二:变量名='变量值'重点:我看到的内容,我就输出什么内容
方式三:变量名="变量值"重点:如果变量值范围内,有可以解析的变量A,那么首先解析变量A,将A的结果和其他内容组合成一个整体,重新赋值给变量B
习惯:
数字不加引号,其他默认加双引号

例:

root@instance-nl5v4j4n:/home/kungs# kungs=nihao222
root@instance-nl5v4j4n:/home/kungs# echo $kungs
nihao222
root@instance-nl5v4j4n:/home/kungs# kungs='nihao333'
root@instance-nl5v4j4n:/home/kungs# echo $kungs
nihao333
root@instance-nl5v4j4n:/home/kungs# kungs="hello555"
root@instance-nl5v4j4n:/home/kungs# echo $kungs
hello555

2. 命令变量( 熟练)

命令变量有两种定义方式

方式一:变量名=`命令`echo $变量名注意:` 是反引号方式二(常用的方法):变量名=$(命令)echo $变量名

实例:

root@instance-nl5v4j4n:/home/kungs# dir=`pwd`
root@instance-nl5v4j4n:/home/kungs# echo $dir
/home/kungs
root@instance-nl5v4j4n:/home/kungs# pwd
/home/kungs
root@instance-nl5v4j4n:/home/kungs# echo $(pwd)
/home/kungs

2.2.3 全局变量

在当前系统的所有环境下都能生效的变量。

查看全局环境变量命令

env  只显示全局变量

定义全局变量

方法一:变量=值export 变量
方法二(常用):export 变量=值

2.2.4 变量查看和取消

1. 查看变量:

方法 实例
$变量名 echo $kungs
“$变量名” echo “$kungs”
${变量名} echo ${kungs}
“${变量名}” echo “${kungs}”

2. 取消变量

unset 变量名
例:
unset kungs

2.2.5 shell内置变量

1. 和脚本文件有关

符号 意义
$0 获取当前执行的shell脚本文件名,包括脚本路径
$n 获取当前执行的shell脚本的第n个参数值,n=1,…,9,当n为0时表示脚本的文件名,如果n大于9就要用大括号括起来${10}
$# 获取当前shell命令行中参数的数量
$? 获取执行上一个指令的返回值(0为成功,非0为失败)

实例:

NgandeMacBook-Pro:kungs_shells kungs$ cat get_name1.sh
#!/bin/bash
# $0 获取当前脚本的名称
echo "脚本名称是;get_name.sh"
echo "当前获取脚本的名称是;$0"
NgandeMacBook-Pro:kungs_shells kungs$ bash get_name1.sh
脚本名称是;get_name.sh
当前获取脚本的名称是;get_name1.shNgandeMacBook-Pro:kungs_shells kungs$ cat get_args.sh
#!/bin/bash
# $n  获取第n个位置的参数
echo "第一个位置参数是:$1"
NgandeMacBook-Pro:kungs_shells kungs$ bash get_args.sh
第一个位置参数是:
NgandeMacBook-Pro:kungs_shells kungs$ bash get_args.sh a
第一个位置参数是:a
NgandeMacBook-Pro:kungs_shells kungs$ cat get_args1.sh
#!/bin/bash
# $n  获取第n个位置的参数
echo "第一个位置参数是:$1"
echo "第二个位置参数是:$2"
echo "第三个位置参数是:$3"
echo "第四个位置参数是:$4"
NgandeMacBook-Pro:kungs_shells kungs$ bash get_args1.sh a b c d
第一个位置参数是:a
第二个位置参数是:b
第三个位置参数是:c
第四个位置参数是:d

获取文件执行或者命令执行的返回状态值:

NgandeMacBook-Pro:kungs_shells kungs$ bash hello
bash: hello: No such file or directory
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
127
NgandeMacBook-Pro:kungs_shells kungs$ ls
ceshi-11.sh ceshi.sh    get_num.sh  moren2.sh   zhengque
ceshi-all   cuowu       grep.txt    nihao.txt   zhushi.sh
ceshi-err   get_args.sh kungs.sh    sed.txt     zhushi.sh-1
ceshi-ok    get_name1.sh    moren1.sh   tree1
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0

2. 字符串精确截取

格式:${变量名:起始位置:截取长度}

实例:

NgandeMacBook-Pro:~ kungs$ file=sdfjoermrelcdgid
NgandeMacBook-Pro:~ kungs$ echo $file
sdfjoermrelcdgid
NgandeMacBook-Pro:~ kungs$ echo ${file:0:5}
sdfjo
NgandeMacBook-Pro:~ kungs$ echo ${file::5}
sdfjo
NgandeMacBook-Pro:~ kungs$ echo ${file:5:5}
ermre
NgandeMacBook-Pro:~ kungs$ echo ${file:0-5}
cdgid
NgandeMacBook-Pro:~ kungs$ echo ${file:0-5:3}
cdg

3. 默认值相关

场景一:

1. 变量a如果有内容,那么就输出a的变量值
2. 变量a如果没有内容,那么就输出默认的内容

格式:${变量名:-默认值}

实例:

如果我输入的参数为空,那么输出内容是 "您选择的套餐是: 套餐1"
如果我输入的参数为n,那么输出内容是 "您选择的套餐是: 套餐 n"
NgandeMacBook-Pro:kungs_shells kungs$ vim moren1.sh
NgandeMacBook-Pro:kungs_shells kungs$ cat moren1.sh
#!/bin/bash
# 默认值场景1 有条件的默认值# 定义一个本地变了,接受脚本传参
a="$1"
echo " 您选择的套餐是:${a:-1} 套餐"
NgandeMacBook-Pro:kungs_shells kungs$ bash moren1.sh 您选择的套餐是:1 套餐
NgandeMacBook-Pro:kungs_shells kungs$ bash moren1.sh 3您选择的套餐是:3 套餐

场景二:

无论变量a是否有内容,都输出默认值

格式:${变量名+默认值}

实例:

不管我说那个输出内容是 多少,都输出 那个输出内容是 22 岁
NgandeMacBook-Pro:kungs_shells kungs$ vim moren2.sh
NgandeMacBook-Pro:kungs_shells kungs$ cat moren2.sh
#!/bin/bash
# 默认值场景2,默认值强制生效# 定义一个本地变了,接受脚本传入的参数
a="$1"echo "输出内容是:${a+22} 岁"
NgandeMacBook-Pro:kungs_shells kungs$ bash moren2.sh
输出内容是:22 岁
NgandeMacBook-Pro:kungs_shells kungs$ bash moren2.sh 3
输出内容是:22 岁

第3章 SHELL进阶

内容

1. 测试语句
2. 表达式(条件+计算)
3. linux常见富豪和命令

3.1 表达式

要使Shell脚本程序具备一定的“逻辑能力”,面临的第一个问题就是:区分不同的情况以确定执行何种操作。

学习解决这个问题方法:测试语句

3.1.1 测试语句

Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0,表示成功,值为其他时,表示失败。使用专门的测试工具—test命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值0为成立)

测试语句形式

A: test 条件表达式,注意后面的等式要有空格

NgandeMacBook-Pro:kungs_shells kungs$ test 1 = 1
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ test 1 = 3
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
1

B: [ 条件表达式 ]

格式注意:以上两种方法的作用完全一样,后者为常用。

但后者需要注意方括号[、]与条件表达式之间至少有一个空格。

test[] 的意思一样:

  • 条件成立,状态返回值是0

  • 条件不成立,状态返回值是1

NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 1 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 2 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
1

操作注意:

[]两侧为什么要有空格

NgandeMacBook-Pro:kungs_shells kungs$ [-x /bin/bash ]
-bash: [-x: command not found
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 2]
-bash: [: missing `]'

可以看到:

两侧没有空格,就会报错,为什么呢?因为你不合规范

3.1.2 条件表达式

测试的结果使用 echo $? 来查看

1. 逻辑表达式:逻辑表达式一般用于判断多个条件之间的依赖关系。

常见的逻辑表达式有: &&||

1). &&

命令1 && 命令2

1. 如果命令1执行成功,那么我才执行命令2     --夫唱妇随
2. 如果命令1执行失败,那么命令2也不执行:

实例:

NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 1 ] && echo "条件成立"
条件成立
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 2 ] && echo "条件成立"
NgandeMacBook-Pro:kungs_shells kungs$

2). ||

命令1 || 命令2

1. 如果命令1执行成功,那么命令2不执行           -- 对着干
2. 如果命令1执行失败,那么命令2执行

​ 实例:

NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 2 ] || echo "条件不成立"
条件不成立
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 = 1 ] || echo "条件不成立"
NgandeMacBook-Pro:kungs_shells kungs$

2. 文件表达式

1). -f 判断输入内容是否是一个文件

NgandeMacBook-Pro:kungs_shells kungs$ ls
get_args.sh get_num.sh  moren1.sh   zhushi.sh
get_name1.sh    kungs.sh    moren2.sh   zhushi.sh-1
NgandeMacBook-Pro:kungs_shells kungs$ [ -f moren1.sh ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ [ -f moren1.sh ] && echo "它是一个普通文件"
它是一个普通文件
NgandeMacBook-Pro:kungs_shells kungs$ [ -f moren1.shsad ] && echo "它是一个普通文件"
NgandeMacBook-Pro:kungs_shells kungs$

2). -d 判断输入内容是否是一个目录

NgandeMacBook-Pro:kungs_shells kungs$ ls
get_args.sh get_num.sh  moren1.sh   tree1       zhushi.sh-1
get_name1.sh    kungs.sh    moren2.sh   zhushi.sh
NgandeMacBook-Pro:kungs_shells kungs$ [ -d tree1 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ [ -d tree1 ] && echo "是一个目录"
是一个目录
NgandeMacBook-Pro:kungs_shells kungs$ [ -d tree1 ] || echo "不是一个目录"
NgandeMacBook-Pro:kungs_shells kungs$ [ -d tree11 ] || echo "不是一个目录"
不是一个目录

3). -x 判断输入内容是否可执行

NgandeMacBook-Pro:kungs_shells kungs$ ls -al
total 64
-rw-r--r--   1 kungs  staff   156 10 29 11:13 moren1.sh
NgandeMacBook-Pro:kungs_shells kungs$ [ -x moren1.sh ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
1
NgandeMacBook-Pro:kungs_shells kungs$ [ -x moren1.sh ] || chmod +x moren1.sh
NgandeMacBook-Pro:kungs_shells kungs$ ls -alh
total 64
-rwxr-xr-x   1 kungs  staff   156B 10 29 11:13 moren1.sh
NgandeMacBook-Pro:kungs_shells kungs$ [ -x moren1.sh ] && ./moren1.sh 您选择的套餐是:1 套餐

3. 数值操作符(-eq-gt-ltne)

主要根据给定的两个值,判断第一个与第二个数的关系,如是否大于、小于、等于第二个数。常见选项如下:

n1 -eq n2    相等
n1 -gt n2    大于
n1 -lt n2    小于
n1 -ne n2    不等于

实例:

NgandeMacBook-Pro:kungs_shells kungs$ [ 1 -eq 1 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 -gt 1 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
1
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 -lt 2 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ [ 1 -ne 2 ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0

4. 字符串比较

str1 == str2          str1和str2字符串内容一致
str1 != str2          str1和str2字符串内容不一致,!表示相反的意思

实例:

判断字符是否内容一致

NgandeMacBook-Pro:kungs_shells kungs$ [ a == a ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0
NgandeMacBook-Pro:kungs_shells kungs$ [ a == ab ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
1
NgandeMacBook-Pro:kungs_shells kungs$ a=hello
NgandeMacBook-Pro:kungs_shells kungs$ b=nobody
NgandeMacBook-Pro:kungs_shells kungs$ echo $a
hello
NgandeMacBook-Pro:kungs_shells kungs$ echo $b
nobody
NgandeMacBook-Pro:kungs_shells kungs$ [ "${a}" == "${b}" ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
1
NgandeMacBook-Pro:kungs_shells kungs$ [ "${a}" != "${b}" ]
NgandeMacBook-Pro:kungs_shells kungs$ echo $?
0

3.1.3 计算表达式($(( 计算表达式 ))let)

计算表达式,简单来说就是对具体的内容进行算数计算

格式:

方式一:$(( 计算表达式 ))
方式二:let注意:$(())中只能用+-*/和()运算符,并且只能做整数运算

计算表达式

实例:

$((变量名a+1)) 注意:表达式范围内,空格不限制

NgandeMacBook-Pro:kungs_shells kungs$ echo $((1+1))
2
NgandeMacBook-Pro:kungs_shells kungs$ echo $((2+2))
4
NgandeMacBook-Pro:kungs_shells kungs$ echo $((2*3))
6

let 注意:表达式必须是一个整体,中间不能出现空格等特殊字符

NgandeMacBook-Pro:kungs_shells kungs$ let a=1+1
NgandeMacBook-Pro:kungs_shells kungs$ echo $a
2
NgandeMacBook-Pro:kungs_shells kungs$ let a=1+5
NgandeMacBook-Pro:kungs_shells kungs$ echo $a
6
NgandeMacBook-Pro:kungs_shells kungs$ let a=a+1
NgandeMacBook-Pro:kungs_shells kungs$ echo $a
7
NgandeMacBook-Pro:kungs_shells kungs$ a=$((a+7))
NgandeMacBook-Pro:kungs_shells kungs$ echo $a
14

3.2 Linux常见符号

重定向符号、管道符、其他符号

3.2.1 重定向符号( >>>)

shell脚本中有两种常见的重定向符号 >>>

1. >

作用:将符号左侧的内容,以**覆盖**的方式输入到右侧文件中

实例:

NgandeMacBook-Pro:kungs_shells kungs$ echo 'nihao'
nihao
NgandeMacBook-Pro:kungs_shells kungs$ echo 'nihao' > nihao.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat nihao.txt
nihao
NgandeMacBook-Pro:kungs_shells kungs$ echo 'nihaoma' > nihao.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat nihao.txt
nihaoma

2. >>

作用:将符号左侧的内容,以**追加**的方式输入到右侧文件的末尾行中

实例:

NgandeMacBook-Pro:kungs_shells kungs$ cat nihao.txt
nihaoma
NgandeMacBook-Pro:kungs_shells kungs$ echo 'hellonihao' >> nihao.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat nihao.txt
nihaoma
hellonihao
NgandeMacBook-Pro:kungs_shells kungs$ echo 'hellonihao1' >> nihao.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat nihao.txt
nihaoma
hellonihao
hellonihao1

3.2.2 管道符(|)

| 这个就是管道符,传递信息使用的

使用格式:命令1 | 命令2

管道符左侧命令1 执行后的结果,**传递**给管道符右侧的命令2使用

实例:

NgandeMacBook-Pro:kungs_shells kungs$ env |grep SHELL
SHELL=/bin/bash

3.2.3 其他符号(&)

1. 后台展示符号 &

定义:& 就是将一个命令从前台转到后台执行

使用格式:命令 &

NgandeMacBook-Pro:kungs_shells kungs$ sleep 10 &
[1] 2483
NgandeMacBook-Pro:kungs_shells kungs$
NgandeMacBook-Pro:kungs_shells kungs$
NgandeMacBook-Pro:kungs_shells kungs$
NgandeMacBook-Pro:kungs_shells kungs$
[1]+  Done                    sleep 10
NgandeMacBook-Pro:kungs_shells kungs$ sleep 10 &
[1] 2489
NgandeMacBook-Pro:kungs_shells kungs$ ps aux |grep sleep
kungs             2493   0.0  0.0  2432804    772 s000  S+    3:58下午   0:00.00 grep sleep
kungs             2489   0.0  0.0  2432788    636 s000  S     3:58下午   0:00.00 sleep 10

2. 全部信息符号 2>&1

符号详解:1 表示正确输出的信息  1>>2 表示错误输出的信息  2>>2>&1 代表所有输出的信息

符号实例

1).标准正确输出实例:

NgandeMacBook-Pro:kungs_shells kungs$ cat nihao.txt 1>> zhengque
NgandeMacBook-Pro:kungs_shells kungs$ cat zhengque
nihaoma
hellonihao
hellonihao1

2).标准错误输出实例:

NgandeMacBook-Pro:kungs_shells kungs$ lll
-bash: lll: command not found
NgandeMacBook-Pro:kungs_shells kungs$ dgsa
-bash: dgsa: command not found
NgandeMacBook-Pro:kungs_shells kungs$ dgsa 2>> cuowu
NgandeMacBook-Pro:kungs_shells kungs$ cat cuowu
-bash: dgsa: command not found

综合演示实例:

NgandeMacBook-Pro:kungs_shells kungs$ cat ceshi.sh
#!/bin/bash
echo "下一条错误命令"
sahdaosfdofgaovavav
NgandeMacBook-Pro:kungs_shells kungs$ bash ceshi.sh
下一条错误命令
ceshi.sh: line 3: sahdaosfdofgaovavav: command not found
NgandeMacBook-Pro:kungs_shells kungs$ bash ceshi.sh 1>> ceshi-ok 2>> ceshi-err
NgandeMacBook-Pro:kungs_shells kungs$ cat ceshi-ok
下一条错误命令
NgandeMacBook-Pro:kungs_shells kungs$ cat ceshi-err
ceshi.sh: line 3: sahdaosfdofgaovavav: command not found
NgandeMacBook-Pro:kungs_shells kungs$ bash ceshi.sh 1>> ceshi-11 2>> ceshi-11
NgandeMacBook-Pro:kungs_shells kungs$ cat ceshi-11
下一条错误命令
ceshi.sh: line 3: sahdaosfdofgaovavav: command not found
NgandeMacBook-Pro:kungs_shells kungs$ bash ceshi.sh >> ceshi-all 2>&1
NgandeMacBook-Pro:kungs_shells kungs$ cat ceshi-all
下一条错误命令
ceshi.sh: line 3: sahdaosfdofgaovavav: command not found

3. linux 系统垃圾桶

/dev/null 是linux下的一个设备文件,这个文件类似于一个垃圾桶,特点是:容量无限大,常常把其设置到此垃圾桶里,避免后期再去删除相关文件。

NgandeMacBook-Pro:kungs_shells kungs$ ls /dev/null
/dev/null
NgandeMacBook-Pro:kungs_shells kungs$ bash ceshi.sh >> /dev/null 2>&1

3.3 常见命令详解(grepsedawkfind)

shell脚本中经常使用的linux命令:grepsedawkfind

3.3.1 grep命令详解

grep命令是常用的一个强大的文本搜索命令。

格式:

grep [参数][关键字] <文件名>

注意:

我们在查看某个文件的内容的时候,是需要有<文件名>

grep命令在结合|(管道符)使用的情况下,后面的<文件名>是没有的

可以通过 grep --help 查看grep的帮助信息

参数详解

    -c:只输出匹配行的计数。-n:显示匹配行及行号。-v:显示不包含匹配文本的所有行。
NgandeMacBook-Pro:kungs_shells kungs$ cat grep.txt
hello aaa
hello aaa
hello AAA
hello bbb
hello ccc
NgandeMacBook-Pro:kungs_shells kungs$ grep -c aaa grep.txt
2
NgandeMacBook-Pro:kungs_shells kungs$ grep aaa grep.txt
hello aaa
hello aaa
NgandeMacBook-Pro:kungs_shells kungs$ grep -c hello grep.txt
5
NgandeMacBook-Pro:kungs_shells kungs$ grep -n aaa grep.txt
1:hello aaa
2:hello aaa
NgandeMacBook-Pro:kungs_shells kungs$ grep -n ccc grep.txt
5:hello ccc
NgandeMacBook-Pro:kungs_shells kungs$ grep -v aaa grep.txt
hello AAA
hello bbb
hello ccc
NgandeMacBook-Pro:kungs_shells kungs$ grep -nr aaa *
grep.txt:1:hello aaa
grep.txt:2:hello aaa

3.3.2 sed命令详解

sed 行文件编辑工具。因为它编辑文件是以行为单位的。

格式

sed [参数] '<匹配条件> [动作]'[文件名]
mac版:
sed [参数] '' '<匹配条件> [动作]'[文件名]

注意:可以通过 sed —help 查看grep的帮助信息

参数详解:

1. 参数为空 表示sed的操作效果,实际上不对文件进行编辑
2. -i   表示对文件进行编辑
3. 注意:mac版的bash中使用 -i参数,必须在后单独加个东西(''): -i ''

**匹配条件:**数字行号 或 关键字匹配

关键字匹配格式:'/关键字/'

注意:隔离符号 / 可以更换成 @#等符号

根据情况使用,如果关键字和隔离符号有冲突,就更换成其他的符号即可。

例:

root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '2s\SED\sed\2' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
hello SED sed SED
news_add
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '2s@SED@sed@2' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
hello SED sed sed
news_add
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '5s@SED@sed@2' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
hello SED sed sed
news_add
hello sed sed sed
hello SED sed SED

动作详解

-a      在匹配到的内容下一行增加内容
-i      在匹配到的内容上一行增加内容
-d      删除匹配到的内容
-s      替换匹配到的内容

注意:上面的动作应该在参数为-i的时候使用,不然的话不会有效果

1. 替换命令(行号、列号、全体)

格式:sed -i [替换格式][文件名]

sed -i '行号s#原内容#替换内容#原内容第几个(默认空:1,全部:g)' 文件名
例:
sed -i '3s#SED#sed#g' sed.txt # 第三行所有的SED改为sed

实例:

NgandeMacBook-Pro:kungs_shells kungs$ cat sed.txt
hello sed sed sed
hello sed sed sed
hello sed sed sed
hello sed sed sed# 文件第一行的第一个(默认) 'sed' 替换为 'SED'
NgandeMacBook-Pro:kungs_shells kungs$ sed -i '1s#sed#SED#' sed.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat sed.txt
hello SED sed sed
hello sed sed sed
hello sed sed sed
hello sed sed sed# 文件所有行的第二个'sed'替换为'SED'
NgandeMacBook-Pro:kungs_shells kungs$ sed -i 's#sed#SED#2' sed.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat sed.txt
hello SED sed SED
hello sed SED sed
hello sed SED sed
hello sed SED sed# 文件第三行的第二个'sed'替换为'SED'
NgandeMacBook-Pro:kungs_shells kungs$ sed -i '3s#sed#SED#2' sed.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat sed.txt
hello SED sed SED
hello sed SED sed
hello sed SED SED
hello sed SED sed# 文件所有行的所有'sed'替换为'SED'
NgandeMacBook-Pro:kungs_shells kungs$ sed -i 's#sed#SED#g' sed.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat sed.txt
hello SED SED SED
hello SED SED SED
hello SED SED SED
hello SED SED SED# 文件第三行所有的'SED'替换为'sed'
NgandeMacBook-Pro:kungs_shells kungs$ sed -i '3s#SED#sed#g' sed.txt
NgandeMacBook-Pro:kungs_shells kungs$ cat sed.txt
hello SED SED SED
hello SED SED SED
hello sed sed sed
hello SED SED SED

2. 增加操作

**目的1:**在指定行号的下一行增加内容;

**目的2:**在指定行号的上一行增加内容;

格式:

# 在某行号的下一行增加内容
sed -i '行号a\增加的内容' 文件名
# 增加多行,可以在行号位置写个范围值,彼此间用逗号隔开,例:在1~3每行的下一行都增加内容
sed -i '1,3a\增加内容' 文件名# 在指定行号的前一行增加内容
sed -i '行号i\增加的内容' 文件名
# 行号前增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例:在1~3每行的上一行都增加内容
sed -i '1,3i\增加内容' 文件名注意:在mac终端中有所区别,不然会报下面的错
NgandeMacBook-Pro:kungs_shells kungs$ sed -i '' '1a\add-1\' sed.txt
sed: 1: "1a\add-1\": extra characters after \ at the end of a command
NgandeMacBook-Pro:kungs_shells kungs$ sed -i '' "1,3a\tongshi-2" sed.txt
sed: 1: "1,3a\tongshi-2": command a expects up to 1 address(es), found 2正确做法:下面是mac中的正确方法
# 在某行号的下一行增加内容
NgandeMacBook-Pro:kungs_shells kungs$ sed -i '' "1a\\
> 增加的内容\\
> " 文件名
注意:这里增加多行目前没有办法去解决

实例:

root@instance-nl5v4j4n:/home/kungs# cat sed.txt
hello SED SED SED
hello SED SED SED
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '1a\add_news' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
hello SED SED SED
add_news
hello SED SED SED
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '1,3a\news_add' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
hello SED SED SED
news_add
add_news
news_add
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SEDroot@instance-nl5v4j4n:/home/kungs# sed -i '1i\insert_1' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
hello SED SED SED
news_add
add_news
news_add
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '1,3i\insert_news' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_news
insert_1
insert_news
hello SED SED SED
insert_news
news_add
add_news
news_add
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SED

3. 删除操作

格式:

# 指定行号删除
sed -i '行号d' 文件名
# 如果删除多行,可以在行号位置多写几个行号,彼此间使用逗号隔开,例:1-3行删除
sed -i '1,3d' 文件名

实例:

root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_news
insert_1
insert_news
hello SED SED SED
insert_news
news_add
add_news
news_add
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '1d' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
insert_news
hello SED SED SED
insert_news
news_add
add_news
news_add
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SED
root@instance-nl5v4j4n:/home/kungs# sed -i '2,7d' sed.txt
root@instance-nl5v4j4n:/home/kungs# cat sed.txt
insert_1
hello SED SED SED
news_add
hello sed sed sed
hello SED SED SED

3.3.3 awk命令详解

awk是一个功能非常强大的文档编辑工具,不仅能以行为单位还能以列为单位处理文件。

命令格式:

awk [参数] '[ 动作]' [文件名]

常见参数:-F 指定行的分隔符

常见动作:

print  显示内容$0  显示当前行所有内容$n  显示当前行的第n列内容,如果存在多个$n,它们之间使用逗号(,)隔开

常见内置变量

FILENAME   当前输入文件的文件名,该变量是只读的
NR         指定显示行的行号
NF         输出最后一列的内容
OFS        输出格式的列分隔符,缺省是空格
FS         输入文件的列分融符,缺省是连续的空格和Tab

实例:

root@instance-nl5v4j4n:/home/kungs# cat awk.txt
hello awk awk awk awk
hello awk awk awk awk
root@instance-nl5v4j4n:/home/kungs# awk '{print $0}' awk.txt
hello awk awk awk awk
hello awk awk awk awk
root@instance-nl5v4j4n:/home/kungs# awk '{print $1}' awk.txt
hello
hello
root@instance-nl5v4j4n:/home/kungs# awk '{print $1$3}' awk.txt
helloawk
helloawk
root@instance-nl5v4j4n:/home/kungs# awk '{print $1,$3}' awk.txt
hello awk
hello awk# 打印第1列第3列内容,显示行的行号
root@instance-nl5v4j4n:/home/kungs# awk '{print NR,$1,$3}' awk.txt
1 hello awk
2 hello awk
root@instance-nl5v4j4n:/home/kungs# awk 'NR==1 {print $1,$3}' awk.txt
hello awk
root@instance-nl5v4j4n:/home/kungs# sed -i 's# #:#g' awk.txt
root@instance-nl5v4j4n:/home/kungs# cat awk.txt
hello:awk:awk:awk:awk
hello:awk:awk:awk:awk
root@instance-nl5v4j4n:/home/kungs# awk '{print $1,$3}' awk.txt
hello:awk:awk:awk:awk
hello:awk:awk:awk:awk
root@instance-nl5v4j4n:/home/kungs# awk -F ':' '{print $1,$3}' awk.txt
hello awk
hello awk
root@instance-nl5v4j4n:/home/kungs# awk -F ':' 'BEGIN{OFS="@"} {print $1,$3}' awk.txt
hello@awk
hello@awk

3.3.4 find命令

格式:

find [路径][参数] [关键字]

参数

-name  按照文件名查找文件。
-perm  按照文件权限来查找文件
-user  按照文件属主来查找文件。
-group 按照文件所属的组来查找文件。
-type  查找某一类型的文件,诸如:b - 块设备文件d - 目录c -字符设备文件p - 管道文件l - 符号链接文件f- 普通文件。
-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。
-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。-mindepth n:在查找文件时,查找当前目录中的第n层目录的文件,然后再在其子目录中查找。
! : 表示取反

例:

NgandeMacBook-Pro:kungs_shells kungs$ ls
ceshi-11    ceshi.sh    get_num.sh  moren2.sh   zhengque
ceshi-all   cuowu       grep.txt    nihao.txt   zhushi.sh
ceshi-err   get_args.sh kungs.sh    sed.txt     zhushi.sh-1
ceshi-ok    get_name1.sh    moren1.sh   tree1
NgandeMacBook-Pro:kungs_shells kungs$ find ./ -type d
./
.//tree1
.//tree1/tree2
.//tree1/tree2/tree3
NgandeMacBook-Pro:kungs_shells kungs$ find ./ -type d -name "tree*"
.//tree1
.//tree1/tree2
.//tree1/tree2/tree3
NgandeMacBook-Pro:kungs_shells kungs$ find ./ -type f -name "moren*"
.//moren1.sh
.//moren2.sh

第4章 流程控制

在shell的语句中,流程控制主要分为两种:

1. 简单流程控制语句:选择和循环
2. 复杂流程控制语句:函数

4.1 简单流程控制语句

4.1.1 单分支if语句

语法格式:单一条件,只有一个输出

if [ 条件 ]
then指令
fi

实例:

root@instance-nl5v4j4n:/home/kungs# cat danif.sh
#!/bin/bash
# 单if语句的使用场景# 定义一个本地变量,用于接受脚本执行时候的参数
a="$1"if [ "${a}" == "nan" ]
thenecho "男"
fi
root@instance-nl5v4j4n:/home/kungs# bash danif.sh nan
男
root@instance-nl5v4j4n:/home/kungs# bash danif.sh nand
root@instance-nl5v4j4n:/home/kungs#

4.1.2 双分支if语句

语法格式: 一个条件,两种结果

if [ 条件 ]
then指令1
else指令2
fi

实例:

root@instance-nl5v4j4n:/home/kungs# cat shuangif.sh
#!/bin/bash
# 双if语句的使用场景# 定义一个本地变量,用于接受脚本执行时候的参数
a="$1"if [ "${a}" == "nan" ]
thenecho "男"
elseecho "女"
fi
root@instance-nl5v4j4n:/home/kungs# bash shuangif.sh nan
男
root@instance-nl5v4j4n:/home/kungs# bash shuangif.sh nand
女

4.1.3 多分支if语句

语法格式:n个条件,n+1个结果

if [ 条件 ]
then指令1
elif[ 条件2 ]
then指令2
else指令3
fi

实例:

root@instance-nl5v4j4n:/home/kungs# cat duoif.sh
#!/bin/bash
# 多if语句的使用场景# 定义一个本地变量,用于接受脚本执行时候的参数
a="$1"if [ "${a}" == "nan" ]
thenecho "男"
elif [ "${a}" == "nv" ]
thenecho "女"
elseecho "未知"
fi
root@instance-nl5v4j4n:/home/kungs# bash duoif.sh nan
男
root@instance-nl5v4j4n:/home/kungs# bash duoif.sh nv
女
root@instance-nl5v4j4n:/home/kungs# bash duoif.sh nvd
未知

-------------------

多if语句生产场景:服务的启动

​ 要求脚本执行需要有参数,通过传入参数来实现不同的功能。

参数和功能:

参数 执行效果
start 服务启动中…
stop 服务关闭中…
restart 服务重启中…
* 脚本 X.sh 使用方式 X.sh [ start|stop|restart ]

实例:

root@instance-nl5v4j4n:/home/kungs# cat duoif_serv.sh
#!/bin/bash
# 多if语句生产案例,服务脚本# 定义一个本地变量,接受传入的参数
a="$1"if [ "${a}" == "start" ]
thenecho "服务启动中..."
elif [ "${a}" == "stop" ]
thenecho "服务关闭中..."
elif [ "${a}" == "restart" ]
thenecho "服务重启中..."
elseecho "脚本$0 的使用方式:$0 [ start|stop|restart ]"
fi
root@instance-nl5v4j4n:/home/kungs# bash duoif_serv.sh
脚本duoif_serv.sh 的使用方式:duoif_serv.sh [ start|stop|restart ]
root@instance-nl5v4j4n:/home/kungs# bash duoif_serv.sh start
服务启动中...
root@instance-nl5v4j4n:/home/kungs# bash duoif_serv.sh stop
服务关闭中...
root@instance-nl5v4j4n:/home/kungs# bash duoif_serv.sh restart
服务重启中...

4.1.4 case选择语句

多if语句使用的时候,代码量很多,而且整体看起来确实有那么一丁点乱。Case语句:简明。

case 语句格式

case 变量名 in值1)指令1;;值2)指令2;;值3)指令3;;
esac

实例:

root@instance-nl5v4j4n:/home/kungs# cat case.sh
#!/bin/bash
# case语法演示# 定义一个本地变量,接受脚本传入的参数
a="$1"case "${a}" in start)echo "服务启动中...";;stop)echo "服务关闭中...";;restart)echo "服务重启中...";;*)echo "脚本 $0 的使用方式:$0 [ start|stop|restart ]";;
esac
root@instance-nl5v4j4n:/home/kungs# bash case.sh
脚本 case.sh 的使用方式:case.sh [ start|stop|restart ]
root@instance-nl5v4j4n:/home/kungs# bash case.sh start
服务启动中...
root@instance-nl5v4j4n:/home/kungs# bash case.sh stop
服务关闭中...
root@instance-nl5v4j4n:/home/kungs# bash case.sh restart
服务重启中...

---------------

4.1.5 for循环语句

遍历列表,循环指定的所有元素,循环完毕之后就推出

语法格式

for 值 in 列表
do执行语句
done

注意:

1. ”for”循环总是接收 “in” 语句之后的某种类型的字列表
2. 执行次数和list列表中常数或字符串的个数相同,当循环的数量足够了,就自动退出

实例:

root@instance-nl5v4j4n:/home/kungs# cat for.sh
#!/bin/bash
# for 语句演示for i in $(ls /home/kungs)
doecho "/home/kungs 目录下的文件:${i}"
done
root@instance-nl5v4j4n:/home/kungs# ls
awk.txt        elasticsearch-2.4.6        __MACOSX          shuangif.sh
case.sh        elasticsearch-2.4.6.zip    meiduo_01         test01
danif.sh       fdfs_client-py-master.zip  mysql_slave       zhushi.sh
data.tar.gz    for.sh                     pi.py
duoif_serv.sh  goods_data.sql             requirements.txt
duoif.sh       kungs.sh                   sed.txt
root@instance-nl5v4j4n:/home/kungs# bash for.sh
/home/kungs 目录下的文件:awk.txt
/home/kungs 目录下的文件:case.sh
/home/kungs 目录下的文件:danif.sh
/home/kungs 目录下的文件:duoif_serv.sh
/home/kungs 目录下的文件:duoif.sh
/home/kungs 目录下的文件:for.sh
/home/kungs 目录下的文件:kungs.sh
/home/kungs 目录下的文件:sed.txt
/home/kungs 目录下的文件:shuangif.sh
/home/kungs 目录下的文件:zhushi.sh

4.1.6 while循环语句

语法格式:只要条件满足,就一直循环下去

while 条件
do执行语句
done其中条件的类型:
命令、[[ 字符串表达式 ]]、(( 数字表达式 ))

实例:

root@instance-nl5v4j4n:/home/kungs# cat while.sh
#!/bin/bash
# while 语法演示# 定义一个本地变量
a=1while [ "${a}" -lt 5 ]
doecho "${a}"a=$((a+1))
done
root@instance-nl5v4j4n:/home/kungs# bash while.sh
1
2
3
4

4.1.7 until循环语句

语法格式:只要条件不满足,就一直循环下去

until 条件
do执行语句
done条件的类型:
命令、[[ 字符串表达式 ]]、(( 数字表达式 ))

实例:

root@instance-nl5v4j4n:/home/kungs# cat until.sh
#!/bin/bash
# until 语句演示# 定义一个本地变量
a=1# until主框架
until [ "${a}" -eq 3 ]
doecho "${a}"a=$((a+1))
done
root@instance-nl5v4j4n:/home/kungs# bash until.sh
1
2

4.2 复杂流程控制语句

​ 函数就是我们的复杂流程控制语句

4.2.1 函数基础知识

函数是什么?

函数就是将某些命令组合起来实现某一特殊功能的方式,是脚本编写中非常重要的一部分。

1. 简单函数格式:

定义函数:

函数名(){函数体
}

​ 调用函数:

函数名

实例:

root@instance-nl5v4j4n:/home/kungs# cat func.sh
#!/bin/bash
# 简单函数定义# 定义函数
function1(){echo "welcome to China"
}
# 调用函数
function1
root@instance-nl5v4j4n:/home/kungs# bash func.sh
welcome to China

2. 传参函数格式:

传参数

函数名 参数

函数体调用参数:

函数名(){函数体 $n
}

​ 注意:类似于shell内置变量中的位置参数

实例:

root@instance-nl5v4j4n:/home/kungs# cat func_canshu.sh
#!/bin/bash
# 传参函数定义# 定义函数
function1(){echo "welcome to China $1"
}
# 调用函数
function1 kungs
function1 kungs1
root@instance-nl5v4j4n:/home/kungs# bash func_canshu.sh
welcome to China kungs
welcome to China kungs1

4.2.2 函数实践

简单函数定义和调用示例

root@instance-nl5v4j4n:/home/kungs# cat func_canshu.sh
#!/bin/bash
# 传参函数定义和调用# 定义函数
function1(){echo "welcome to China $1"
}
# 调用函数
# function1 kungs
function1 "$1"
root@instance-nl5v4j4n:/home/kungs# bash func_canshu.sh kung00
welcome to China kung00

函数传参和函数体内调用参数示例

root@instance-nl5v4j4n:/home/kungs# cat func_canshu.sh
#!/bin/bash
# 传参函数定义和调用# 定义函数
function1(){echo "welcome to China $1"
}
# 调用函数
function1 kungs
root@instance-nl5v4j4n:/home/kungs# bash func_canshu.sh
welcome to China kung

函数调用脚本传参

root@instance-nl5v4j4n:/home/kungs# cat func_canshu.sh
#!/bin/bash
# 传参函数定义和调用# 定义函数
function1(){echo "welcome to China $1"
}
# 调用函数
function1 "$1"
root@instance-nl5v4j4n:/home/kungs# bash func_canshu.sh kung00
welcome to China kung00

脚本传多参,函数分别调用示例

root@instance-nl5v4j4n:/home/kungs# cat func_jiaoben.sh
#!/bin/bash
# 传参函数定义和调用# 定义函数
function1(){echo "welcome to China $1"
}
# 调用函数
function1 "$1"
function1 "$2"
root@instance-nl5v4j4n:/home/kungs# bash func_jiaoben.sh kungs8 kungs9
welcome to China kungs8
welcome to China kungs9

---------------

4.3 第一阶段综合案例

需求

1、zonghe.sh 脚本执行时候需要添加参数才能执行

参数和功能详情如下:

参数 执行效果
start 服务启动中…
stop 服务关闭中…
restart 服务重启中…
* 脚本帮助信息…

2、参数的数量有限制,只能是1个,多余一个会提示脚本的帮助信息

3、帮助信息使用函数来实现

信息内容:脚本 zonghe.sh 使用方式 zonghe.sh [ start|stop|restart ]

知识点分析:

1、zonghe.sh 脚本执行时候需要添加参数才能执行脚本传参、case语句
2、参数的数量有限制,只能是1个,多余一个会提示脚本的帮助信息参数数量、条件表达式(验证+数字)、if语句
3、帮助信息使用函数来实现函数定义+调用
4、if语句和case语句嵌套if语句在外,case语句在内

脚本编写流程

1、先写主流程框架
2、完善函数功能
3、完善需求功能

实例:

root@instance-nl5v4j4n:/home/kungs# cat zonghe.sh
#!/bin/bash
# 脚本主框架# 动议本地变量,接受脚本传参
a="$1"# 编写脚本帮助信息
usage(){echo "脚本 $0 使用方式 $0 [ start|stop|restart ]"
}# 脚本主框架
if [ "$#" -eq 1 ]
thencase "${a}" instart)echo "服务启动中...";;stop)echo "服务关闭中...";;restart)echo "服务重启中...";;*)usage;;esac
elseusage
fi
root@instance-nl5v4j4n:/home/kungs# bash zonghe.sh
脚本 zonghe.sh 使用方式 zonghe.sh [ start|stop|restart ]
root@instance-nl5v4j4n:/home/kungs# bash zonghe.sh start
服务启动中...
root@instance-nl5v4j4n:/home/kungs# bash zonghe.sh stop
服务关闭中...
root@instance-nl5v4j4n:/home/kungs# bash zonghe.sh restart
服务重启中...
root@instance-nl5v4j4n:/home/kungs# bash zonghe.sh red
脚本 zonghe.sh 使用方式 zonghe.sh [ start|stop|restart ]

第5章 代码发布

5.1 代码发布

发布什么?

​ 代码:经过测试,功能完善,没有问题的代码

发布到哪里?

​ 服务器:所有人都能访问的到的一台服务器(有公网IP)

​ idc机房、阿里云、亚马逊、腾讯云、华为云、…

发布的效果?

​ web网页:对外展示

发布方式

1. 手工发布代码:慢干扰因素多不安全
2. 脚本发布代码:快干扰因素少安全

5.2 代码发布流程

获取代码 —> 打包代码 —> 传输代码 —> 停止应用 —> 解压代码 —> 放置代码 —> 开启代码 —> 开启应用 —> 检查效果 —> 对外访问

0. 部署场景:

两台主机做部署动作

注意:部署的文件就是两台主机右上角的红色内容

1. 获取代码

​ 代码仓库

1. 集中式的:  svn
2. 分布式的:  git区别:
svn的几乎所有操作命令,都集中在我和代码仓库服务器处于网络连接状态。
git的几乎所有操作命令,可以在本地完成,和代码仓库服务器是否连接无关。

公司的代码仓库:

私有仓库: gitlab
内部服务器或者公网服务器

仓库权限

只有项目的开发人员才有权限,项目之外的人没有权限

代码权限:

开发、管理、查看

提交的方式:

代码版本号

2. 打包代码

目的:

1. 减少传输文件数量
2. 减小传输文件大小
3. 增强传输速率

常见打包方式:

1. windows:  zip、rar...
2. linux:    tar、zip...

3. 传输代码

​ 传输方式:

1. 有网情况下:多种方式:git、ftp、**scp**、共享挂载 cp、rsync2. 没有网情况下:物理方式: U盘或者硬盘

4. 停止应用

代码所在的服务用到了什么应用,就关闭什么应用

关闭的顺序:先关闭离客户近的,后关闭离客户远的

5. 解压代码

tar xf

6. 放置代码

避免我们在放置代码过程中,对老文件造成影响

放置代码分为两步:1. 备份老文件  2. 放置新文件。
注意:两个文件的名称是一样的,只是内容不同对整个应用项目来说,两个文件没有区别

1) 备份原文件

2) 放置新文件

7. 开启应用

刚才关闭了什么应用就开启什么应用

开启的顺序:先开启离客户远的,后开启离客户近的

8. 检查效果

查看浏览器效果或者netstat -tnulp查看系统开放的端口

5.3 技术关键点

1. 文件的压缩和解压

文件的压缩

压缩格式:
tar zcvf 压缩后的文件名  将要压缩的文件

文件的解压

解压格式:
tar xf 压缩后的文件名

命令参数详解

z   指定压缩文件的格式为 tar.gz
c   表示压缩
v   显示详细过程
f   指定压缩文件
x   解压

查看压缩文件内容

zcat 压缩文件

2. 文件的传输

​ scp传输工具:

命令格式:scp  要传输的文件       要放置的位置
将本地文件推送到远程主机scp python.tar.gz root@182.61.28.143:/root/
将远程主机的文件拉取到本地scp root@182.61.28.143:/root/python.tar.gz ./
远端主机文件放置位置的表示形式:远程连接的用户@远程主机:远程主机的目录路径
远端主机文件位置的表示形式:远程连接的用户@远程主机:远程主机的文件路径

3. 文件的备份

文件的备份要有一定的标志符号,使用目前通用的时间戳形式来表示

命令格式:date [option]
常见参数:%F  显示当前日期格式,%Y-%m-%d%T  显示当前时间格式,%H:%M:%S

演示效果:

# 显示当前日期
root@instance-nl5v4j4n:/home/kungs# date +%F
2018-10-31# 显示当前时间
root@instance-nl5v4j4n:/home/kungs# date +%T
20:42:54

根据上面的参数介绍,我们可以指定命令显示的格式,

年月日:date +%Y%m%d
时分秒:date +%H%M%S

实例:

显示当前日期
root@instance-nl5v4j4n:/home/kungs# date +%Y%m%d
20181031显示当前时间
root@instance-nl5v4j4n:/home/kungs# date +%H%M%S
204546

指定时间戳格式:

年月日时分秒:date +%Y%m%d%H%M%S

实例:

指定的时间戳格式
root@instance-nl5v4j4n:/home/kungs# date +%Y%m%d%H%M%S
20181031204724

备份命令效果格式:

方式一:复制备份cp hello hello-$(date +%Y%m%d%H%M%S)
方式二:移动备份mv hello hello-$(date +%Y%m%d%H%M%S)

注意:我们为了避免在放置新文件时候,出现验证操作,我们确定采用方式二

---------------

实例操作:

1、在主机1上创建一个目录/data/tar-ceshi/,在目录里面创建两个文件,内容分别如下:

文件名          内容
file1.txt      file1
file2.txt      file2

2、对目录tar-ceshi进行压缩

3、对目录tar-ceshi进行时间戳备份

4、将压缩包文件传输到远端主机2

5、在主机2上解压 压缩包文件

6、在主机2上修改压缩包文件内容。然后再次压缩

7、在主机1上拉取主机2的压缩包文件

8、使用命令查看压缩包文件的内容

# 答案
1.在主机1上创建一个目录/data/tar-ceshi/,在目录里面创建两个文件及内容mkdir /data/tar-ceshi -pcd /dataecho 'file1' > tar-ceshi/file1.txtecho 'file2' > tar-ceshi/file2.txt
2. 对目录tar-ceshi进行压缩tar zcvftar-ceshi.tar.gz tar-ceshi
3. 对目录tar-ceshi进行时间戳备份mv tar-ceshitar-ceshi-$(date +%Y%m%d%H%M%S)
4. 将压缩包文件传输到远端主机2scptar-ceshi.tar.gz root@192.168.8.15:/tmp
5. 在主机2上解压 压缩包文件cd /tmptar xf tar-ceshi.tar.gz
6. 在主机2上修改压缩包文件内容。然后再次压缩echo 'file3' >> tar-ceshi/file1.txttar zcvf tar-ceshi-1.tar.gz tar-ceshi
7. 在主机1上拉取主机2的压缩包文件scproot@182.61.28.143:/tmp/tar-ceshi-1.tar.gz ./
8. 使用命令查看压缩包文件的内容zcat tar-ceshi-1.tar.gz

第六章 环境部署

需要有一个项目的基础环境,然后在这个基础环境上,再根据项目需求搭建一个能让项目代码正常运行的环境。

6.1 基础环境

6.1.1 基础目录环境

创建基本目录

root@instance-nl5v4j4n:/data# mkdir /data/{server,logs,backup,softs,virtual,scripts,codes}
root@instance-nl5v4j4n:/data# ls /data/
backup  codes  logs  scripts  server  soft  virtual

查看

root@instance-nl5v4j4n:/data# tree -L 1 /data/
/data/
├── backup
├── codes
├── logs
├── scripts
├── server
├── softs
└── virtual7 directories, 0 files

6.1.2 主机网络环境

问题:

我们上面进行文件传输的时候,发现一个问题,每次进行文件传输都需要进行密码验证,解决办法:

主机间免密码认证

主机间免密码认证步骤:

1. 本机生成密钥对
2. 对端机器使用公钥文件认证
3. 验证

代码操作:

1. 生成秘钥对

ssh-keygen -t rsa
其中:   -t   指定秘钥的类型  rsa  秘钥类型
秘钥目录:/root/.ssh/私钥     id_rsa      钥匙公钥     id_rsa.pub  锁

2. 将公钥发送到要远程登陆的服务器上

scp -P 端口 ~/.ssh/id_rsa.pub 用户名@对方ip:~/.ssh/

3. 在服务器建立authorized_keys映射

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

4. 在服务端打开authorized_keys修改配置

vi /etc/ssh/sshd_config#1. 本地是linux系统(屏蔽mac操作):
AuthorizedKeysFile   %h/.ssh/authorized_keys
#2. 本地是mac系统(屏蔽linux操作):
AuthorizedKeysFile .ssh/authorized_keys

5. 本地验证操作

ssh root@182.61.28.143# 若是不成功
用chmod 检查.shh权限.ssh 应为700authorized_keys 为600

6.2 方案分析

6.2.1 需求

​ 部署一个环境,支持我们的django项目正常运行

6.2.2 需求分析

2、python环境  --->  3、python虚拟环境
1、django环境部署4、django软件安装5、项目基本操作6、应用基本操作7、view和url配置8、问题:只有本机能访问9、方案代理---- 10、nginx
11、nginx实现代理13、pcre软件安装12、nginx软件安装14、nginx基本操作15、nginx代理的配置16、目录结构17、查看配置文件18、找到对应的代理配置项
19、启动django
20、启动nginx
21、整个项目调试

6.2.3 部署方案

一、django环境部署1.1 python虚拟环境1.2 django环境部署1.2.1 django软件安装1.2.2 项目基本操作1.2.3 应用基本操作1.2.4 view和url配置
二、nginx代理django2.1 nginx软件安装2.1.1 pcre软件安装2.1.2 nginx软件安装2.1.3 nginx基本操作2.2 nginx代理配置2.2.1 目录结构查看2.2.2 配置文件查看2.2.3 编辑代理配置项
三、项目调试3.1 启动软件3.1.1 启动django3.1.2 启动nginx3.2 整个项目调试

6.3 项目环境部署

6.3.1 python 虚拟环境

1. 虚拟环境安装

apt-getinstall python-virtualenv -y
或者
pip3 install virtualenv

2. 虚拟环境基本操作

# 创建
virtualenv -p /usr/bin/python3.5 venv
# 进入
source venv/bin/activate
# 退出
deactivate
# 删除
rm-rf venv

6.3.2 django环境

1. django 软件安装

# 注意:先进入虚拟环境
source venv/bin/activate
# 解压
cd /data/soft
tar xf Django-1.10.7.tar.gz
# 查看
cd Django-1.10.7
cat INSTALL or README
# 安装
python setup.py install

拓展知识点:

python类型软件的安装流程
普通:解压  安装
特殊:解压  编译  安装编译:python setup.py build

2. django 项目创建

cd /data/server
django-admin startproject kungs

3. django 应用操作

​ 1) 创建应用

cd /data/server/kungs
python manage.py startapp test1

​ 2) 注册应用

# vimitcast/settings.py
INSTALL_APP= [...'test1',
]

4. view 和 url 配置

  1. 需求:
访问django的页面请求为:127.0.0.1:8000/hello/,页面返回效果为:itcast v1.0
  1. 分析:
views文件定制逻辑流程函数
urls文件定制路由跳转功能
  1. view配置文件生效
admin-1@ubuntu:/data/soft#cat /data/server/kungs/test1/views.py
from django.shortcuts import render
from django.http import HttpResponse# Create your views here.
def hello(resquest):return HttpResponse("kungs V1.0")
  1. url文件配置
admin-1@ubuntu:/data/soft#cat /data/server/kungs/kungs/urls.py
...
from django.contrib import admin
from test1.views import *
urlpatterns= [url(r'^admin/', admin.site.urls),url(r'^hello/$', hello),
]
  1. 启动django:
cd /data/server/kungs
python manage.py runserver  注意:避免在运行的时候不能做别的时候,改为这样操作
(venv) root@instance-nl5v4j4n:/data/server/kungs# python manage.py runserver >dev/null 2>&1 &
[1] 10620
(venv) root@instance-nl5v4j4n:/data/server/kungs# # 解决8000端口被占用(Error: That port is already in use).
sudo fuser -k 8000/tcp

6.3.3 nginx环境

1. pcre 软件安装

# 解压
cd /data/soft/
tarxf pcre-8.39.tar.gz
# 查看帮助
cd pcre-8.39
INSTALL或者 README
# 配置
./configure
# 编译
make
# 安装
make install

拓展知识点:

linux中软件安装的一般流程

# 解压(解压文件,获取真正的配置文件)
tar
# 配置(根据默认的配置项或者更改配置项,生成编译配置文件(Makefile))
configure
# 编译(根据 Makefile 内容,编译生成指定的软件所需要的所有文件)
make
# 安装(将编译生成的所有文件,转移到软件指定安装的目录下面--prefix)
make install

2. nginx 软件安装

# 解压
cd /data/soft/
tar xf nginx-1.10.2.tar.gz
# 配置
(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2# cd nginx-1.10.2/
(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2# ./configure --prefix=/data/server/nginx
(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2# ./configure --prefix=/data/server/nginx --without-http_gzip_module
# 编译
make
# 安装
make install

nginx 简单操作

# 检查
/data/server/nginx/sbin/nginx -t
# 开启
/data/server/nginx/sbin/nginx
# 关闭
/data/server/nginx/sbin/nginx -s stop
# 重载
/data/server/nginx/sbin/nginx -s reload# 查看端口,检查是否运行
netstat -tnulp

常见报错问题

突发问题:

(venv) root@instance-nl5v4j4n:/data/server/nginx#./sbin/nginx -t./sbin/nginx:error while loading shared libraries: libpcre.so.1: cannot open shared objectfile: No such file or directory

分析:

1、先看报错
2、思考,是否报错真实有效分析: 谁错了
3、查找文件全名找不到,我们使用正则
4、找到文件,我没有问题nginx默认找库文件的路径有问题
5、解决

解决:

(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2#ldd /data/server/nginx/sbin/nginx
linux-vdso.so.1 =>  (0x00007ffdb9154000)
libdl.so.2 =>/lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa59379b000)
libpthread.so.0 =>/lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa59357e000)
libcrypt.so.1 =>/lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fa593345000)
libpcre.so.1 => not found
libc.so.6 =>/lib/x86_64-linux-gnu/libc.so.6 (0x00007fa592f7c000)
/lib64/ld-linux-x86-64.so.2(0x0000564bfef41000)

查找文件:

(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2#find / -name "libpcre.so.1"
/data/soft/pcre-8.39/.libs/libpcre.so.1
/usr/local/lib/libpcre.so.1
...

链接该文件

(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2#ln -s /usr/local/lib/libpcre.so.1 /lib/x86_64-linux-gnu/

再次检查一下nginx的配置文件

(venv) root@instance-nl5v4j4n:/data/soft/nginx-1.10.2#/data/server/nginx/sbin/nginx -tnginx:the configuration file /data/server/nginx/conf/nginx.conf syntax is oknginx:configuration file /data/server/nginx/conf/nginx.conf test is successful

---------------

6.3.4 nginx代理django

nginx 配置简介

nginx的目录结构

root@instance-nl5v4j4n:/data/soft/nginx-1.10.2# tree -L 2 /data/server/nginx/
/data/server/nginx/
├── client_body_temp
├── conf
│   ├── fastcgi.conf
│   ├── fastcgi.conf.default
│   ├── fastcgi_params
│   ├── fastcgi_params.default
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── mime.types.default
│   ├── nginx.conf
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp
├── html
│   ├── 50x.html
│   └── index.html
├── logs
│   ├── access.log
│   ├── error.log
│   └── nginx.pid
├── proxy_temp
├── sbin
│   └── nginx
├── scgi_temp
└── uwsgi_temp9 directories, 21 files

nginx 配置文件介绍

全局配置段                  http配置段server配置段           项目或者应用location配置段. url配置

nginx 代理配置

案例需求:

​ 访问地址 182.61.28.143/hello/ 跳转到 127.0.0.1:8000/hello/的django服务来处理hello请求

编辑配置文件实现代理功能

配置内容

62:  location /hello/ {
63:     proxy_pass http://127.0.0.1:8000;
64: }

注释:当我访问地址是

配置文件生效

/data/server/nginx/sbin/nginx -t
/data/server/nginx/sbin/nginx -s reload

第7章 手工代码发布

7.1 方案分析

发布需求:

​ 手工方式部署代码

发布方案:

  1. 获取代码
sed -i 's#文件原始的内容#替换后的内容#g' 要更改到文件名

打包代码

  1. 传输代码

  1. 关闭应用

  2. 解压代码

  3. 放置代码​

  4. 备份老文件

  1. 放置新文件

  1. 开启应用

  2. 检查

注意:

​ 获取代码和打包代码在==代码仓库主机==上进行操作

​ 其他操作,都在**线上服务器**进行操作

--------------------

7.2 方案实施

1. 获取代码

mkdir /data/codes -p
cd /data/codes
sed -i 's#1.0#1.1#' django/views.py
sed -i  's#原内容#替换后内容#g' 文件

2. 打包代码

cd /data/codes/
tar zcf django.tar.gz django

3. 传输代码

cd /data/codes/
scp django.tar.gz root@182.61.28.143:/data/codes/

注意:前面两步在代码仓库主机上NgandeMBP:~ kungs$操作

4. 关闭应用

1. 关闭nginx应用/data/server/nginx/sbin/nginx -s stop
2. 关闭django应用根据端口查看进程号,lsof -Pti :8000杀死进程号kill 56502一条命令搞定它:kill $(lsof -Pti:8000)

5. 解压代码

cd /data/codes
tar xf django.tar.gz

6. 放置代码

1. 备份老文件需求:备份的格式:文件名-时间戳时间戳:年月日时分秒date +%Y%m%d%H%M%Smv /data/server/kungs/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)
2. 放置新文件cd /data/codesmv django/views.py /data/server/kungs/test1/

7. 开启应用

开启django应用source /data/virtual/venv/bin/activatecd /data/server/kungspython manage.py runserver >> /dev/null 2>&1 &deactivate
开启nginx应用/data/server/nginx/sbin/nginx

8. 检查

netstat -tnulp | grep ':80'

完整的代码:

#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:kungs
# 版本:V 0.2
# 联系方式:yanpenggong@163.com# 获取代码
get_code(){echo "获取代码"
}
# 打包代码
tar_code(){echo "打包代码"ssh root@182.61.28.143 "/bin/bash /data/scripts/tar_code.sh"
}
# 传输代码
scp_code(){echo "传输代码"cd /data/codes# [ -f django.tar.gz ] && rm -f django.tar.gzscp root@182.61.28.143:/data/codes/django.tar.gz ./
}
# 关闭应用
stop_serv(){echo "关闭应用"echo "关闭nginx应用"/data/server/nginx/sbin/nginx -s stopecho "关闭django应用"kill $(lsof -Pti:8000)
}
# 解压代码
untar_code(){echo "解压代码"cd /data/codestar xf django.tar.gz
}
# 放置代码
fangzhi_code(){echo "放置代码"echo "备份老文件"mv /data/server/kungs/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)echo "放置新文件"# mv /data/codes/django/views.py /data/server/kungs/test1/cp /data/codes/django/views.py /data/server/kungs/test1/
}
# 开启应用
start_serv(){echo "开启应用"echo "开启django应用"source /data/virtual/venv/bin/activatecd /data/server/kungs/python manage.py runserver >> /dev/null 2>&1 &deactivateecho "开启nginx应用"/data/server/nginx/sbin/nginx
}
# 检查
check(){echo "检查应用"netstat -tnulp | grep ':80'
}
# 部署函数
pro_deploy(){get_codetar_codescp_codestop_servuntar_codefanghi_codestart_servcheck
}
# 主函数
main(){pro_deploy
}
# 调用主函数
main

--------------------

注: 大型脚本之[命令填充](#_8.2.2 命令填充)


第8章 脚本发布代码

代码部署流程拆分成两部分:

  1. 简单脚本(远端主机上执行)

  2. 大型脚本(线上机器执行)

8.1 简单脚本编写

1、命令罗列实现功能
2、固定内容变量实现
3、功能函数实现
4、远程执行命令

8.1.1 命令罗列

目的:实现代码仓库主机上的操作命令功能即可

实现简单的功能— 简单的命令罗列

#!/bin/bash
# 功能:打包代码
# 脚本名:tar_code.sh
# 作者:kungs
# 版本:V 0.1
# 联系方式:yanpenggong@163.comcd /data/codes
[ -f django.tar.gz ] && rm -f django.tar.gz
tar zcf django.tar.gz django

脚本编写完成后,进行测试:

sed -i 's#1.1#1.2#' /data/codes/django/views.py
bash /data/scripts/tar_code.sh

查看压缩文件内容

zcat django.tar.gz

8.1.2 固定内容变量化

问题:脚本里面的手写的固定的内容太多了,更改时候费劲

脚本优化之 固定内容变量化

#!/bin/bash
# 功能:打包代码
# 脚本名:tar_code.sh
# 作者:kungs
# 版本:V 0.2
# 联系方式:yanpenggong@163.comFILE='django.tar.gz'
CODE_DIR='/data/codes'
CODE_PRO='django'cd "${CODE_DIR}"
[ -f "$Misplaced &{FILE}" ] && rm -f "${FILE}"
tar zcf "${FILE}" "${CODE_PRO}"

脚本编写完成后,进行测试:

sed -i 's#1.2#1.3#' /data/codes/django/views.py
bash /data/scripts/tar_code.sh

查看压缩文件内容

zcat django.tar.gz
# mac 下的方法:
gunzip -c django.tar.gz

8.1.3 功能函数化

需求:三条命令其实是一个组合,实现的是一个功能

脚本优化之 功能函数化

#!/bin/bash
# 功能:打包代码
# 脚本名:tar_code.sh
# 作者:kungs
# 版本:V 0.3
# 联系方式:yanpenggong@163.comFILE='django.tar.gz'
CODE_DIR='/data/codes'
CODE_PRO='django'code_tar(){cd "${CODE_DIR}"[ -f "$Misplaced &{FILE}" ] && rm -f "${FILE}"tar zcf "${FILE}" "${CODE_PRO}"
}
code_tar

脚本编写完成后,进行测试:

sed -i 's#1.2#1.3#' /data/codes/django/views.py
bash /data/scripts/tar_code.sh

查看压缩文件内容

zcat /data/codes/django.tar.gz

8.1.4 远程执行

远程命令执行

格式:

ssh 远程主机登录用户名@远程主机ip地址 "执行命令"

效果

NgandeMBP:scripts kungs$# ssh root@182.61.28.143 "ifconfig eth0"
eth0      Link encap:Ethernet  HWaddr 00:0c:29:f7:ca:d4  inet addr:182.61.28.143  Bcast:182.168.56.255  Mask:255.255.255.0...

远程执行脚本测试

1. 远程更新文件内容
ssh root@182.61.28.143 "sed -i /'s#1.4#1.5#' /data/codes/django/views.py"
2. 远程查看脚本
ssh root@182.61.28.143 "ls /data/scripts"
3. 远程执行脚本
ssh root@182.61.28.143 "/bin/bash /data/scripts/tar_code.sh"
4. 远程检查更新效果
ssh root@182.61.28.143 "zcat /data/codes/django.tar.gz"

--------------------

8.2 大型脚本编写

本地是指线上服务器主机(云服务器)

​ 我们先来回顾一下代码[发布流程图](#_5.2.1 流程简介)

编写大型脚本有一个流程:

一、脚本框架
二、[命令填充](#_7.2 方案实施)
三、完善功能增加日志功能增加锁文件功能增加主函数逻辑增加参数安全措施

8.2.1 脚本框架

不用脚本框架:1、命令多; 2、功能多; 3、不好组合

需求:先将脚本所涉及的所有业务流程跑通

方案:使用函数来体现

脚本实施:

#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:kungs
# 版本:V 0.1
# 联系方式:yanpenggong@163.com# 获取代码
get_code(){echo "获取代码"
}# 打包代码
tar_code(){echo "打包代码"
}# 传输代码
scp_code(){echo "传输代码"
}# 关闭应用
stop_serv(){echo "关闭应用"echo "关闭nginx应用"echo "关闭django应用"
}# 解压代码
untar_code(){echo "解压代码"
}# 放置代码
fangzhi_code(){echo "放置代码"echo "备份老文件"echo "放置新文件"
}# 开启应用
start_serv(){echo "开启应用"echo "开启django应用"echo "开启nginx应用"
}# 检查
check(){echo "检查项目"
}# 部署函数
deploy_pro(){get_codetar_codescp_codestop_servuntar_codefangzhi_codestart_servcheck
}# 主函数
main(){deploy_pro
}# 执行主函数
main

8.2.2 命令填充

需求:在流程跑通的情况下,执行完整的代码部署过程

方案:在脚本框架中,填写执行成功的命令

脚本实施:

#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:kungs
# 版本:V 0.2
# 联系方式:yanpenggong@163.com# 获取代码
get_code(){echo "获取代码"
}# 打包代码
tar_code(){echo "打包代码"ssh root@182.61.28.143 "/bin/bash /data/scripts/tar_code.sh"
}# 传输代码
scp_code(){echo "传输代码"cd /data/codes[ -f django.tar.gz ] && rm -f django.tar.gzscp root@182.61.28.143:/data/codes/django.tar.gz ./
}# 关闭应用
stop_serv(){echo "关闭应用"echo "关闭nginx应用"/data/server/nginx/sbin/nginx -s stopecho "关闭django应用"kill $(lsof -Pti :8000)
}# 解压代码
untar_code(){echo "解压代码"cd /data/codestar xf django.tar.gz
}# 放置代码
fangzhi_code(){echo "放置代码"echo "备份老文件"mv /data/server/kungs/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)echo "放置新文件"mv /data/codes/django/views.py /data/server/kungs/test1/
}# 开启应用
start_serv(){echo "开启应用"echo "开启django应用"source /data/virtual/venv/bin/activatecd /data/server/kungs/python manage.py runserver >> /dev/null 2>&1 &deactivateecho "开启nginx应用"/data/server/nginx/sbin/nginx
}
# 检查
check(){echo "检查项目"netstat -tnulp | grep ':80'
}...

8.2.3 增加日志功能

需求:1、追踪记录; 2、数据说话

方案:增加日志功能

1、日志文件/data/logs/deploy.log
2、日志格式日期 时间 脚本名称 步骤

知识点:

文件内容追加: >>日期:date +%F时间:date +%T脚本:$0

脚本实施:

#!/bin/bash
...# 定义本地变量
LOG_FILE='/data/logs/deploy.log'
# 增加日志功能函数
write_log(){DATE=$(date +%F)TIME=$(date +%T)buzhou="$1"echo "${DATE} ${TIME} $0 : ${buzhou}" >> "${LOG_FILE}"
}# 获取代码
get_code(){...write_log "获取代码"
}# 打包代码
tar_code(){...write_log "打包代码"
}# 传输代码
scp_code(){...write_log "传输代码"
}# 关闭应用
stop_serv(){...write_log "关闭应用"...write_log "关闭nginx应用"...write_log "关闭django应用"
}# 解压代码
untar_code(){...write_log "解压代码"
}# 放置代码
fangzhi_code(){...write_log "放置代码"...write_log "备份老文件"...write_log "放置新文件"
}# 开启应用
start_serv(){...write_log "开启应用"...write_log "开启django应用"...write_log "开启nginx应用"
}
# 检查
check(){...write_log "检查项目"
}...

8.2.4 增加锁文件功能

需求:

同一时间段内,只允许有一个用户来执行这个脚本
如果脚本执行的时候,有人在执行,那么输出报错:脚本 deploy.sh 正在运行,请稍候...

设计:

1、锁文件       /tmp/deploy.pid
2、存在锁文件时候,输出报错信息
3、脚本执行的时候,需要创建锁文件
4、脚本执行结束的时候,需要删除锁文件

知识点:

条件和结果: 双分支if语句
文件表达式: -f  file_name
验证表达式: [ 表达式 ]
创建命令:touch
删除命令:rm -f

脚本实施:

#!/bin/bash
...
PID_FILE='/tmp/deploy.pid'
...
# 增加锁文件功能
add_lock(){echo "增加锁文件"touch "${PID_FILE}"write_log "增加锁文件"
}# 删除锁文件功能
del_lock(){echo "删除锁文件"rm -f "${PID_FILE}"write_log "删除锁文件"
}# 部署函数
deploy_pro(){add_lock...del_lock
}# 脚本报错信息
err_msg(){echo "脚本 $0 正在运行,请稍候..."
}# 主函数
main(){if [ -f "${PID_FILE}" ]
thenerr_msg
elsedeploy_pro
fi
}# 执行主函数
main

8.2.5 脚本流程知识点填充

需求:

如果我给脚本输入的参数是deploy,那么脚本才执行,否则的话,提示该脚本的使用帮助信息,然后退出提示信息:脚本 deploy.sh 的使用方式: deploy.sh [ deploy ]

分析:

1、脚本传参,就需要在脚本内部进行调用参数
2、脚本的帮助信息
3、脚本内容就需要对传参的内容进行判断

知识点:

1、shell内置变量:$n
2、帮助信息: 简单函数定义和调用
3、内容判断: 多if语句或者case语句

方案:

1、脚本的传参脚本执行:bash deploy.sh deploy位置参数的调用: $1
2、脚本的帮助信息定义一个usage函数,然后调用。提示信息格式:脚本 deploy.sh 的使用方式: deploy.sh [ deploy ]
3、内容判断main函数体调用函数传参: $1在main函数中,结合case语句,对传入的参数进行匹配如果传入参数内容是"deploy",那么就执行代码部署流程如果传入参数内容不是"deploy",那么输出脚本的帮助信息if语句和case语句的结合if语句在外,case语句在内case语句在外,if语句在内

脚本实施:

#!/bin/bash
...# 脚本帮助信息
usage(){echo "脚本 $0 的使用方式: $0 [deploy]"exit
}# 主函数
main(){case "$1" in "deploy")if [ -f "${PID_FILE}" ]thenerr_msgelsedeploy_profi;;*)usage;;esac
}# 执行主函数
main $1

8.2.6 输入参数安全优化

需求:

对脚本传入的参数的数量进行判断,如果参数数量不对,提示脚本的使用方式,然后退出

分析:

1、脚本参数数量判断
2、条件判断数量对,那么执行主函数数量不对,那么调用脚本帮助信息

知识点:

1、脚本参数数量判断shell内置变量:  $#条件表达式:     [ $# -eq 1 ]
2、条件判断:双分支if语句

方案:

1、双分支if语句 + main函数调用

脚本实施:

#!/bin/bash
...# 执行主函数
if [ $# -eq 1 ]
thenmain $1
elseusage
fi

完整的脚本代码实例查看:

1、deploy.sh

root@instance-nl5v4j4n:/data/scripts# cat deploy.sh
#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:kungs
# 版本:V 0.6
# 联系方式:yanpenggong@163.com# 定义本地变量
LOG_FILE='/data/logs/deploy.log'
PID_FILE='/temp/deploy.pid'# 增加日志功能函数
write_log(){DATE=$(date +%F)TIME=$(date +%T)buzhou="$1"echo "${DATE} ${TIME} $0 : ${buzhou}" >> "${LOG_FILE}"
}# 增加锁文件
add_lock(){echo "增加锁文件"touch "${PID_FILE}"write_log "增加锁文件"
}
# 删除锁文件
del_lock(){echo "删除锁文件"rm -f "${PID_FILE}"write_log "删除锁文件"
}
# 获取代码
get_code(){echo "获取代码"write_log "获取代码"
}
# 打包代码
tar_code(){echo "打包代码"ssh root@182.61.28.143 "/bin/bash /data/scripts/tar_code.sh"write_log "打包代码"
}
# 传输代码
scp_code(){echo "传输代码"cd /data/codes# [ -f django.tar.gz ] && rm -f django.tar.gzscp root@182.61.28.143:/data/codes/django.tar.gz ./write_log "传输代码"
}
# 关闭应用
stop_serv(){echo "关闭应用"write_log "关闭应用"echo "关闭nginx应用"/data/server/nginx/sbin/nginx -s stopwrite_log "关闭nginx应用"echo "关闭django应用"kill $(lsof -Pti:8000)write_log "关闭django应用"
}
# 解压代码
untar_code(){echo "解压代码"cd /data/codestar xf django.tar.gzwrite_log "解压代码"
}
# 放置代码
putdemo_code(){echo "放置代码"write_log "放置代码"echo "备份老文件"mv /data/server/kungs/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)write_log "备份老文件"echo "放置新文件"# mv /data/codes/django/views.py /data/server/kungs/test1/cp /data/codes/django/views.py /data/server/kungs/test1/write_log "放置新文件"
}
# 开启应用
start_serv(){echo "开启应用"write_log "开启应用"echo "开启django应用"source /data/virtual/venv/bin/activatecd /data/server/kungs/python manage.py runserver >> /dev/null 2>&1 &deactivatewrite_log "开启django应用"echo "开启nginx应用"/data/server/nginx/sbin/nginxwrite_log "开启nginx应用"
}
# 检查
check(){echo "检查应用"netstat -tnulp | grep ':80'write_log "检查应用"
}
# 部署函数
pro_deploy(){add_lockget_codetar_codescp_codestop_servuntar_codeputdemo_codestart_servcheckdel_lock
}# 报错信息
err_msg(){echo "该脚本 $0 正在运行,请稍候..."
}# 帮助信息
usage(){echo "脚本 $0 的使用方式是:$0 [deploy]"
}# 主函数
main(){case "$1" indeploy)if [ -f "${PID_FILE}" ]thenerr_msgelsepro_deployfi;;*)usage;;esac
}
# 调用主函数
if [ "$#" -ne 1 ]
thenusage
elsemain $1
fi

2、tar_code.sh

root@instance-nl5v4j4n:/data/scripts# cat tar_code.sh# !/bin/bash# 功能:打包代码# 脚本名:tar_code.sh# 作者:kungs# 版本:V 0.3# 联系方式:yanpenggong@163.com# 定义本地变量FILE='django.tar.gz'
CODE_DIR='/data/codes'
PRO_DIR='django'# 定义一个功能函数tar_code(){cd "${CODE_DIR}"[ -f "${FILE}" ] && rm -f "${FILE}"tar zcf "${FILE}" "${PRO_DIR}"
}# 调用主函数tar_code

--------------------

8.3 脚本调试功能

脚本调试的时候,主要分三种方式:

-n      检查脚本中的语法错误
-v      先显示脚本所有内容,然后执行脚本,结果输出,如果执行遇到错误,将错误输出。
-x      将执行的每一条命令和执行结果都打印出来

--------------------

8.4 生产脚本编写总结

8.4.1 简单脚本编写总结

1、手工执行的命令一定要可执行
2、命令简单罗列
3、固定的内容变量化
4、功能函数化

8.4.2 复杂脚本编写总结

1、手工执行的命令一定要可执行
2、根据发布流程编写脚本的框架
3、将手工执行的命令填充到对应的框架函数内部
4、增加日志功能,方便跟踪脚本历史执行记录
5、主函数中逻辑流程控制好
6、设计安全的方面:增加锁文件,保证代码发布的过程中不受干扰,输入参数数量输入参数匹配脚本帮助信息
7、调试脚本

8.4.3 注意事项:

1、命令一定要保证能正常执行
2、成对的符号,要成对写,避免丢失
3、函数调用,写好函数后,一定要在主函数中进行调用
4、避免符号出现中文
5、命令变量的写法一定要规范
6、固定的内容一定要变量实现,方便以后更改
7、日志的输出
8、脚本的传参和函数的传参要区别对待

备注:

文件整理:Kungs

博客:https://blog.csdn.net/yanpenggong

SHELL自动化运维相关推荐

  1. linux云自动化运维,Liunx运维一线大神亲授 全新Linux云计算运维基础与Linux Shell自动化运维实战课程...

    Liunx运维一线大神亲授 全新Linux云计算运维基础与Linux Shell自动化运维实战课程 全新Linux云计算运维基础与Linux Shell自动化运维实战课程,由于国内一线大神亲自授课与教 ...

  2. 如何做好python自动化运维,python在运维中的应用

    这篇文章主要介绍了一个有趣的事情,具有一定借鉴价值,需要的朋友可以参考下.希望大家阅读完这篇文章后大有收获,下面让小编带着大家一起了解一下. 1.如何做好python自动化运维 随着移动互联网的普及, ...

  3. 自动化运维Shell课堂笔记

    1.课程回顾 2.课程大纲 1.shell编程 开发和运维 shell基础知识 shell变量 shell表达式 shell流程控制语句 2.代码发布 项目周期 代码部署的方式 代码部署流程 服务器环 ...

  4. linux运维脚本编写,最强Linux自动化运维 Shell高级脚本编程实战 带习题+项目实战案例+全套配置脚本...

    最强Linux自动化运维 Shell高级脚本编程实战 带习题+项目实战案例+全套配置脚本 大家可以通过参考下面的课程学习目录,就会发现单单只从目录上来分析就知道这是一部非常系统的Shell自动化脚本运 ...

  5. python学习之自动化运维(一):shell的使用

    第一章: shell快速入门: 一.运维简介: 1.运维简介以及企业中的那些事: 2.简单的运维知识 规划: 需要多少资源来支持项目的运行; 管理: 项目运行过程中的所有内容都管理起来; 流程规范: ...

  6. linux 【完结篇】第六章 shell编程及自动化运维--三剑客

    linux 第六章 shell编程及自动化运维–三剑客 一.正则表达式 1.前言 名词解释: 正则表达式是一种字符模式,用于在查找过程中匹配指定的字符.在大多数程序里,正则表达式都被置于2个正斜杠之间 ...

  7. 自动化运维—saltstack

    2019独角兽企业重金招聘Python工程师标准>>> 自动化运维--saltstack .ansible 一.自动化运维介绍 传统运维:传统运维效率低,大多工作需要人工完成,工作繁 ...

  8. 自动化运维工具Ansible

    ansible简介: ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)的优点,实现了批量系统配置.批 ...

  9. 自动化运维工具----ansible

    自动化运维工具----ansible ansible是新出现的运维工具是基于Python研发的糅合了众多老牌运维工具的优点实现了批量操作系统配置.批量程序的部署.批量运行命令等功能. 主要模块以及功能 ...

最新文章

  1. HTML中单选框的设置,和提交按钮之间的组合
  2. Mysql学习总结(4)——MySql基础知识、存储引擎与常用数据类型
  3. POJ 1423 Big Number
  4. lintcode:二叉树的中序遍历
  5. poj 2985(并查集+线段树求K大数)
  6. 金蝶服务器删除缓存文件,金蝶KIS专业版卸载不干净导致无法安装之解决办法
  7. 95-130-346-源码-source-kafka相关-KafkaConsumerThread
  8. 《密码爆破漏洞详解》——黑客必修的入门操作( 建议收藏 )
  9. 趣味程序之打印字符图案系列
  10. SQLPrompt关闭联网
  11. windows取色器(吸取颜色,获取颜色的rgb信息)
  12. 请帮助和关心Unix-Center
  13. 单细胞测序在免疫治疗研究中的应用
  14. 一个vector内容赋值给另一个vector
  15. Ansible#Ansible-Jinja2模板介绍
  16. 高效领导者提升思考力的5个底层法则
  17. 超详细mac新手教程,让你离熟练操作mac只需十分钟!
  18. 数据结构与算法-进阶(八)AOV 网
  19. 小数化分数 (思维)
  20. 如何高效学习 - 斯科特·扬

热门文章

  1. 废话中的极品废话 单反对焦系统全解析
  2. Burp Suite抓取安卓手机微信小程序数据包(HTTPS) 主机有线/无线连接两种方式
  3. 一个等差×等比数列连加式
  4. 如何操作拆分Word文档?干货来啦!怎样上下拆分Word文档?
  5. 数字图像处理之颜色空间
  6. Firefox OS 2.0 模拟器 – 使用官方火狐浏览器扩展无痛完美模拟体验火狐手机系统
  7. 上海科技大学计算机本科2020,上海科技大学
  8. [日推荐]『旅行云清单』列好清单,准备出发!
  9. 高盛:腾讯、阿里和百度将被移出MSCI中国指数IT行业
  10. jsp 格式化输出日期,数字