自动化运维Shell课堂笔记

1、课程回顾
2、课程大纲
1、shell编程
开发和运维
shell基础知识
shell变量
shell表达式
shell流程控制语句

2、代码发布
项目周期
代码部署的方式
代码部署流程
服务器环境部署
手工方式部署代码
脚本方式部署代码




3、shell
3.1、开发和运维
3.1.1 开发
开发是什么?
岗位
项目代码的开发
给公司带来效益

开发会运维如何
1、技能提升
2、面试有优势


开发人员发展规划
开发人员 -- 开发组长 -- 开发经理 --- 更高岗位cto
技术熟练、熬死他们   了解:精益管理和敏捷开发 运维、熟练精益管理和敏捷开发、devops
网络、数据库、存储、虚拟化、云计算、
Docker、持续集成和持续交付
项目访问流程
1、用户访问前端
2、前端转移数据请求给web服务器
3、涉及到数据调用,和数据库进行交互

3.1.2 运维
运维是什么
岗位

常见技术岗位:
产品、开发、测试、运维

运维的工作范围
规划、管理、安全、监控、告警、规范和流程、平台、优化

团队
项目 -- 多个团队(应用)
团队 多个组
多个人



自动化运维
基础:脚本自动化
分类:
开发人员:开发语言脚本
运维人员:shell脚本


3.2 shell 基础知识
3.2.1 shell 是什么
shell 贝壳
shell就是一个命令解释器[重点]

3.2.2 shell 分类
基本上shell分两大类:
图形界面shell和命令行shell

图形界面shell
gnome,kde

命令行shell
windows:cmd.exe
linux:bash

shell的历史:
sh ksh csh bash[重点]
1970左右
程序设计语言

常见的linux发行版本:
ubuntu
centos
6.5-6.8   7.0
redhat
debain
生产上重点:
稳定压倒一切

shell命令执行特点:
逐行输入命令、逐行进行确认



3.2.3 shell 脚本
shell脚本是什么
就是一堆可执行命令的组合[重点]

shell脚本开发规范
1、命名:
要有意义,后缀.sh
2、首行
是而且必须是命令解释器
3、注释
简单描述脚本信息
4、执行
bash 脚本名称
5、脚本内容
从上到下,依次执行。
6、其他
成对的符号,成对写,避免丢失
() {} [] '' ""
流程格式:
先写完,然后填空
缩进
仅仅是表示美观


脚本执行方式
方式一:
bash 脚本名称
bash test.sh
/bin/bash /data/scripts/python10/test.sh

场景:
工作中常用[*****]

方式二:
文件的路径
示例:
/data/scripts/python10/test.sh
./test.sh

重点:
文件一定要有执行权限

场景:
工作中常用

方式三:
source 或者 .
加载

场景:
保证环境一致性

案例:
某个脚本在你自己的笔记本可以执行成功,但是在其他人机器上执行失败,
原因就是:环境不一致

超前知识点:
命令变量的定义:
dir=`pwd`
查看变量的方式
echo $dir



注释
单行注释: #
多行注释:
:<<!。。。!

示例:
#!/bin/bash
:<<!
脚本描述:测试命令行输入
作者:python 13期
版本:v1.0
联系方式:中南海
!
dir=`pwd`
echo $dir

3.2.4 shell & python


执行方式
shell脚本直接调用系统命令执行

为什么运维shell使用比例比python高
执行python --- 导入模块 -- 模块调用系统命令 --- 执行

调用系统命令情况下,
shell效率比python高

对比

shell 杀猪刀 干净利索
python 导弹 需要模块帮助、实现功能多、


3.3 shell 变量
3.2.1 shell变量是什么
变量:
存储动态值的一个抽象概念

变量包括两部分:
变量名 不变的
变量值 变化的


变量之歌:
星星还是那个星星

变量名 星星
变量值 时间

散文 形散而神不散
变量名
变量值 形式

我的角色
变量名
变量值 角色


3.2.2 常见变量


本地变量
在本地有效

全局变量
在当前系统下,所有环境都有效

内置变量
bash中内置了很多变量,我们可以直接拿过来使用


3.2.3 本地变量
普通变量:
方式一:
变量名=变量值
重点:
变量值必须是一个整体,中间么有特殊字符

方式二:
变量名='变量值'
重点:
我看到的内容,我就输出什么内容

方式三:
变量名="变量值"
重点:
如果变量值范围内,有可以解析的变量A,那么首先解析变量A,将A的结果和其他内容组合成一个整体,重新赋值给变量B

示例:
# echo $hello


# hello=nihao
# echo $hello
nihao
# hello1=nihao 666
666: command not found
# hello1="nihao 666"
# echo $hello1
nihao 666
# hello2='nihao 777'
# echo $hello2
nihao 777
# echo $hello
nihao
# hello3='nihao 666-$hello'
# echo $hello3
nihao 666-$hello
# hello4="nihao 666-$hello"
# echo $hello4
nihao 666-nihao


命令变量
变量名=`命令`
变量名=$(命令)

执行流程:
1、执行命令
2、将命令执行后的结果,赋值给新的变量名A



变量的查看:


方式一:
$变量名
场景:
私下里,在命令行/脚本中使用
图省事
方式二:
${变量名}
场景:
echo " dsa  dsafsa  dsafsa ${变量名} f "

方式三:
"${变量名}"
场景:
标准使用方式,




3.3.4 全局变量
定义方式:
方式一:
1、首先定义一个本地变量
2、使用export声明这个本地变量为全局变量
示例:
root@admina-virtual-machine:/data/scripts/python10# hello5=qiang666
root@admina-virtual-machine:/data/scripts/python10# export hello5=qiang666
root@admina-virtual-machine:/data/scripts/python10# env | grep hello
hello=nihao
hello5=qiang666
hello1=nihao 666



方式二:
我定义本地变量的同时,使用export声明本地变量为全局变量

示例:
root@admina-virtual-machine:/data/scripts/python10# export hello5=qiang666
root@admina-virtual-machine:/data/scripts/python10# env | grep hello
hello=nihao
hello5=qiang666
hello1=nihao 666


全局变量查看方式
查看方式:
env
set
declare



删除变量
格式:
unset 变量名

示例:
root@admina-virtual-machine:/data/scripts/python10# env | grep hello
hello=nihao
hello5=qiang666
hello1=nihao 666
root@admina-virtual-machine:/data/scripts/python10# unset hello
root@admina-virtual-machine:/data/scripts/python10# unset hello1
root@admina-virtual-machine:/data/scripts/python10# unset hello2
root@admina-virtual-machine:/data/scripts/python10# unset hello3
root@admina-virtual-machine:/data/scripts/python10# unset hello4
root@admina-virtual-machine:/data/scripts/python10# unset hello5
root@admina-virtual-machine:/data/scripts/python10# env | grep hello
root@admina-virtual-machine:/data/scripts/python10# echo $hello2


root@admina-virtual-machine:/data/scripts/python10# echo $hello3


root@admina-virtual-machine:/data/scripts/python10# echo $hello4


3.3.5 内置变量
跟脚本文件有关系的变量
$0 获取脚本的名称
示例:
root@admina-virtual-machine:/data/scripts/python10# bash file1.sh 
我脚本的名称是: file.sh
我脚本的名称是:file1.sh
root@admina-virtual-machine:/data/scripts/python10# cat file1.sh 
#!/bin/bash
# 获取脚本的名称
echo "我脚本的名称是: file.sh"
echo "我脚本的名称是:$0"
场景:
获取当前脚本的使用方式
root@admina-virtual-machine:/data/scripts/python10# bash file1.sh 
file1.sh 脚本的使用方法:file1.sh  [ arg1 | arg2 ]
root@admina-virtual-machine:/data/scripts/python10# cat file1.sh 
#!/bin/bash
# 获取脚本的名称
echo "$0 脚本的使用方法:$0  [ arg1 | arg2 ]"


$# 获取当前脚本传入参数的数量
示例:
root@admina-virtual-machine:/data/scripts/python10# cat num.sh 
#!/bin/bash
# 获取当前脚本传入的参数数量
echo "当前脚本传入的参数数量是: $#"
root@admina-virtual-machine:/data/scripts/python10# bash num.sh 
当前脚本传入的参数数量是: 0
root@admina-virtual-machine:/data/scripts/python10# bash num.sh a
当前脚本传入的参数数量是: 1
root@admina-virtual-machine:/data/scripts/python10# bash num.sh a dsanfdsn dsa f ds f ds af dsa f dsa f dsa f ds fds  fds af ds  fds  fds  fds f sa f ds af ds af dsa  sd f dsa  fd
当前脚本传入的参数数量是: 34


场景:
判断我输入的参数数量是否是我要求的个数


需求:
我的脚本只允许传入两个参数,如果输入参数不对,那么输出脚本的执行帮助

root@admina-virtual-machine:/data/scripts/python10# cat num1.sh 
#!/bin/bash
# 判断传入参数数量
[ "$#" -eq 2 ] && echo "$0 开始执行..."
[ "$#" -eq 2 ] || echo "$0 帮助: $0 [ arg1 ]"
root@admina-virtual-machine:/data/scripts/python10# bash num1.sh 
num1.sh 帮助: num1.sh [ arg1 ]
root@admina-virtual-machine:/data/scripts/python10# bash num1.sh 2
num1.sh 帮助: num1.sh [ arg1 ]
root@admina-virtual-machine:/data/scripts/python10# bash num1.sh 2 2
num1.sh 开始执行...




$n 获取当前脚本传入的第n个位置的参数
示例:
root@admina-virtual-machine:/data/scripts/python10# cat weizhi.sh 
#!/bin/bash
# 获取指定位置的参数
echo "第一个位置的参数是: $1"
echo "第二个位置的参数是: $2"
echo "第三个位置的参数是: $3"
echo "第四个位置的参数是: $4"
root@admina-virtual-machine:/data/scripts/python10# bash weizhi.sh 1
第一个位置的参数是: 1
第二个位置的参数是: 
第三个位置的参数是: 
第四个位置的参数是: 
root@admina-virtual-machine:/data/scripts/python10# bash weizhi.sh 1 2 3 4
第一个位置的参数是: 1
第二个位置的参数是: 2
第三个位置的参数是: 3
第四个位置的参数是: 4


场景:
1、脚本同时传入多个参数
2、脚本中有不同的函数专门调用不同位置的传参

执行脚本的方式:
bash 脚本名  arg1  arg2

脚本的内容:
函数1 $1
函数2 $2


$? 获取文件执行或者命令执行的返回状态值
示例:
root@admina-virtual-machine:/data/scripts/python10# bash nihao
bash: nihao: No such file or directory
root@admina-virtual-machine:/data/scripts/python10# echo $?
127
root@admina-virtual-machine:/data/scripts/python10# ls
file1.sh  num.sh  test.sh  weizhi.sh
root@admina-virtual-machine:/data/scripts/python10# echo $?
0
root@admina-virtual-machine:/data/scripts/python10# llllllll
llllllll: command not found
root@admina-virtual-machine:/data/scripts/python10# echo $?
127

场景:
root@admina-virtual-machine:/data/scripts/python10# bash zhuangtai.sh 
执行返回状态值是 0
/data/scripts/python10
执行返回状态值是 0
当前dir位置是 /data/scripts/python10
执行返回状态值是 0
root@admina-virtual-machine:/data/scripts/python10# cat zhuangtai.sh 
#!/bin/bash
# 文件执行返回状态值演示
cd /data/scripts/python10
echo "执行返回状态值是 $?"
pwd
echo "执行返回状态值是 $?"
./test.sh
echo "执行返回状态值是 $?"




获取随机字符串
场景
创建一个用户,密码是随机生成

生成随机数
$RANDOM 生成随机的5位数以内的数字

示例:
root@admina-virtual-machine:/data/scripts/python10# echo $RANDOM
18061
root@admina-virtual-machine:/data/scripts/python10# echo $RANDOM | md5sum
27e8fda6333d9716503ff007cbd4cdb7  -
root@admina-virtual-machine:/data/scripts/python10# echo $RANDOM | md5sum | awk '{print $1}'
3a8d2e3493d99151f43b68df8ab09fdc
root@admina-virtual-machine:/data/scripts/python10# str=$(echo $RANDOM | md5sum | awk '{print $1}')
root@admina-virtual-machine:/data/scripts/python10# echo $str
e111ef894a8fd92979c4331386901381



字符串相关的内置变量
截取
${变量名:起始位置:截取长度}

示例:从头截取8个字符
root@admina-virtual-machine:/data/scripts/python10# echo $str
e111ef894a8fd92979c4331386901381
root@admina-virtual-machine:/data/scripts/python10# echo ${str:0:8}
e111ef89

示例:从第5个位置开始,截取8个字符
root@admina-virtual-machine:/data/scripts/python10# echo ${str:4:8}
ef894a8f


示例:从末尾截取8个字符
root@admina-virtual-machine:/data/scripts/python10# echo ${str: -8}
86901381
root@admina-virtual-machine:/data/scripts/python10# echo ${str:0-8}
86901381
注意:
${str: -8}
${str:0-8}

只有一个冒号,空格或者0 


默认值
场景一:
变量a如果有内容,那么就输出a的变量值
变量a如果没有内容,那么就输出默认的内容

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

套餐示例:
如果我输入的参数为空,那么输出内容是 "您选择的套餐是: 套餐 1"
如果我输入的参数为n,那么输出内容是 "您选择的套餐是: 套餐 n"

root@admina-virtual-machine:/data/scripts/python10# cat select.sh 
#!/bin/bash
# 套餐选择演示
a="$1"


echo "您选择的套餐是: 套餐 ${a:-1}"
root@admina-virtual-machine:/data/scripts/python10# bash select.sh 
您选择的套餐是: 套餐 1
root@admina-virtual-machine:/data/scripts/python10# bash select.sh 2
您选择的套餐是: 套餐 2
root@admina-virtual-machine:/data/scripts/python10# bash select.sh 6
您选择的套餐是: 套餐 6




场景二:
无论变量a是否有内容,都输出默认值
格式:
${变量名+默认值}
场景示例:
不管我说国家法定结婚年龄是 多少岁,都输出 国家法定结婚年龄(男性)是 22 岁

root@admina-virtual-machine:/data/scripts/python10# cat age.sh 
#!/bin/bash
# 默认值演示示例二
a="$1"
echo "国家法定结婚年龄(男性)是 ${a+22} 岁"
root@admina-virtual-machine:/data/scripts/python10# bash age.sh 3
国家法定结婚年龄(男性)是 22 岁
root@admina-virtual-machine:/data/scripts/python10# bash age.sh 300
国家法定结婚年龄(男性)是 22 岁



3.4 shell 表达式
3.4.1 shell验证操作
方式一:
[ 表达式 ]

0 表示表达式成立
1 表示表达式不成立

方式二:
test 表达式

示例:
root@admina-virtual-machine:/data/scripts/python10# [ 1 = 1 ]
root@admina-virtual-machine:/data/scripts/python10# echo $?
0
root@admina-virtual-machine:/data/scripts/python10# [ 1 = 2 ]
root@admina-virtual-machine:/data/scripts/python10# echo $?
1
root@admina-virtual-machine:/data/scripts/python10# test 1 = 1
root@admina-virtual-machine:/data/scripts/python10# echo $?
0
root@admina-virtual-machine:/data/scripts/python10# test 1 = 2
root@admina-virtual-machine:/data/scripts/python10# echo $?
1


3.4.2 shell表达式
逻辑
&&
命令1  &&  命令2
如果命令1执行成功,那么我才执行命令2 -- 夫唱妇随
如果命令1执行失败,那么命令2也不执行
示例:
root@admina-virtual-machine:/data/scripts/python10# [ 1 = 1 ] && echo "条件成立"
条件成立
root@admina-virtual-machine:/data/scripts/python10# [ 1 = 2 ] && echo "条件成立"
root@admina-virtual-machine:/data/scripts/python10# 

||
命令1 || 命令2
如果命令1执行成功,那么命令2不执行 -- 对着干
如果命令1执行失败,那么命令2执行
示例:
root@admina-virtual-machine:/data/scripts/python10# [ 1 = 2 ] || echo "条件不成立"
条件不成立
root@admina-virtual-machine:/data/scripts/python10# [ 1 = 1 ] || echo "条件不成立"
root@admina-virtual-machine:/data/scripts/python10# 


文件

-f 判断输入内容是否是一个文件
示例:
root@admina-virtual-machine:/data/scripts/python10# [ -f weizhi.sh ] && echo "是一个文件"
是一个文件
root@admina-virtual-machine:/data/scripts/python10# [ -f weizhi.sddh ] || echo "不是一个文件"
不是一个文件

-d 判断输入内容是否是一个目录
示例:
root@admina-virtual-machine:/data/scripts/python10# [ -d weizhi.sddh ] || echo "不是一个目录"
不是一个目录
root@admina-virtual-machine:/data/scripts/python10# mkdir nihao
root@admina-virtual-machine:/data/scripts/python10# ls
age.sh  file1.sh  nihao  num1.sh  num.sh  select.sh  test.sh  weizhi.sh  zhuangtai.sh
root@admina-virtual-machine:/data/scripts/python10# [ -d nihao ] && echo "是一个目录"
是一个目录

-x 判断输入内容是否可执行
示例:
root@admina-virtual-machine:/data/scripts/python10# [ -x age.sh ] || echo "文件没有执行权限"
文件没有执行权限
root@admina-virtual-machine:/data/scripts/python10# [ -x test.sh ] && echo "文件有执行权限"
文件有执行权限
root@admina-virtual-machine:/data/scripts/python10# [ -x test.sh ] && ./test.sh 
当前dir位置是 /data/scripts/python10

数字
-gt 大于
-lt 小于
-eq 等于
-ne 不等于

场景:
root@admina-virtual-machine:/data/scripts/python10# cat num2.sh 
#!/bin/bash
# 数字表达式 -ne使用场景
[ "$#" -ne 2 ] && echo " $0 脚本使用帮助信息: $0 [ arg1 arg2 ]"
[ "$#" -eq 2 ] && echo "$0 脚本正在执行......"
root@admina-virtual-machine:/data/scripts/python10# bash num2.sh 
num2.sh 脚本使用帮助信息: num2.sh [ arg1 arg2 ]
root@admina-virtual-machine:/data/scripts/python10# bash num2.sh 2
num2.sh 脚本使用帮助信息: num2.sh [ arg1 arg2 ]
root@admina-virtual-machine:/data/scripts/python10# bash num2.sh 2 2
num2.sh 脚本正在执行......
root@admina-virtual-machine:/data/scripts/python10# bash num2.sh 2 2 3
num2.sh 脚本使用帮助信息: num2.sh [ arg1 arg2 ]



字符串
== 两侧的内容是一致的
!= 两侧的内容是不一致的

使用场景:
root@admina-virtual-machine:/data/scripts/python10# cat str.sh 
#!/bin/bash
# 字符串表达式的演示
a="$1"
b="$2"


[ "${a}" == "${b}" ] && echo "您输入的两个参数内容是一致的"
[ "${a}" != "${b}" ] && echo "您输入的两个参数内容是不一致的"


root@admina-virtual-machine:/data/scripts/python10# bash str.sh abc abc
您输入的两个参数内容是一致的
root@admina-virtual-machine:/data/scripts/python10# bash str.sh abc abcd
您输入的两个参数内容是不一致的


3.5 shell 流程控制



3.5.1 简单流程控制


选择
python if语句格式:

python中的流程控制:

if语句:
单if语句:
if 条件:
执行语句

双if语句:
if 条件:
执行语句
else:
执行语句2

多if语句:
if 条件1:
执行语句1
elif 条件2:
执行语句2
else:
执行语句2

shell中的if
单if语句:
格式:
if 条件
then
执行语句
fi
重点:
首行关键字是if
末行关键字是fi
场景:
单一条件,只有一个输出


示例:
如果我输入内容是 nan
root@admina-virtual-machine:/data/scripts/python10# bash danif.sh nan
您的性别是 男
root@admina-virtual-machine:/data/scripts/python10# cat danif.sh 
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
  echo "您的性别是 男"
fi

双if语句:
格式:
if 条件
then
执行语句
else
执行语句2
fi

场景:
一个条件,两种结果

示例:
root@admina-virtual-machine:/data/scripts/python10# cat shuangif.sh 
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
  echo "您的性别是 男"
else
  echo "您的性别是 女"
fi
root@admina-virtual-machine:/data/scripts/python10# bash shuangif.sh nan
您的性别是 男
root@admina-virtual-machine:/data/scripts/python10# bash shuangif.sh nv
您的性别是 女
root@admina-virtual-machine:/data/scripts/python10# bash shuangif.sh nvdsaf
您的性别是 女

多if语句:
格式:
if 条件1
then
执行语句1
elif 条件2
then
执行语句2
else
执行语句3
fi


场景:
n个条件,n+1个结果

示例:
root@admina-virtual-machine:/data/scripts/python10# cat duoif.sh 
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
  echo "您的性别是 男"
elif [ "$1" == "nv" ]
then
  echo "您的性别是 女"
else
  echo "您的性别,我不知道"
fi
root@admina-virtual-machine:/data/scripts/python10# bash duoif.sh 
您的性别,我不知道
root@admina-virtual-machine:/data/scripts/python10# bash duoif.sh nan
您的性别是 男
root@admina-virtual-machine:/data/scripts/python10# bash duoif.sh nv
您的性别是 女
root@admina-virtual-machine:/data/scripts/python10# bash duoif.sh nvdsaf
您的性别,我不知道

场景:
服务的启动
需求:
start 启动
stop 关闭
restart 重启
* 脚本使用方式

root@admina-virtual-machine:/data/scripts/python10# cat if.sh 
#!/bin/bash
# 多if语句的使用场景
if [ "$1" == "start" ]
then
  echo "启动 $0 脚本"
elif [ "$1" == "stop" ]
then
  echo "关闭 $0 脚本"
elif [ "$1" == "restart" ]
then
  echo "重启 $0 脚本"
else
  echo "$0 脚本的使用方式: $0 [ start | stop | restart ]"
fi
root@admina-virtual-machine:/data/scripts/python10# bash if.sh 
if.sh 脚本的使用方式: if.sh [ start | stop | restart ]
root@admina-virtual-machine:/data/scripts/python10# bash if.sh start
启动 if.sh 脚本
root@admina-virtual-machine:/data/scripts/python10# bash if.sh stop
关闭 if.sh 脚本
root@admina-virtual-machine:/data/scripts/python10# bash if.sh restart
重启 if.sh 脚本

case语句
格式:
case 值 in
值1)
执行语句
;;
值1)
执行语句
;;
值1)
执行语句
;;
值1)
执行语句
;;
esac



场景:服务启动
root@admina-virtual-machine:/data/scripts/python10# cat case.sh 
#!/bin/bash
# case语句使用场景
case "$1" in
"start")
echo "启动 $0 脚本"
;;
"stop")
echo "关闭 $0 脚本"
;;
"restart")
echo "重启 $0 脚本"
;;
*)
echo "$0 脚本的使用方式: $0 [ start | stop | restart ]"
;;
esac
root@admina-virtual-machine:/data/scripts/python10# bash case.sh 
case.sh 脚本的使用方式: case.sh [ start | stop | restart ]
root@admina-virtual-machine:/data/scripts/python10# bash case.sh start
启动 case.sh 脚本
root@admina-virtual-machine:/data/scripts/python10# bash case.sh stop
关闭 case.sh 脚本
root@admina-virtual-machine:/data/scripts/python10# bash case.sh restart
重启 case.sh 脚本




循环
python格式:
for语句:
for 条件:
执行语句
while语句:
while 条件:
执行语句

until语句:
until 条件:
执行语句

shell的格式:
for 语句:
格式;
for 条件
do
执行语句
done

场景:
遍历列表

示例:遍历文件
root@admina-virtual-machine:/data/scripts/python10# ls
age.sh   danif.sh  file1.sh  nihao    num2.sh  select.sh    str.sh   weizhi.sh
case.sh  duoif.sh  if.sh     num1.sh  num.sh   shuangif.sh  test.sh  zhuangtai.sh

root@admina-virtual-machine:/data/scripts/python10# cat for.sh 
#!/bin/bash
# for语句的使用示例
file=`ls /data/scripts/python10`
for i in "${file}"
do
 echo "${i}"
done
root@admina-virtual-machine:/data/scripts/python10# bash for.sh 
age.sh
case.sh
danif.sh
duoif.sh
file1.sh
for.sh
if.sh
...


示例2:遍历数字
root@admina-virtual-machine:/data/scripts/python10# cat for1.sh 
#!/bin/bash
# for 语句示例2
num=$(seq 10)
for i in "${num}"
do
 echo "${i}"
done
root@admina-virtual-machine:/data/scripts/python10# bash for1.sh 
1
2
3
4
5
6
7
8
9
10

shell中的计算方法:
格式;
let 变量名a=变量名a+1
a=$((变量名a+1))

示例:
root@admina-virtual-machine:/data/scripts/python10# echo $a


root@admina-virtual-machine:/data/scripts/python10# a=1
root@admina-virtual-machine:/data/scripts/python10# let a=a+1
root@admina-virtual-machine:/data/scripts/python10# echo $a
2
root@admina-virtual-machine:/data/scripts/python10# a=$((a+1))
root@admina-virtual-machine:/data/scripts/python10# echo $a
3



while 语句:
格式;
while 条件
do
执行语句
done

场景:
如果条件满足,那么我一直循环下去

示例:
root@admina-virtual-machine:/data/scripts/python10# cat while.sh 
#!/bin/bash
# while的示例
a=1
while [ "${a}" -lt 5 ] 
do
  echo "${a}"
  a=$((a+1))
done
root@admina-virtual-machine:/data/scripts/python10# bash while.sh 
1
2
3
4



until 语句:
格式;
until 条件
do
执行语句
done

场景:
如果条件不满足,那么我一直循环下去


示例:
root@admina-virtual-machine:/data/scripts/python10# cat until.sh 
#!/bin/bash
# until的示例
a=1
until [ "${a}" -gt 4 ] 
do
  echo "${a}"
  a=$((a+1))
done
root@admina-virtual-machine:/data/scripts/python10# bash until.sh 
1
2
3
4

3.5.2 复杂流程控制
python的函数
定义函数:
def 函数名():
函数体
调用
函数名()

传参数
def 函数名(参数):
函数体


调用传参数
函数名(参数)

shell函数格式:
定义函数:
函数名(){
函数体
}

调用函数:
函数名

传参数
函数名 参数

函数体调用参数:
函数名(){
函数体 $n
}
注意:
类似于shell内置变量中的位置参数

定义和调用函数示例:
root@admina-virtual-machine:/data/scripts/python10# bash fun2.sh 
wo de mingzi shi  111
root@admina-virtual-machine:/data/scripts/python10# cat fun2.sh 
#!/bin/bash
# 函数使用场景一:执行频繁的命令
dayin(){
 echo "wo de mingzi shi  111"
}
dayin

函数传参和函数体内调用参数的示例
root@admina-virtual-machine:/data/scripts/python10# bash fun4.sh 
wo de mingzi shi 111
root@admina-virtual-machine:/data/scripts/python10# cat fun4.sh 
#!/bin/bash
# 函数的使用场景二
dayin(){
 echo "wo de mingzi shi $1"
}
dayin 111

函数使用场景:
执行频繁的命令
或者
执行命令格式相近的命令

场景一:执行频繁的命令
root@admina-virtual-machine:/data/scripts/python10# bash fun1.sh 
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
root@admina-virtual-machine:/data/scripts/python10# cat fun1.sh 
#!/bin/bash
# 输出一大堆执行频繁的命令
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
echo "wo de mingzi shi  111"
函数演变一下
root@admina-virtual-machine:/data/scripts/python10# cat fun2.sh 
#!/bin/bash
# 函数使用场景一:执行频繁的命令
dayin(){
 echo "wo de mingzi shi  111"
}
dayin
dayin
dayin
dayin
dayin
dayin
root@admina-virtual-machine:/data/scripts/python10# bash fun2.sh 
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111
wo de mingzi shi  111

场景二;执行命令格式相近的命令
root@admina-virtual-machine:/data/scripts/python10# cat fun3.sh 
#!/bin/bash
# 输出格式相近的命令
echo "wo de mingzi shi  1a11"
echo "wo de mingzi shi  11d1"
echo "wo de mingzi shi  111d"
echo "wo de mingzi shi  111s"
echo "wo de mingzi shi  111a"
echo "wo de mingzi shi  111s"
echo "wo de mingzi shi  111s"
echo "wo de mingzi shi  111d"
echo "wo de mingzi shi  111f"
echo "wo de mingzi shi  111e"
root@admina-virtual-machine:/data/scripts/python10# bash fun3.sh 
wo de mingzi shi  1a11
wo de mingzi shi  11d1
wo de mingzi shi  111d
wo de mingzi shi  111s
wo de mingzi shi  111a
wo de mingzi shi  111s
wo de mingzi shi  111s
wo de mingzi shi  111d
wo de mingzi shi  111f
wo de mingzi shi  111e

函数演变
root@admina-virtual-machine:/data/scripts/python10# cat fun4.sh 
#!/bin/bash
# 函数的使用场景二
dayin(){
 echo "wo de mingzi shi $1"
}
dayin 111
root@admina-virtual-machine:/data/scripts/python10# vim fun4.sh 
root@admina-virtual-machine:/data/scripts/python10# bash fun4.sh 
wo de mingzi shi 111
wo de mingzi shi 111s
wo de mingzi shi 111d
wo de mingzi shi 111g
wo de mingzi shi 111d
root@admina-virtual-machine:/data/scripts/python10# cat fun4.sh 
#!/bin/bash
# 函数的使用场景二
dayin(){
 echo "wo de mingzi shi $1"
}
dayin 111
dayin 111s
dayin 111d
dayin 111g
dayin 111d

函数传参多个,函数体内调用示例
root@admina-virtual-machine:/data/scripts/python10# bash fun4.sh 
wo de mingzi shi 111
wo de mingzi shi df
wo de mingzi shi dfs
root@admina-virtual-machine:/data/scripts/python10# cat fun4.sh 
#!/bin/bash
# 函数的使用场景二
dayin(){
 echo "wo de mingzi shi $1"
 echo "wo de mingzi shi $2"
 echo "wo de mingzi shi $3"
}
dayin 111 df dfs


1、项目周期
1.1 项目周期
需求:
开发
开发经理拆分项目
1、人员
2、技术水平

组员:
项目的子模块

项目交给测试之前,需要项目的联调后,联调的时候,需要开发团队都在一起

测试
部署
运营

1.2 项目开发环境
个人开发环境
个人笔记本
公司配的电脑

特点:
环境是自己配的,团队中不同的个人开发环境可以不一样
代码版本、软件版本、工具....

工作内容:
项目的子模块,子功能

工作人员:
自己

最终目的:
领导安排的内容,完成
项目的子模块开发完成

公司开发环境
公司内部的服务器,
特点:
服务器环境和线上的服务器环境完全一致

工作内容:
项目子模块间的功能联调

工作人员
开发团队所有人

最终目的:
项目开发完成
项目调试完成


测试环境:
公司内部的服务器,
特点:
服务器环境和线上的服务器环境完全一致

工作内容:
找茬

工作人员
测试团队

最终目的:
保证项目功能完备


预发布环境:
公司线上服务器组中的一台,
特点:
服务器环境和线上的服务器环境完全一致

工作内容:
1、支付类型的特殊功能
2、数据压力测试
3、其他安全措施

工作人员
运维团队

最终目的:
保证项目功能完备


线上环境
公司线上服务器组


工作内容:
代码部署

工作人员
运维团队

最终目的:
保证项目功能完备



2、代码发布
2.1 什么是部署
部署什么?
代码 经过测试,功能完善,没有问题的代码
部署到哪里?
服务器 所有人都能访问的到的一台服务器(有公网IP)
阿里云、亚马逊、腾讯云、华为云、....
部署的效果
web网页对外展示


2.2 部署方式
手工发布代码 步行

干扰因素多
不安全

脚本发布代码 坐车

干扰因素少
安全




2.3 部署流程
获取代码

代码仓库
集中式的
svn
分布式的
git

公司的代码仓库:
私有仓库 gitlab
内部服务器。或者公网服务器

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

代码权限:
开发、管理、查看

提交的方式:
代码版本号

打包代码:
目的:
减少传输文件数量
减小传输文件大小
增强传输速率

常见打包方式:
windows:
zip、rar...
linux:
tar、zip...

传输代码
传输方式:
有网情况下
git
ftp
scp
共享挂载 cp
rsync

没有网情况下
物理方式 
U盘或者硬盘


传输工具演示:
格式:
scp  要传输的文件 要放置的位置

将本地文件推送到远程主机
scp python10.tar.gz root@192.168.56.12:/root/
远程连接的用户@远程主机:远程主机的位置
将远程主机的文件拉取到本地
scp root@192.168.56.12:/root/python10.tar.gz ./



主机间免秘钥认证
1、生成秘钥对
ssh-keygen -t rsa
-t 指定秘钥的类型  
rsa 秘钥类型

秘钥目录:/root/.ssh/
私钥 id_rsa 钥匙
公钥 id_rsa.pub


2、编辑认证文件
root@admina-virtual-machine:~/.ssh# cat /root/.ssh/authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDdC36zf/x+K8BQx582r+uYx78NC6s24PljsnpL6mELJkcXEVvIQ49lWpeJJm58F9j73J3h342WeaW50HzkxvcZGOqdx/pOp6tphkqlIe3utnJlRYvhSmULGFMBC1C0dNWcU/igK28XYBe3Rwhzh43vb5cc2jh90Ef2iQTny2RzjT11B2pro02wGGdcPKRHQkVfHdCkPa1iFsL2YHuYDr8XPMCcfbLfNUUSugGq2VoqpmjdR+G1xXgoHnAucFUMwHVTeGXEDiqFd56fPeEHQ9cSeVAFiQeqKeiNLvjQ0LJCgIy4TEx1DTc//3ND9TQbCA6NZJt4zgNc19jqAdT/PVp root@admina-virtual-machine
注意:
认证文件内容和56.11机器的公钥文件内容一致
保证文件内容是一整行

3、编辑ssh配置文件
root@admina-virtual-machine:~/.ssh# cat /etc/ssh/sshd_config
...
AuthorizedKeysFile %h/.ssh/authorized_keys
注意:
直接取消该行的注释即可

4、配置文件生效
重启ssh服务
/etc/init.d/ssh restart

5、验证操作
ssh root@192.168.56.12


1和5是在56.11上操作
2-4是在56.12上操作

关闭应用
开启什么应用,就关闭什么应用

解压代码:
tar xf ...

放置代码
备份原文件
cp nihao nihao-`date +%Y%m%d%H%M%S`


放置新文件


注意:
两个文件的名称是一样的,只是内容不同
对整个应用项目来说,两个文件没有区别

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

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




时间戳生成示例:
root@admina-virtual-machine:~/.ssh# date +%D
09/28/17
root@admina-virtual-machine:~/.ssh# date +%F
2017-09-28
root@admina-virtual-machine:~/.ssh# date +%Y%m%d
20170928
root@admina-virtual-machine:~/.ssh# date +%T
03:06:30
root@admina-virtual-machine:~/.ssh# date +%H%M%S
030643
root@admina-virtual-machine:~/.ssh# date +%Y%m%d%H%M%S
20170928030742


开启应用
关闭什么应用就开启什么应用

检查
查看浏览器效果

ok


3、环境部署
3.1 准备工作
创建基本目录
root@admina-virtual-machine:/data# mkdir /data/{server,logs,backup,soft,virtual}
root@admina-virtual-machine:/data# ls /data/
backup  logs  scripts  server  soft  virtual
root@admina-virtual-machine:/data# mkdir /data/codes
查看
root@admina-virtual-machine:/data# tree -L 1 /data/ 
/data/
├── backup 备份
├── codes 代码
├── logs 日志
├── scripts 脚本
├── server 服务
├── soft 软件
└── virtual 虚拟环境
3.2 项目分析
需求:
部署一个环境,支持我们的django项目正常运行

分析:

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、整个项目调试


3.2 python虚拟环境
3.2.1 软件安装
apt-get install python-virtualenv -y

3.2.2 虚拟环境基本操作
创建 
virtualenv -p /usr/bin/python2.7 venv
进入
source venv/bin/activate
退出
deactivate
删除
rm -rf venv


3.3 django环境部署
3.3.1 django软件安装
解压
cd /data/soft
tar xf Django。。。
查看
cd Django...
cat INSTALL or README
安装
python setup.py install

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

编译:python setup.py build



3.3.2 django项目操作
创建
django-admin startproject hello






3.3.3 django应用操作
创建应用
python manager.py startapp test1
注册应用
hello/settings.py

INSTALL_APP = [
。。。
'test1',
]




3.3.4 view和url配置
view 配置文件生效
root@admina-virtual-machine:/data/soft# cat /data/server/hello/test1/views.py
from django.shortcuts import render
from django.http import HttpResponse


# Create your views here.


def hello(resquest):
  return HttpResponse("hello V1.0")


url文件配置
root@admina-virtual-machine:/data/soft# cat /data/server/hello/hello/urls.py
"""hello URL Configuration


The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
1. Add an import:  from my_app import views
2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
1. Add an import:  from other_app.views import Home
2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from test1.views import *


urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^hello/$', hello),
]


启动服务:
cd /data/server/hello
python  manager.py runserver



启动django
python manage.py runserver >> /dev/null 2>&1 &
关闭:
ps aux | grep python
kill 56491

问题:
django项目只能在本机查看

方案:
nginx、haproxy

优中选优
简单


3.4 nginx环境部署
3.4.1 pcre软件安装
解压
tar xf pcre...
查看帮助
cd pcre。。。
INSTALL 或者 README

配置
./configure

编译
make

安装
make install

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


3.4.2 nginx软件安装
解压
cd /data/soft/
tar xf nginx-1.10.2.tar.gz
配置
cd nginx-1.10.2/
./configure --prefix=/data/server/nginx --without-http_gzip_module

编译
make
安装
make install


3.4.3 nginx简单操作


检查
./sbin/nginx -t
开启
./sbin/nginx
关闭
./sbin/nginx -s stop

重载
./sbin/nginx -s reload



突发问题:
root@admina-virtual-machine:/data/server/nginx# ./sbin/nginx -t
./sbin/nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory


分析:
1、先看报错
2、思考,是否报错真实有效
分析: 谁错了

3、查找文件
全名找不到,我们使用正则
4、找到文件,我没有问题
nginx默认找库文件的路径有问题
5、解决



3.4.4 nginx代理django项目
nginx的目录结构
root@admina-virtual-machine:/data/server/nginx# tree -L 2 /data/server/nginx/
/data/server/nginx/
├── ...
├── conf 配置文件目录
│   ...
│   ├── nginx.conf 默认的配置文件
│   ...
├── ...
├── html 网页文件
│   ├── 50x.html
│   └── index.html
├── logs 日志目录
│   ├── access.log
│   └── error.log
├── ...
├── sbin 执行文件目录
│   └── nginx
├── ...

nginx配置文件介绍
全局配置段
http配置段
server配置段 项目或者应用
location配置段 url配置



需求:
127.0.0.1:8000/hello/


代理配置项
#location ~ \.php$ {
#    proxy_pass   http://127.0.0.1;
#}


编辑配置文件实现代理功能
配置内容
62: location /hello/ {
63: proxy_pass http://127.0.0.1:8000;
64: }

标准配置文件
root@admina-virtual-machine:/data/server/nginx# egrep -vn '#|^$' conf/nginx.conf
3:worker_processes  1;
12:events {
13:    worker_connections  1024;
14:}
17:http {
18:    include       mime.types;
19:    default_type  application/octet-stream;
27:    sendfile        on;
31:    keepalive_timeout  65;
35:    server {
36:        listen       80;
37:        server_name  localhost;
43:        location / {
44:            root   html;
45:            index  index.html index.htm;
46:        }
52:        error_page   500 502 503 504  /50x.html;
53:        location = /50x.html {
54:            root   html;
55:        }
62: location /hello/ {
63: proxy_pass http://127.0.0.1:8000;
64: }
81:    }
119:}

配置文件生效

3.5 调试


4、手工发布代码
需求:
手工方式部署代码
线上主机:56.11
代码仓库:56.12

方案:
获取代码
打包代码
传输代码
关闭应用
解压代码
放置代码
备份老文件
放置新文件
开启应用
检查


实践
获取代码
sed -i 's#1.0#1.1#' django/views.py 
sed -i 's#原内容#替换后内容#g' 文件
分隔符:# / @ 

打包代码
tar zcf django.tar.gz django
传输代码
scp root@192.168.56.12:/data/code/django.tar.gz ./
关闭应用
关闭nginx应用
/data/server/nginx/sbin/nginx -s stop

关闭django应用
根据端口查看进程号,
lsof -Pti :8000
杀死进程号
kill 56502

解压代码
cd /data/codes
tar xf django.tar.gz

放置代码
备份老文件
需求:备份的格式:
文件名-时间戳
时间戳:年月日时分秒
date +%Y%m%d%H%M%S

mv /data/server/hello/test1/views.py /data/backup/views.py-`date +%Y%m%d%H%M%S`

放置新文件
cd /data/codes
mv django/views.py /data/server/hello/test1/

开启应用
开启django应用
source /data/virtual/venv/bin/activate
cd /data/server/hello/
python manage.py runserver >> /dev/null 2>&1
deactivate

开启nginx应用
/data/server/nginx/sbin/nginx


检查
netstat -tnulp | grep :80


5、脚本发布代码
5.1 远程脚本编写
5.1.1 远程命令执行
56.11 让 56.12 执行命令
示例:
root@admina-virtual-machine:/data/server/hello# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0c:29:b7:e7:b7  
 inet addr:192.168.56.11  Bcast:192.168.56.255  Mask:255.255.255.0
 inet6 addr: fe80::20c:29ff:feb7:e7b7/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 RX packets:436193 errors:0 dropped:3 overruns:0 frame:0
 TX packets:232980 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:549035735 (549.0 MB)  TX bytes:20894523 (20.8 MB)


lo        Link encap:Local Loopback  
 inet addr:127.0.0.1  Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING  MTU:65536  Metric:1
 RX packets:1630 errors:0 dropped:0 overruns:0 frame:0
 TX packets:1630 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1 
 RX bytes:137717 (137.7 KB)  TX bytes:137717 (137.7 KB)


root@admina-virtual-machine:/data/server/hello# ssh root@192.168.56.12 "ifconfig"
eth0      Link encap:Ethernet  HWaddr 00:0c:29:f7:ca:d4  
 inet addr:192.168.56.12  Bcast:192.168.56.255  Mask:255.255.255.0
 inet6 addr: fe80::20c:29ff:fef7:cad4/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
 RX packets:9732 errors:0 dropped:3 overruns:0 frame:0
 TX packets:6918 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000 
 RX bytes:884755 (884.7 KB)  TX bytes:822817 (822.8 KB)


lo        Link encap:Local Loopback  
 inet addr:127.0.0.1  Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING  MTU:65536  Metric:1
 RX packets:306051 errors:0 dropped:0 overruns:0 frame:0
 TX packets:306051 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1 
 RX bytes:23417793 (23.4 MB)  TX bytes:23417793 (23.4 MB)

5.1.2 远程脚本编写
1、实现简单的功能--- 简单的命令罗列
root@admina-virtual-machine:/data/scripts# cat tar_code.sh 
#!/bin/bash
# 功能:打包代码
# 脚本名:tar_code.sh
# 作者:python 13期全体
# 版本:V 0.1
# 联系方式:长安街1号 太和殿旁边 中南海1号厅


cd /data/code
[ -f django.tar.gz ] && rm -f django.tar.gz
tar zcf django.tar.gz django

2、 脚本优化之 固定内容变量化
root@admina-virtual-machine:/data/scripts# cat tar_code.sh 
#!/bin/bash
# 功能:打包代码
# 脚本名:tar_code.sh
# 作者:python 13期全体
# 版本:V 0.2
# 联系方式:长安街1号 太和殿旁边 中南海1号厅


FILE='django.tar.gz'
CODE_DIR='/data/code'
CODE_PRO='django'

cd "${CODE_DIR}"
[ -f "${FILE}" ] && rm -f "${FILE}"
tar zcf "${FILE}" "${CODE_PRO}"

3、脚本优化之 功能函数化
root@admina-virtual-machine:/data/scripts# cat tar_code.sh 
#!/bin/bash
# 功能:打包代码
# 脚本名:tar_code.sh
# 作者:python 13期全体
# 版本:V 0.3
# 联系方式:长安街1号 太和殿旁边 中南海2号厅


FILE='django.tar.gz'
CODE_DIR='/data/code'
CODE_PRO='django'

code_tar(){
cd "${CODE_DIR}"
[ -f "${FILE}" ] && rm -f "${FILE}"
tar zcf "${FILE}" "${CODE_PRO}"
}
code_tar

5.2 部署脚本编写
5.2.1 脚本框架
需求:先将脚本所设计的所有业务流程跑通

方案:
使用函数来体现

脚本实施:
#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:python 13期全体
# 版本:V 0.1
# 联系方式:长安街1号 太和殿旁边 国务院1号厅


# 打包代码
tar_code(){
echo "打包代码"
}


# 传输代码
scp_code(){
echo "传输代码"
}


# 关闭应用
serv_stop(){
echo "关闭nginx应用"
echo "关闭django应用"
}


# 解压代码
untar_code(){
echo "解压代码"
}


# 放置代码
fangzhi_code(){
echo "放置代码"
}


# 开启应用
serv_star(){
echo "开启django应用"
echo "开启nginx应用"
}


# 检查
check(){
echo "检查"
}


main(){
tar_code
scp_code
serv_stop
untar_code
fangzhi_code
serv_star
check
}


main



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

方案:
在流程框架中,填写执行没有任何问题的命令

脚本实施:

#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:python 13期全体
# 版本:V 0.2
# 联系方式:长安街1号 太和殿旁边 国务院2号厅


# 打包代码
tar_code(){
echo "打包代码"
ssh root@192.168.56.12 "/bin/bash /data/scripts/tar_code.sh"
}


# 传输代码
scp_code(){
echo "传输代码"
cd /data/codes/
[ -f django.tar.gz ] && rm -f django.tar.gz
[ -d django ] && rm -rf django
scp root@192.168.56.12:/data/code/django.tar.gz ./
}


# 关闭应用
serv_stop(){
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 "备份原文件"
mv /data/server/hello/test1/views.py /data/backup/views.py-`date +%Y%m%d%H%M%S`
echo "放置新文件"
mv /data/codes/django/views.py /data/server/hello/test1/
}


# 开启应用
serv_star(){
echo "开启django应用"
source /data/virtual/venv/bin/activate
cd /data/server/hello/
python manage.py runserver >> /dev/null 2>&1 &
deactivate
echo "开启nginx应用"
/data/server/nginx/sbin/nginx
}


# 检查
check(){
echo "检查"
netstat -tnulp | grep :80
}


main(){
tar_code
scp_code
serv_stop
untar_code
fangzhi_code
serv_star
check
}


main


5.2.3 增加日志功能
需求:
1、追踪记录
2、数据说话

方案:
增加日志功能
1、日志文件
/data/logs/deploy.log
2、日志格式
日期 时间 脚本名称 步骤

日期:date +%F
时间:date +%T
脚本:$0

脚本实施:
#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:python 13期全体
# 版本:V 0.3
# 联系方式:长安街1号 太和殿旁边 国务院3号厅


LOG_FILE='/data/logs/deploy.log'


# 增加日志功能
write_log(){
  log_date='date +%F'
  log_time='date +%T'
  buzhou="$1"
  
  echo "${log_date}  ${log_time}  $0  ${buzhou}" >> "${LOG_FILE}"
}


# 打包代码
tar_code(){
echo "打包代码"
ssh root@192.168.56.12 "/bin/bash /data/scripts/tar_code.sh"
write_log "打包代码"
}


# 传输代码
scp_code(){
echo "传输代码"
cd /data/codes/
[ -f django.tar.gz ] && rm -f django.tar.gz
[ -d django ] && rm -rf django
scp root@192.168.56.12:/data/code/django.tar.gz ./
write_log "传输代码"
}


# 关闭应用
serv_stop(){
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 "解压代码"
}


# 放置代码
fangzhi_code(){
echo "备份原文件"
mv /data/server/hello/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/hello/test1/
write_log "放置新文件"
}


# 开启应用
serv_star(){
echo "开启django应用"
source /data/virtual/venv/bin/activate
cd /data/server/hello/
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 "检查"
}


main(){
tar_code
scp_code
serv_stop
untar_code
fangzhi_code
serv_star
check
}


main

5.2.4 增加锁文件功能
需求:
同一时间段内,只允许有一个用户来执行这个脚本
如果脚本执行的时候,有人在执行,那么输入报错:改脚本正在运行......

设计:
锁文件 /tmp/deploy.pid
脚本执行的时候,需要创建锁文件
脚本执行结束的时候,需要删除锁文件

脚本实施
#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:python 13期全体
# 版本:V 0.4
# 联系方式:长安街1号 太和殿旁边 国务院4号厅


LOG_FILE='/data/logs/deploy.log'


# 增加锁文件
add_lock(){
echo "增加锁文件"
touch /tmp/deploy.pid
write_log "增加锁文件"
}


# 删除锁文件
del_lock(){
echo "删除锁文件"
rm -f /tmp/deploy.pid
write_log "删除锁文件"
}


# 增加日志功能
write_log(){
  log_date='date +%F'
  log_time='date +%T'
  buzhou="$1"
  
  echo "${log_date}  ${log_time}  $0  ${buzhou}" >> "${LOG_FILE}"
}


# 打包代码
tar_code(){
echo "打包代码"
ssh root@192.168.56.12 "/bin/bash /data/scripts/tar_code.sh"
write_log "打包代码"
}


# 传输代码
scp_code(){
echo "传输代码"
cd /data/codes/
[ -f django.tar.gz ] && rm -f django.tar.gz
[ -d django ] && rm -rf django
scp root@192.168.56.12:/data/code/django.tar.gz ./
write_log "传输代码"
}


# 关闭应用
serv_stop(){
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 "解压代码"
}


# 放置代码
fangzhi_code(){
echo "备份原文件"
mv /data/server/hello/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/hello/test1/
write_log "放置新文件"
}


# 开启应用
serv_star(){
echo "开启django应用"
source /data/virtual/venv/bin/activate
cd /data/server/hello/
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 "检查"
}


main(){
if [ -f /tmp/deploy.pid ]
then
echo "脚本 $0 正在运行中....."
exit
else
add_lock
tar_code
scp_code
serv_stop
untar_code
fangzhi_code
serv_star
check
del_lock
fi
}


main






5.2.5 脚本流程知识点填充
需求:
如果我给脚本出入的参数是deploy,那么我才执行
方案;
1、脚本的传参
2、位置参数的调用
3、case流程语句的使用

输出帮助信息:
脚本 $0 的使用方式: $0 [ deploy ]

脚本实施
#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:python 13期全体
# 版本:V 0.5
# 联系方式:长安街1号 太和殿旁边 国务院5号厅


LOG_FILE='/data/logs/deploy.log'


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


# 增加锁文件
add_lock(){
echo "增加锁文件"
touch /tmp/deploy.pid
write_log "增加锁文件"
}


# 删除锁文件
del_lock(){
echo "删除锁文件"
rm -f /tmp/deploy.pid
write_log "删除锁文件"
}


# 增加日志功能
write_log(){
  log_date='date +%F'
  log_time='date +%T'
  buzhou="$1"
  
  echo "${log_date}  ${log_time}  $0  ${buzhou}" >> "${LOG_FILE}"
}


# 打包代码
tar_code(){
echo "打包代码"
ssh root@192.168.56.12 "/bin/bash /data/scripts/tar_code.sh"
write_log "打包代码"
}


# 传输代码
scp_code(){
echo "传输代码"
cd /data/codes/
[ -f django.tar.gz ] && rm -f django.tar.gz
[ -d django ] && rm -rf django
scp root@192.168.56.12:/data/code/django.tar.gz ./
write_log "传输代码"
}


# 关闭应用
serv_stop(){
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 "解压代码"
}


# 放置代码
fangzhi_code(){
echo "备份原文件"
mv /data/server/hello/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/hello/test1/
write_log "放置新文件"
}


# 开启应用
serv_star(){
echo "开启django应用"
source /data/virtual/venv/bin/activate
cd /data/server/hello/
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 "检查"
}


main(){
case "$1" in
"deploy")
if [ -f /tmp/deploy.pid ]
then
echo "脚本 $0 正在运行中....."
exit
else
add_lock
tar_code
scp_code
serv_stop
untar_code
fangzhi_code
serv_star
check
del_lock
fi
;;
*)
usage
;;
esac
}


main $1



5.2.6 输入参数安全优化
需求:
对脚本传入的参数进行判断,如果传入的参数数量不对,直接提示脚本使用方式,然后退出

方案:
条件表达式 + $# 

脚本实施
#!/bin/bash
# 功能:打包代码        
# 脚本名:deploy.sh     
# 作者:python 13期全体 
# 版本:V 0.6
# 联系方式:长安街1号 太和殿旁边 国务院6号厅


LOG_FILE='/data/logs/deploy.log'




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


[ "$#" -eq 1 ] || usage
...



5.2.7 脚本调试功能

-x

示例:
root@admina-virtual-machine:/data/scripts/python10# bash -x while.sh 
+ a=1
+ '[' 1 -lt 5 ']'
+ echo 1
1
+ a=2
+ '[' 2 -lt 5 ']'
+ echo 2
2
+ a=3
+ '[' 3 -lt 5 ']'
+ echo 3
3
+ a=4
+ '[' 4 -lt 5 ']'
+ echo 4
4
+ a=5
+ '[' 5 -lt 5 ']'



5.3 生产脚本编写总结
5.3.1 简单脚本编写总结
1、命令简单罗列
2、固定的内容变量化
3、功能函数化


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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

InfluxDB安装及使用

1 安装 1.1 Tar包安装 &#xff08;1&#xff09;获取tar包 wget https://dl.influxdata.com/influxdb/releases/influxdb-1.8.0_linux_amd64.tar.gz&#xff08;2&#xff09;解压tar包   tar xvfz influxdb-1.8.0_linux_amd64.tar.gz $ su - tigk $ tar xvfz /opt/packa…

倒排索引原理和实现

关于倒排索引 搜索引擎通常检索的场景是&#xff1a;给定几个关键词&#xff0c;找出包含关键词的文档。怎么快速找到包含某个关键词的文档就成为搜索的关键。这里我们借助单词——文档矩阵模型&#xff0c;通过这个模型我们可以很方便知道某篇文档包含哪些关键词&#xff0c;某…

天池 在线编程 Character deletion

文章目录1. 题目2. 解题1. 题目 描述 Enter two strings and delete all characters in the second string from the first string 字符串长度&#xff1a;[1, 10^5] Example 1: Input: str”They are students”&#xff0c;sub”aeiou” Output: ”Thy r stdnts”来源&am…

【翻译】在Ext JS中创建特定主题的重写

Ext JS提供了大量的功能来使类的创建和处理变得简单&#xff0c;还提供了一系列的功能来扩展和重新现有的Javascript类。这意味着可以为类添加行为和创建属于自己的类&#xff0c;或者重写某些函数的行为。在本文&#xff0c;将展示如何实现特定主题类的重写。原文&#xff1a;…

Kapacitor安装及使用

1 安装 1.1 Tar包安装 &#xff08;1&#xff09;下载 wget https://dl.influxdata.com/kapacitor/releases/kapacitor-1.5.5_linux_amd64.tar.gz&#xff08;2&#xff09;安装 $ tar xvfz /opt/package/kapacitor-1.5.5-static_linux_amd64.tar.gz -C /home/tigk/.local/ …

Python答题:LinteCode简单题库(一)

366. 斐波纳契数列&#xff1a;查找斐波纳契数列中第 N 个数。 所谓的斐波纳契数列是指&#xff1a; 前2个数是 0 和 1 。 第 i 个数是第 i-1 个数和第i-2 个数的和。 斐波纳契数列的前10个数字是&#xff1a; 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ... 给定 1&#xff0c;返回 …

天池 在线编程 扫雷(BFS)

文章目录1. 题目2. 解题1. 题目 描述 现在有一个简易版的扫雷游戏&#xff0c;你将得到一个n*m大小的二维数组作为游戏地图。 每个位置上有一个值&#xff08;0或1&#xff0c;1代表此处没有雷&#xff0c;0表示有雷&#xff09;。 你将获得一个起点的位置坐标&#xff08;x&a…

Linux搭建高并发高可用Redis集群

安装Redis Redis 是一个高性能的key-value数据库。常用作缓存服务器使用。 1. 下载redis安装包&#xff0c;redis-3.2.11.tar.gz&#xff08;http://download.redis.io/releases/redis-3.2.11.tar.gz&#xff09; > wget http://download.redis.io/releases/redis-3.2.11.…

Flink简介

1 什么是Flink Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算。 它的主要特性包括&#xff1a;批流一体化、精密的状态管理、事件时间支…

Winform datagridview相关操作

datagridview显示行号的2种方法: 方法一&#xff1a; 网上最常见的做法是用DataGridView的RowPostPaint事件在RowHeaderCell中绘制行号&#xff1a; privatevoiddataGridView1_RowPostPaint(objectsender, DataGridViewRowPostPaintEventArgs e){try{e.Graphics.DrawString((e.…

天池 在线编程 旅行计划(暴力回溯)

文章目录1. 题目2. 解题1. 题目 描述 有n个城市&#xff0c;给出邻接矩阵arr代表任意两个城市的距离。 arr[i][j]代表从城市i到城市j的距离。Alice在周末制定了一个游玩计划&#xff0c;她从所在的0号城市开始&#xff0c;游玩其他的1 ~ n-1个城市&#xff0c;最后回到0号。 A…

初始化环境配置:CentOS 7.4x64 系统安装及基础配置

1.安装CentOS操作系统 ① 在进入系统引导后&#xff0c;会进入文字界面&#xff0c;选择install CentOS7 &#xff08;用键盘上的方向键↑、↓来选择要执行的操作&#xff0c;白色字体表示选中&#xff0c;按下回车&#xff0c;进入下一步操作&#xff09; ② 按回车执行安…

天池 在线编程 拿走瓶子(区间DP)

文章目录1. 题目2. 解题1. 题目 描述 有n个瓶子排成一列&#xff0c;用arr表示。 你每次可以选择能够形成回文连续子串的瓶子拿走&#xff0c;剩下的瓶子拼接在一起。 返回你能拿走所有的瓶子的最小次数。 n<500 arr[i]<1000示例 例1: 输入&#xff1a;[1,3,4,1,5] …

Flink运行时架构

1 运行时相关的组件 Flink运行时架构主要包括四个不同的组件&#xff1a;作业管理器&#xff08;JobManager&#xff09;、资源管理器&#xff08;ResourceManager&#xff09;、任务管理器&#xff08;TaskManager&#xff09;&#xff0c;以及分发器&#xff08;Dispatcher&a…

大型网站电商网站架构案例和技术架构的示例

大型网站架构是一个系列文档&#xff0c;欢迎大家关注。本次分享主题&#xff1a;电商网站架构案例。从电商网站的需求&#xff0c;到单机架构&#xff0c;逐步演变为常用的&#xff0c;可供参考的分布式架构的原型。除具备功能需求外&#xff0c;还具备一定的高性能&#xff0…

Spring JPA

http://files.cnblogs.com/weishuai90/spring.rar转载于:https://www.cnblogs.com/weishuai90/p/3567794.html

天池 在线编程 删除字符(单调栈)

文章目录1. 题目2. 解题1. 题目 描述 给定一个字符串str&#xff0c;现在要对该字符串进行删除操作&#xff0c; 保留字符串中的 k 个字符且相对位置不变&#xff0c;并且使它的字典序最小&#xff0c;返回这个子串。 示例 例1: 输入:str"fskacsbi",k2 输出:&quo…

Flink常见流处理API

Flink 流处理API的编程可以分为environment&#xff0c;source&#xff0c;transform&#xff0c;sink四大部分 1 Flink支持的数据类型 在Flink底层因为要对所有的数据序列化&#xff0c;反序列化对数据进行传输&#xff0c;以便通过网络传送它们&#xff0c;或者从状态后端、…

Flask框架项目实例:**租房网站(二)

Flask是一款MVC框架&#xff0c;主要是从模型、视图、模板三个方面对Flask框架有一个全面的认识&#xff0c;通过完成作者-读书功能&#xff0c;先来熟悉Flask框架的完整使用步骤。 操作步骤为&#xff1a; 1.创建项目2.配置数据库3.定义模型类4.定义视图并配置URL 5.定义模板…

Android中的APK,TASK,PROCESS,USERID之间的关系

开发Android已经有一段时间了&#xff0c;今天接触到底层的东西&#xff0c;所以对于进程&#xff0c;用户的id以及Android中的Task,Apk之间的关系&#xff0c;要做一个研究&#xff0c;下面就是研究结果: apk一般占一个dalvik,一个进程,一个task。当然通过通过设置也可以多个进…