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日志并进行多维度分析。
相关文章
|
7月前
|
存储 Unix Shell
Shell
Shell
39 0
|
2月前
|
Unix Shell Linux
Shell
【10月更文挑战第15天】
20 3
|
安全 Shell Linux
强大好用的shell:什么是shell?
系统内核是操作系统的基本组成部分,它负责管理系统的硬件和软件资源,并提供一组基本的系统服务。内核是操作系统的核心,控制着计算机的所有主要功能,包括内存管理、进程管理、设备驱动程序、系统调用和安全防护等。内核在计算机中扮演着重要的角色,它为用户空间的应用程序提供访问硬件资源的接口,并通过进程间通信机制及系统调用来完成这些操作。内核的设计和实现对于操作系统的性能和稳定性有着至关重要的影响。
|
机器学习/深度学习 Shell Linux
shell
shell
90 0
|
Shell Linux Perl
|
Shell Windows 监控