SHELL自动化运维

2023-05-16

第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.sh

NgandeMacBook-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 SED

root@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" ]
then
  echo "男"
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" ]
then
  echo "男"
else
  echo "女"
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" ]
then
  echo "男"
elif [ "${a}" == "nv" ]
then
  echo "女"
else
  echo "未知"
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" ]
then
  echo "服务启动中..."
elif [ "${a}" == "stop" ]
then
  echo "服务关闭中..."
elif [ "${a}" == "restart" ]
then
  echo "服务重启中..."
else
  echo "脚本$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循环语句

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

语法格式

forin 列表
do
   执行语句
done

注意:

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

实例:

root@instance-nl5v4j4n:/home/kungs# cat for.sh 
#!/bin/bash
# for 语句演示

for i in $(ls /home/kungs)
do
  echo "/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=1

while [ "${a}" -lt 5 ]
do
  echo "${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 ]
do
  echo "${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 ]
then
  case "${a}" in
    start)
      echo "服务启动中..."
      ;;
    stop)
      echo "服务关闭中..."
      ;;
    restart)
      echo "服务重启中..."
      ;;
    *)
      usage
      ;;
    esac
else
  usage
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、rsync

2. 没有网情况下:物理方式: 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 -p
    cd /data
    echo 'file1' > tar-ceshi/file1.txt
    echo '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. 将压缩包文件传输到远端主机2
	scptar-ceshi.tar.gz root@192.168.8.15:/tmp
5. 在主机2上解压 压缩包文件
    cd /tmp
    tar xf tar-ceshi.tar.gz
6. 在主机2上修改压缩包文件内容。然后再次压缩
    echo 'file3' >> tar-ceshi/file1.txt
    tar 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
└── virtual

7 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 应为700
    authorized_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代理django
    2.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 启动django
        3.1.2 启动nginx
    3.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 -t

nginx:the configuration file /data/server/nginx/conf/nginx.conf syntax is ok

nginx: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_temp

9 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%S
        mv /data/server/kungs/test1/views.py /data/backup/views.py-$(date +%Y%m%d%H%M%S)
2. 放置新文件
    cd /data/codes
    mv django/views.py /data/server/kungs/test1/

7. 开启应用

开启django应用
    source /data/virtual/venv/bin/activate
    cd /data/server/kungs
    python 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.gz
  scp root@182.61.28.143:/data/codes/django.tar.gz ./
}
# 关闭应用
stop_serv(){
  echo "关闭应用"
  echo "关闭nginx应用"
  /data/server/nginx/sbin/nginx -s stop
  echo "关闭django应用"
  kill $(lsof -Pti:8000)
}
# 解压代码
untar_code(){
  echo "解压代码"
  cd /data/codes
  tar 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/activate
  cd /data/server/kungs/
  python manage.py runserver >> /dev/null 2>&1 &
  deactivate
  echo "开启nginx应用"
  /data/server/nginx/sbin/nginx
}
# 检查
check(){
  echo "检查应用"
  netstat -tnulp | grep ':80'
}
# 部署函数
pro_deploy(){
  get_code
  tar_code
  scp_code
  stop_serv
  untar_code
  fanghi_code
  start_serv
  check
}
# 主函数
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.com

cd /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.com

FILE='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.com

FILE='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_code
  tar_code
  scp_code
  stop_serv
  untar_code
  fangzhi_code
  start_serv
  check
}

# 主函数
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.gz
  scp root@182.61.28.143:/data/codes/django.tar.gz ./
}

# 关闭应用
stop_serv(){
  echo "关闭应用"
  echo "关闭nginx应用"
  /data/server/nginx/sbin/nginx -s stop
  echo "关闭django应用"
  kill $(lsof -Pti :8000)
}

# 解压代码
untar_code(){
  echo "解压代码"
  cd /data/codes
  tar 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/activate
  cd /data/server/kungs/
  python manage.py runserver >> /dev/null 2>&1 &
  deactivate
  echo "开启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}" ]
then
      err_msg
else
      deploy_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}" ]
      then
         err_msg
      else
        deploy_pro
      fi
    ;;
    *)
      usage
    ;;
  esac
}

# 执行主函数
main $1

8.2.6 输入参数安全优化

需求:

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

分析:

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

知识点:

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

方案:

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

脚本实施:

#!/bin/bash
...

# 执行主函数
if [ $# -eq 1 ] 
then
  main $1
else
  usage
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.gz
  scp 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 stop
  write_log "关闭nginx应用"
  echo "关闭django应用"
  kill $(lsof -Pti:8000)
  write_log "关闭django应用"
}
# 解压代码
untar_code(){
  echo "解压代码"
  cd /data/codes
  tar xf django.tar.gz
  write_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/activate
  cd /data/server/kungs/
  python manage.py runserver >> /dev/null 2>&1 &
  deactivate
  write_log "开启django应用"
  echo "开启nginx应用"
  /data/server/nginx/sbin/nginx
  write_log "开启nginx应用"
}
# 检查
check(){
  echo "检查应用"
  netstat -tnulp | grep ':80'
  write_log "检查应用"
}
# 部署函数
pro_deploy(){
  add_lock
  get_code
  tar_code
  scp_code
  stop_serv
  untar_code
  putdemo_code
  start_serv
  check
  del_lock
}

# 报错信息
err_msg(){
  echo "该脚本 $0 正在运行,请稍候..."
}

# 帮助信息
usage(){
  echo "脚本 $0 的使用方式是:$0 [deploy]"
}

# 主函数
main(){
  case "$1" in
    deploy)
      if [ -f "${PID_FILE}" ]
      then
        err_msg
      else
        pro_deploy
      fi
      ;;
    *)
      usage
      ;;
  esac
}
# 调用主函数
if [ "$#" -ne 1 ]
then
  usage
else
  main $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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SHELL自动化运维 的相关文章

  • 有没有办法改变vim的默认模式

    有谁知道如何更改vim的默认模式 它的默认模式是命令模式 但是我可以将其更改为插入模式吗 只需将以下行添加到您的 vimrc 中 start Vim s default mode will be changed to Insert mode
  • 从配置文件中读取分配

    我有配置文件 其中每行都包含用分号分隔的分配 像这样的东西 模仿正常的 shell 分配 VAR1 1 VAR2 2 VAR1 3 VAR2 4 每行包含相同的变量 并且旨在单独处理 这些配置文件都在系统管理员的控制之下 所以使用eval现
  • 如何在 .zip 文件中使用 grep

    有 3 个文件 a csv b csv c csv 压缩为 abh zip 现在可以在 abh zip 上执行 grep 命令 是否有任何通配符 仅对里面的 c csv 文件运行 grep压缩 如果你有zipgrep 据我所知 它是随zip
  • 如何在 PHP 中执行 shell 脚本?

    我有一个脚本 var www myscript sh它创建文件夹并运行命令svn update对于我的项目 我需要通过在浏览器中的 PHP 文件中调用它来执行此脚本 即本地主机 test php 我尝试使用函数shell exec and
  • 如何将发布档案转换为 git repo

    我有一个发布档案列表 MyProject 0 9 zip MyProject 1 0 zip MyProject 1 3 tar gz MyProject 2 0 tar gz 每个文件都包含一个与存档同名的文件夹 不带文件扩展名 其中包含
  • 如何让 Jenkins 2.0 在与结帐相同的目录中执行 sh 命令?

    这是我的 Jenkins 2 x 管道 node master stage Checkout checkout scm stage Build Pex sh build sh 当我运行此管道时 签出会按预期将代码放入工作区 但是它并没有期望
  • Perforce:从命令行“从工作区中删除”?

    The p4v Perforce GUI 客户端 http www perforce com perforce products p4v html具有 操作 gt 从工作空间中删除 菜单命令 该命令可从工作空间中删除受版本控制且未打开进行编
  • 使用 find 和 xargs 交互删除文件

    我正在尝试将一些文件从 find 命令传输到交互式删除命令 以便我可以仔细检查要删除的文件 但我遇到了一些麻烦 find name print0 xargs 0 rm i 我认为上面的方法可行 但我只得到一串 rm remove regul
  • MongoDB - 编辑器变量 - MongoDB shell - Windows 7

    EDITOR 变量功能真的可以在 Windows 7 上使用吗 我正在读一篇文章 说一旦我们设置了 EDITOR 变量在 mongorc js 中 我们只需在 shell 中输入 编辑变量名 and var name将被加载到编辑器中 在我
  • linux + ksh + 向下舍入或向上舍入 - 浮点数

    在我的 ksh 脚本中 我只需要计算整数 有时我会得到浮点数 例如 3 49 或 4 8 等 所以我需要根据以下规则将浮点数转换为整数 示例 3 49 will be 3 2 9 will be 3 4 1 will be 4 23 51
  • 在 Linux 中重新启动时,新创建的文件变为 0 kb(数据被覆盖为空)

    我遇到了一个奇怪的问题 这让我发疯 当前的任务是在 root 用户第一次登录时启动一组文件 并在同一用户第二次登录时启动另一组文件 我决定使用 profile 和 bashrc 文件 并在第一次登录期间发生的任务结束时重新加载 bashrc
  • 有哪些基于对象的 shell?

    我打算写一个面向对象的shell 基于Python 我已经有很多想法了 但在实现它之前 我想通过一些现有的 shell 来激发我的灵感 我所说的面向对象的基本意思是 参数不仅仅是字符串数组 而且是对象数组 返回值也是一个对象 不仅有 std
  • Linux shell 从用户输入中获取设备 ID

    我正在为一个程序编写安装脚本 该程序需要在其配置中使用 lsusb 的设备 ID 因此我正在考虑执行以下操作 usblist lsusb put the list into a array for each line use the arr
  • 如何并行执行4个shell脚本,我不能使用GNU并行?

    我有4个shell脚本dog sh bird sh cow sh和fox sh 每个文件使用 xargs 并行执行 4 个 wget 来派生一个单独的进程 现在我希望这些脚本本身能够并行执行 由于某些我不知道的可移植性原因 我无法使用 GN
  • Python 脚本:每次打印新行到 shell,而不是更新现有行

    说到Python 我是个菜鸟 我有一个 python 脚本 它给我这样的输出 last ZVZX W3vo9I Downloading video webpage last ZVZX W3vo9I Extracting video info
  • 在压缩存档内的文本文件上运行“head”,而不解压存档

    问候 我接手了之前的团队并编写了处理 csv 文件的 ETL 作业 我在 ubuntu 上结合使用 shell 脚本和 perl csv 文件很大 它们以压缩档案形式到达 解压后 很多都超过 30Gb 是的 那是 G 旧进程是在 cron
  • 为什么 fork 炸弹没有使 android 崩溃?

    这是最简单的叉子炸弹 我在许多 Linux 发行版上执行了它 但它们都崩溃了 但是当我在 android 终端中执行此操作时 即使授予后也没有效果超级用户权限 有什么解释为什么它没有使 Android 系统崩溃吗 一句话 ulimit Li
  • 在 bash 中添加(收集)退出代码

    我需要依赖于脚本中的几个单独的执行 并且不想将它们全部捆绑在一个丑陋的 if 语句中 我想使用退出代码 每次执行并添加它 最后 如果这个值超过阈值 我想执行一个命令 伪代码 ALLOWEDERROR 5 run something RESU
  • Bash:递归复制命名文件,保留文件夹结构

    我希望 cp R src prog js images icon jpg tmp package 将在目标目录中产生对称结构 tmp package src prog js images icon jpg 但相反 这两个文件都被复制到 tm
  • 如何制作 Bash 脚本来查找项目中未使用的图像?

    如何制作一个 Bash shell 脚本 它可以识别所有 jpg gif 和 png 文件 然后识别文件夹中任何文本文件中哪些文件未通过 url href 或 src 链接 这就是我开始的 但我最终得到了与我想要的相反的结果 我不想知道引用

随机推荐

  • 如何在 Ubuntu 20.04 上安装 Vagrant

    本文最先发布在 xff1a https www itcoder tech posts how to install vagrant on ubuntu 20 04 Vagrant是一个命令行工具 xff0c 用于构建和管理虚拟开发环境 默认
  • 如何在 Ubuntu 20.04 上安装 GCC(build-essential)

    本文最先发布在 xff1a https www itcoder tech posts how to install gcc on ubuntu 20 04 GNU 编译器集合是一系列用于语言开发的编译器和库的集合 xff0c 包括 C C
  • 如何在 Ubuntu 20.04 上安装和配置 Redis

    本文最先发布在 xff1a https www itcoder tech posts how to install and configure redis on ubuntu 20 04 Redis 是一个开源的在内存存储键值对数据的存储程
  • 如何在 Ubuntu 20.04 上安装 PHP

    本文最先发布在 xff1a https www itcoder tech posts how to install php on ubuntu 20 04 PHP 是世界上使用广泛的服务端编程语言之一 很多著名的 CMS 和框架 xff0c
  • 用python轻松完成一个分布式事务TCC,保姆级教程

    什么是分布式事务 xff1f 银行跨行转账业务是一个典型分布式事务场景 xff0c 假设A需要跨行转账给B xff0c 那么就涉及两个银行的数据 xff0c 无法通过一个数据库的本地事务保证转账的ACID xff0c 只能够通过分布式事务来
  • 如何在 Ubuntu 20.04 上安装 Spotify

    本文最先发布在 xff1a https www itcoder tech posts how to install spotify on ubuntu 20 04 Spotify是一个音乐流媒体服务商 xff0c 它可以让你和无数的歌曲亲密
  • SSH 操作实践指南

    本文最先发布在 xff1a https www itcoder tech posts ssh practice SSH 是我们经常要和远程服务器交互使用的工具 下面是一些实践中总结的 SSH 操作经验 xff1a 一 如何选择 SSH ke
  • 如何在 Ubuntu 20.04 上安装 R

    本文最先发布在 xff1a https www itcoder tech posts how to install r on ubuntu 20 04 R 是一门开源编程语言和自由的环境 xff0c 主要用于统计分析 绘图 它由 R 基金会
  • 如何在 Ubuntu 20.04 上安装 Mono

    本文最先发布在 xff1a https www itcoder tech posts how to install mono on ubuntu 20 04 Mono 是一个平台 xff0c 基于 ECMA ISO 标准 xff0c 用于开
  • 如何在 Ubuntu 20.04 上安装和使用 Composer

    本文最先发布在 xff1a https www itcoder tech posts how to install and use composer on ubuntu 20 04 Composer 是一个 PHP 依赖管理器 xff08
  • 3分钟在线开通优惠费率的微信支付商户号(商户收款码)

    1 问 xff1a 为什么要开通微信商户号 xff1f 答 xff1a 因为微信个人收款 xff0c 不支持信用卡支付 xff0c 无法提供经营报表 xff0c 无法支持线上支付等 关于微信个人收款码与商家码区别 xff0c 参考 xff1
  • 设置git使用vimdiff比较差异

    原文 xff1a http hi baidu com drdr blog item 57de1e95665a81047af48062 html 修改git的如下2条配置 xff1a git config global diff tool v
  • YUV图像格式

    原文 xff1a http blog csdn net zhongnanjun 3 article details 3934938 YUV xff08 亦称YCrCb xff09 是被欧洲电视系统所采用的一种颜色编码方法 xff08 属于P
  • mime types 大全--来自ubuntu /etc/mime.types

    MIME TYPES and the extensions that represent them The format of this file is a MIME type on the left and zero or more fi
  • VUE3中运用axios处理后端数据

    xff08 1 xff09 在src下新建一个http文件夹 xff0c 文件夹下新建一个index js xff08 2 xff09 在index js文件中引入axios xff08 3 xff09 在index js里面写axios实
  • leveldb性能调优

    许多的nosql都使用leveldb或者类似leveldb的系统作为存储引擎 xff0c 例如tair xff0c hbase xff0c canssandra xff0c 因此理解并调优存储引擎可以大大的提高系统的性能 前一篇大致介绍了原
  • Android 重启 不开机 Backtrace 分析

    此文摘自 mtk online Android 在发生crash 时可以通过 backtrace 定位发生的的位置 xff0c 方便进一步来 fix issue 1 Java Backtrace 从Java Backtrace 我们可以知道
  • SQL Server 2016 OPENJSON忽略大小写

    使用WITH子句OPENJSON将输入JSON表达式中的键与该WITH子句中的列名进行匹配 xff0c 是区分大小写 xff0c 可以使用条件聚合以忽略大小写 xff1a DECLARE 64 JSON varchar max 61 39
  • 论文解读:自适应参数控制方案介绍——Effect Assessment

    Adaptive Probabilities of Crossover and Mutation in Genetic Algorithms TCYB 1994 动机自适应 p c p c
  • SHELL自动化运维

    第1章 shell脚本 1 1 shell 简介 shell 的定义 xff1a span class token number 1 span 在计算机科学中 xff0c Shell就是一个命令解释器 span class token nu