shell(二)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: shell(二)

每日分享

The death of a dream is the day that you stop believing in the work it takes to get there.

不再相信自己能够成功,就是梦想破碎的时刻。

小闫语录

支撑一个人前进的,莫过于信念。因为坚信黎明的曙光,所以未曾害怕黑暗。因为心中有你,所以前路尽是温暖。


shell(二)

1.shell流程控制

1.1简单流程控制语句

1.1.1if判断语句

首先我们通过一个示例来展示单分支if语句:

需求:如果输入的参数为 man,那么输出您的性别为男。

#!/bin/bash
if [ "$1" == "man" ]
then
    echo "您的性别是:男"
fi

我们执行上面的脚本文件:

ethanyan@ethanyan-PC:~$ bash if_test.sh man
您的性别是:男

我们可以通过一个条件的判断,得到不同情况下的结果吗?可以。下面我们就通过一个例子展示双分支if语句:

需求:输入参数 man,输出您的性别为男,否则输出女性。

#!/bin/bash
if [ "$1" == "man" ]
then
    echo "您的性别是:男"
else
    echo "您的性别是:女"
fi

我们执行一下这个脚本文件:

ethanyan@ethanyan-PC:~$ bash if_test.sh man
您的性别是:男
ethanyan@ethanyan-PC:~$ bash if_test.sh woman
您的性别是:女

既然有单分支和双分支语句了,那么有多分支语句吗,就好像 elif这种判断?有。下面我们就通过一个例子展示多分支if语句:

需求:输入参数 man,输出您的性别为男;输入参数 woman,输出女;输入其他,输出不知道。

#!/bin/bash
if [ "$1" == "man" ]
then
    echo "您的性别是:男"
elif [ "$1" == "woman" ]
then
    echo "您的性别是:女"
else
    echo "您的性别,臣妾猜不到啊~"
fi

我们执行脚本文件:

ethanyan@ethanyan-PC:~$ bash if_test.sh 
您的性别,臣妾猜不到啊~
ethanyan@ethanyan-PC:~$ bash if_test.sh man
您的性别是:男
ethanyan@ethanyan-PC:~$ bash if_test.sh woman
您的性别是:女
综合示例-服务器

需求:我们通过传入的参数不同,实现不同的功能。

参数 执行效果
start 服务器启动中...
stop 服务器关闭中...
restart 服务器重启中...

脚本文件为:

ethanyan@ethanyan-PC:~$ bash if_test.sh stop
服务其正在关闭...
ethanyan@ethanyan-PC:~$ bash if_test.sh start
服务器正在启动...
ethanyan@ethanyan-PC:~$ bash if_test.sh restart
服务器正在重启...
ethanyan@ethanyan-PC:~$ bash if_test.sh 
脚本执行方式:bash if_test.sh [ start | stop | restart ]

1.1.2case选择语句

你有可能说:上面的if判断语句代码量有点多啊。那么我们就来简化一下,用到的就是 case选择语句。

我们还是以上面的综合案例为例,进行改写。脚本文件如下:

#!/bin/bash
case "$1" in 
    "start")
        echo "服务器正在启动..."
        ;;
    "stop")
        echo "服务器正在关闭..."
        ;;
    "restart")
        echo "服务正在重启..."
        ;;
    *)
        echo "脚本的使用方法:bash $0 [ start | stop | restart ]"
        ;;
esac

我们执行上面的脚本文件:

1. ethanyan@ethanyan-PC:~$ bash case_test.sh stop
2. 服务器正在关闭...
3. ethanyan@ethanyan-PC:~$ bash case_test.sh start
4. 服务器正在启动...
5. ethanyan@ethanyan-PC:~$ bash case_test.sh restart
6. 服务正在重启...
7. ethanyan@ethanyan-PC:~$ bash case_test.sh 
8. 脚本的使用方法:bash case_test.sh [ start | stop | restart ]
1.1.3for循环语句

需求:循环遍历当前文件夹下的文件。

#!/bin/bash
for i in $(ls ./)
do
    echo "${i}"
done

执行结果:

ethanyan@ethanyan-PC:~$ bash for_test 
case_test.sh
for_test.sh
if_test.sh
...

1.1.4while循环语句

格式

while 条件
do
   执行语句
done

注意:条件的类型:命令、[[ 字符串表达式 ]]、(( 数字表达式 ))

示例:a初始值为1,不断 +1操作,直到a不小于5为止。

#!/bin/bash
a=1
while [ "${a}" -lt 5 ]
do
    echo "${a}"
    a=$((a+1))
done

执行上面的脚本文件:

ethanyan@ethanyan-PC:~$ bash while.sh 
1
2
3
4

1.1.5until循环语句

格式

until 条件
do
   执行语句
done

注意:条件的类型:命令、[[ 字符串表达式 ]]、(( 数字表达式 ))

示例:a初始值为1,不断进行 +1操作,直到a等于5为止。

#!/bin/bash
a=1
until [ "${a}" -eq 5 ]
do
    echo "${a}"
    a=$((a+1))
done

执行上面的脚本:

ethanyan@ethanyan-PC:~$ bash util.sh 
1
2
3
4

2.函数

2.1简单函数

先来一个简单的函数,无参数。用于执行频繁的指令。我们封装一些常用指令,只需调用函数即可。

  1. #
!/bin/bash
# 定义函数
func1(){
    echo "my name is ethanyan"
}
# 调用函数
func1
:<<!
我们可以在函数中封装常用指令
此处只是做一个简单的示例
!

执行上面的脚本:

ethanyan@ethanyan-PC:~$ bash fun1.sh 
my name is ethanyan

注意:在调用函数的时候没有括号。脚本文件中所有的标点符号均为英文状态下。

2.2函数传参

实现函数传参和函数体内调用参数,脚本文件示例:

#!/bin/bash
func2(){
    echo "my name is $1"
}
# 调用函数并传参
func2 ethanyan

执行脚本文件:

ethanyan@ethanyan-PC:~$ bash func2.sh 
my name is ethanyan

2.3脚本传参

实现脚本传参,函数调用。脚本文件示例:

#!/bin/bash
func3(){
    echo "my name is $1"
}
func3 $1

执行脚本:

ethanyan@ethanyan-PC:~$ bash func3.sh ethanyan
my name is ethanyan

还有一种脚本传参的方式,这种情况在生产环境下使用:

#!/bin/bash
name="$1"
func4(){
    echo "my name is $1"
}
func4 "${name}"

执行脚本:

ethanyan@ethanyan-PC:~$ bash func4.sh ethanyan
my name is ethanyan

3.linux命令回顾

3.1压缩与解压缩-gz

文件压缩:

tar -zcvf 压缩后的文件名 压缩的文件

文件解压到当前路径:

tar -zxvf 要解压的文件
参数 作用
z 指定压缩文件的格式为 tar.gz
c 压缩
v 显示详细过程
f 指定压缩文件
x 解压

查看压缩文件内容:

  1. zcat 压缩文件

上面压缩与解压缩的格式为常用的 gz压缩格式。当然还有 zipbz2两种格式。

3.2文件传输

将本地的文件推送到远程的服务器:

  1. scp 本地文件名用户名@ip:远程目录

将远程服务器上的文件拉取到本地:

  1. scp 用户名@ip:远程文件本地目录

如果传输的是目录,不是文件,需要指定参数 -r,如下:

  1. scp -r 本地目录名用户名@ip:远程目录

3.3文件备份

可以使用 cp命令来进行操作,但是为了避免放置新文件的时候,出现验证操作,常采用 mv命令,如下:

  1. mv test.txt test-$(date +%Y%m%d%H%M%S)

此处是将文件直接重命名而已,加了一个时间戳。当然你可以采用压缩进行备份;或者将文件复制一份,一份作为备份一份继续使用。根据场景自己选择。

3.3.1date命令:

格式

  1. date [option]
参数 作用
%F 显示当前日期格式,%Y-%m-%d
%T 显示当前时间格式,%H:%M:%S

使用效果:

ethanyan@ethanyan-PC:~$ date +%F
2019-04-05
ethanyan@ethanyan-PC:~$ date +%T
15:58:06

当然我们在给文件加时间戳的时候,希望是一串数字,没有特殊符号。下面代码即可实现:

date命令获取的都是当前系统的时间。

ethanyan@ethanyan-PC:~$ date +%Y%m%d
20190405  # 显示年月日
ethanyan@ethanyan-PC:~$ date +%H%M%S
160301    # 显示时分秒
ethanyan@ethanyan-PC:~$ date +%Y%m%d%H%M%S
20190405160403  # 显示年月日时分秒

4.环境部署

4.1基础目录环境

为了方便项目管理,需要创建基础环境目录。

起名要做到见名知意。

下面举一个例子:

1.创建基本目录:

  1. mkdir ./data/{server,logs,backup,softs,virtual,scripts,codes}-p

-p为创建层级目录。

2.查看创建的目录结构:

ethanyan@ethanyan-PC:~$ tree -L 1 ./data/
./data/
├── backup    # 备份
├── codes    # 代码
├── logs    # 日志
├── scripts    # 脚本文件
├── server    # 服务
├── softs    # 软件
└── virtual    # 虚拟环境

tree命令需要安装,用来查看目录树状结构。 -L参数指定显示的层级,我们指定为显示1层。

4.2免密登录设置

我们在与主机进行文件传输的时候,每次链接都会进行密码验证,如果是手工的话,可以登录。自动化部署的时候,脚本却无能为力。那么有什么办法吗?答案就是进行免密钥认证操作。

方案思路

1.本机生成密钥对;

2.对端机器使用公钥文件认证;

3.验证。

方案实施

1.在本机生成密钥对:

  1. ssh-keygen -t rsa
  • -t:指定密钥类型。
  • rsa:密钥类型。

密钥目录:

  1. /root/.ssh/
  • id_rsa:私钥。
  • id_rsa.pub:公钥。

2.将 .pub公钥文件复制到对端机器的目录中,并改名为 authorized_keys,文件路径展示:

  1. /root/.ssh/authorized_keys

3.在对端机器中,编辑 ssh配置文件:

  1. /etc/ssh/sshd_config

将下面一行的注释取消掉:

  1. AuthorizedKeysFile    %h/.ssh/authorized_keys

4.在对端机器重启ssh服务:

  1. /etc/init.d/ssh restart

5.在本机进行连接,验证操作:

  1. ssh root@192.168.8.15

4.3方案分析

需求:部署一个环境,支持django项目正常运行。

需求分析,部署方案

1.进行django环境部署:

1.1 python虚拟环境
1.2 django环境部署
    1.2.1 django软件安装
    1.2.2 项目基本操作
    1.2.3 应用基本操作
    1.2.4 view和url配置
    1.2.5问题:只有本机才能访问
    1.2.6方案代理 --> nginx

2.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.项目调试:

3.1 启动软件
    3.1.1 启动django
    3.1.2 启动nginx
3.2 整个项目调试

最后就是根据方案对项目进行部署。

5.生产脚本

5.1大型脚本编写

一般的脚本大家都会写了,那么对于线上服务器的大型脚本是如何实现的呢?我们先来看一下流程:

1.编写脚本框架。 (处处有框架,脚本也不例外,但是此框架需要自己实现)

2.用命令对脚本框架进行填充。

3.完善功能(增加日志功能;增加锁文件功能;增加主函数逻辑;增加参数安全措施)。

下面是编写一个简单的脚本框架,大家可以仿照书写:

#!/bin/bash
# 功能:打包代码
# 脚本名:deploy.sh
# 作者:ethanyan
# 版本:V 0.1
# 联系方式:donnotcallme@163.com
# 获取代码
get_code(){
  echo "获取代码"
}
# 打包代码
tar_code(){
  echo "打包代码"
}
# 传输代码
scp_code(){
  echo "传输代码"
}
# 关闭应用
stop_serv(){
  echo "关闭应用"
  echo "关闭nginx应用"
  echo "关闭django应用"
}
# 解压代码
untar_code(){
  echo "解压代码"
}
# 放置代码
lay_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
  lay_code
  start_serv
  check
}
# 主函数
main(){
  deploy_pro
}
# 执行主函数
main

剩下的大家可以填充,完善等。

5.2生产脚本编写总结

  • 生产简单脚本的编写流程:命令可执行-命令罗列-内容变量-功能函数-远程执行。
  • 生产大型脚本的编写流程:脚本框架-命令填充-安全完善。
  • 大型脚本的安全功能完善:由内到外,功能安全-流程安全。
  • 掌握 脚本调试方法 语法-n ,追踪-x。

5.2.1简单脚本编写

  • 手工执行的命令一定要可执行。
  • 命令简单罗列。
  • 固定的内容变量化。
  • 功能函数化。

5.2.2复杂脚本编写

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

5.2.3注意事项

  • 命令一定要保证能正常执行。
  • 成对的符号,要成对写,避免丢失。
  • 函数调用。写好函数后,一定要在主函数中进行调用。
  • 避免符号出现中文。
  • 命令变量的写法一定要规范。
  • 固定的内容一定要变量实现,方便以后更改。
  • 日志的输出。
  • 脚本的传参和函数的传参要区别对待。
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
6月前
|
Shell Linux
什么是shell?
什么是shell?
121 0
|
1天前
|
Shell
Shell是什么?
2. Shell Shell是用户与操作系统之间的交互界面,接受用户命令并将其传递给内核执行。Shell可以是命令行界面(CLI)或图形用户界面(GUI)。其主要作用包括: 命令解释:解析用户输入的命令。 脚本执行:运行Shell脚本,实现自动化任务。 程序启动:根据用户命令启动应用程序。 环境管理:配置和管理用户环境变量。
7 2
|
监控 关系型数据库 MySQL
我们一起来学Shell - 初识shell 1
我们一起来学Shell - 初识shell
92 2
我们一起来学Shell - 初识shell 1
|
11月前
|
Unix Shell
Shell 联机帮助
Shell 联机帮助
52 0
|
11月前
|
Shell 程序员
Shell 替代
Shell 替代
39 0
|
Shell Unix