Linux系统从入门到精通!第四天(shell编程和Docker)

三、Shell编程

Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的系统级程序。用户可以使用Shell来启动,挂起,停止甚至编写一些程序,Shell命令解释器的结构图:


1. 编写Shell脚本

(1)Shell脚本的格式

① 脚本文件必须以"#!/bin/bash"开头

② 脚本文件的文件名以.sh结尾

③ 脚本文件必须具有可执行权限(这样我们能够通过"./shell.sh"来执行脚本文件),当然如果脚本文件没有可执行权限,可以使用"sh shell.sh"的方式来执行。

  1. 第一个Shell脚本程序

3. Shell中的变量

Shell中的变量主要分为系统变量和用户自定义变量

(1)系统变量诸如:HOME、PWD、SHELL、USER等等,可以通过set命令来查看系统变量,系统变量是全局的变量,这意味着任何一个Shell程序都可以已使用这些变量,而系统变量就是我们常说的环境变量。

示例:

(2)自定义变量(只能在当前Shell脚本中使用)

① 语法:

  1. 定义变量:变量名=值(注意:"="左右不能有空格)

  2. 撤销变量:unset 变量名

  3. 声明静态变量:readonly 变量名(注意:静态变量不能unset)

② 变量的定义规则

  1. 变量由字母、数字、下划线组成,不能以数字开头

  2. 等号两侧不能有空格

  3. 变量名习惯大写

示例:

我们也可以将自定义变量提升为全局变量(环境变量)供其他的Shell脚本使用,语法:export 自定义变量名

③ 将命令的执行结果赋值给变量,有两种语法:

  1. 反引号方式:A=`ls -la` #将"ls -la"执行结果赋值给A变量

  2. 小括号方式:A=$(ls -la) #将"ls -la"执行结果赋值给A变量

示例:

④ 设置环境变量:比如我们将某个可执行程序的目录配置成环境变量之后,以后我们就不用每次都进入该目录才能执行程序,在任何一个目录下都能直接执行程序,因为路径配置环境变量后,任何Shell能都识别到。

  1. 语法:

a. export 变量名=变量值(功能描述:将Shell变量输出为环境变量,以便其他Shell脚本也能使用)

b. source 配置文件(功能描述:让修改之后的配置生效)

c. echo $变量名(功能描述:查询环境变量的值)

示例:配置Tomcat的环境变量

1)将Tomcat目录拷贝到/usr/local目录(/usr目录相当于就是Windows中的Program Files目录)

2)修改/etc/profile配置文件(需要root用户)

vi /etc/profile

3)让配置文件立即生效:source /etc/profile

4)系统启动的时候,会去家目录中读取一个隐藏文件.bashrc,我们需要在该配置文件中加上一句:source /etc/profile,系统启动时,让配置文件配置的环境变量生效。

5)验证:在任何目录下都可以访问Tomcat的bin目录中的程序了

(3)位置参数变量

n,n为数字,0表示命令本身,1-9表示命令后面跟的第1个到第9个参数,第10个参数以上用大括号括起来,例如${10}

示例:

② $*,代表命令行中的参数,但是它将这些参数看成是一个整体,如果循环遍历,只会遍历一次。

③ $@,也代表命令行中的参数,但是它将每一个参数看成是单独的个体,如果循环遍历,有多少个参数,就会遍历多少次。

示例:

vi param2.sh

(4)预定义变量

① $?,最后一次执行的命令的返回状态,如果是0,表示命令正确执行,非0,命令执行不正确。

② $$,代表当前进程的进程号(PID)

③ $!,代表后台运行的最后一个进程的进程号(PID)

示例:

vi prevar.sh

4. 运算符

语法:有两种

第一种:$[运算表达式]

第二种:`expr m + n`,反引号方式,注意:运算符之间要有空格,运算符有:+、-、*、/、%

示例:


5. 条件判断

(1)基本语法:

条件表达式 \],注意:"条件表达式"的左右必须要有空格,"条件表达式"非空表示true,空表示false,还可以使用"$?"(0表示true,非0表示false) 举例: \[ "zhangsan" \]:true \[\]:false (2)常用的条件判断 ① 比较运算符 1) = 相等 2) -lt 小于 3) -le 小于等于 4) -eq 等于 5) -gt 大于 6) -ge 大于等于 7) -ne 不等于 ② 按照文件权限判断 1) -r 具有读权限 2) -w 具有写权限 3) -x 具有可执行权限 ③ 按照文件类型判断 1) -f 文件存在,并且是普通文件 2) -e 文件存在 3) -d 文件存在,并且是目录 举例: \[ 23 -ge 22 \]:true \[ -w student.txt \]:判断student.txt文件是否可写 \[ -e /root/install.log \]:判断/root/install.log是否存在 **6. 流程控制** (1)if语句 语法: if \[ 条件1 \] #注意,if和\[\]之间有一个空格,\[\]内的"条件"左右也要有空格 then 执行体1 elif \[ 条件2 \] #注意空格 then 执行体2 ... else 执行体 fi 示例: ![](https://i-blog.csdnimg.cn/direct/8ff7b249a9e64076a5ba2ce1b1d2df49.png) 示例2: ![](https://i-blog.csdnimg.cn/direct/2cf1f48af6624e1e9bfa14ecb521e586.png) ![](https://i-blog.csdnimg.cn/direct/515497d6fcee46248d13ead3621499ff.png) (2)case语句 语法: case $变量名 in "值1") 执行体1;; "值2") 执行体2;; ... \*) 执行体;; esac 执行流程:如果变量跟值1匹配,则执行执行体1,然后结束case语句,如果跟值2匹配,则执行执行体2,然后结束case语句,......,如果都不匹配,执行执行执行体,然后结束case语句。 示例: ![](https://i-blog.csdnimg.cn/direct/57776528b77842989d3c0ac494d42f1c.png) (3)for循环:有两种语法: ① 语法一: for 变量 in 值1 值2 值3... do 循环体 done 示例: vi for1.sh:循环遍历123456 ![](https://i-blog.csdnimg.cn/direct/569193f6d65e47efbe02f07dd103c3d4.png) ![](https://i-blog.csdnimg.cn/direct/e94819001cea47c797837f000f4050bb.png) 示例2: vi for2.sh ![](https://i-blog.csdnimg.cn/direct/924a13d51c9c4bc1b08d3b5d2212bdd7.png) ![](https://i-blog.csdnimg.cn/direct/759660c4dbc24be09b1e60690eea079b.png) ② 语法二: for((初始值;循环条件;迭代值)) do 循环体 done 示例: vi for3.sh ![](https://i-blog.csdnimg.cn/direct/e6110ec2a57f4dd4acaa271496493627.png) ![](https://i-blog.csdnimg.cn/direct/a0130f9d8af24bb39cc7a666a57fdac9.png) (4)while循环 语法: while \[ 循环条件 \] #注意:while和\[\]之间有一个空格,\[\]内的"循环条件"左右也要有空格 do 循环体 done 示例:计算10的阶乘 vi while.sh ![](https://i-blog.csdnimg.cn/direct/4bdbaf78e0584cb78df3e09e08ef6290.png) ![](https://i-blog.csdnimg.cn/direct/a76a263f67a04d67bdbfe000b95a9e61.png) 示例:Shell中的流程控制可以去控制所有Shell命令的执行 ![](https://i-blog.csdnimg.cn/direct/b046e9c798024885b1c09f269f9e49c6.png) ![](https://i-blog.csdnimg.cn/direct/bc11503b54c54fcab2bc4fcb01d5f84d.png) (5)read:从控制台读取输入 语法: read 选项 参数 选项: -p:指定读取值时的提示文字 -t:指定读取值时的等待时间(秒) 参数: 变量名:指定接收读取到的值的变量 示例: vi read.sh ![](https://i-blog.csdnimg.cn/direct/e61e6d12db58454ea735e2e498f1bfbd.png) ![](https://i-blog.csdnimg.cn/direct/1b6fb44b0ab343f89ac08ac5ebde1cd4.png) (6)函数 ① 系统函数 1) basename:会删除文件的前缀路径和后缀 语法: basename 路径/文件名.后缀:去掉路径,只保留"文件名.后缀" basename 路径/文件名.后缀 后缀:去掉路径和后缀,只保留"文件名" 示例: ![](https://i-blog.csdnimg.cn/direct/35d85a2054684a0eb7b40f20e9b1fb6c.png) 2) dirname:去除文件名,得到路径 语法: dirname 完整路径的文件 ![](https://i-blog.csdnimg.cn/direct/e4bcc0a28e8548d39b862b8ef6fac824.png) ② 自定义函数 语法: \[function\] name\[()

{

函数体

}

这里的[]表示可以省略,注意,函数必须先声明后使用,因为Shell是逐行解释执行的

示例:

vi function.sh

四、Docker

1.什么是Docker

Docker是一个开源项目,诞生于2013年初,最初是dotCloud公司内部的一个子项目,基于go语言构建,后来加入了Linux基金会,遵从Apache2.0协议,项目代码在GitHub上维护。Docker项目的目的是显式轻量级的虚拟化解决方案(类似于VMware),Docker的基础是Linux容器(LXC)等技术

Docker和传统的VMware虚拟机相比具有的优点

特性 Docker容器 传统虚拟机

启动 秒级 分钟级

硬盘使用 一般是MB 一般是GB

性能 接近原生 弱于原生

系统支持量 支持上千个容器 一般几十个

2.Docker的三个基本概念

镜像(Image)

容器(Container)

仓库(Repository)

(1)Docker镜像:Docker镜像就是一个只读的模板,比如一个镜像可以包含一个完整的ubuntu操作系统,镜像可以用来创建Docker容器,Docker提供了一个很简单的机制来创建镜像或更新现有的镜像,用户可以直接从其他人那里下载一个已经做好的镜像来使用,类似安装的操作系统的ISO镜像。

(2)Docker容器:Docker利用容器(一个简易的Linux系统)来运行程序,容器是从镜像创建的运行实例,可以被启动,开始,停止,删除,每个容器都是相互隔离的,保证安全的平台,可以把容器看成是一个简易的Linux操作系统环境。

(3)Docker仓库:仓库是集中存放Docker镜像文件的地方,仓库分为公开仓库(public)和私有仓库(private),最大的公开仓库是Docker Hub,存放了大量的镜像给用户使用,用户也可以创建自己的镜像然后通过push命令将其上传到公共仓库货私有仓库,其他人可以通过pull命令下载该镜像。

3.CentOS7安装Docker

(1)安装:卸载旧版本Docker

sudo yum remove docker \

docker-client \

docker-client-latest \

docker-common \

docker-latest \

docker-latest-logrotate \

docker-logrotate \

docker-engine

(2)安装Docker,通过yum的方式安装

① 配置Docker Repository

在主机上首次安装Docker Engine之前,需要设置Docker Repository,之后可以从Repository安装和更新Docker

第一步:安装必要的一些系统工具

sudo yum install -y yum-utils device-mapper-persistent-data lvm2

第二步:添加软件源信息,国内Repository更加稳定

sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

第三步:更新

sudo yum makecache fast

② 安装最新版的Docker Engine和Container

sudo yum -y install docker-ce docker-ce-cli containerd.io

③ 启动Docker服务

sudo systemctl start docker

④ 查看Docker服务状态

systemctl status docker

⑤ 设置Docker服务开机自启动

systemctl enable docker

4.Windows中安装Docker

下载安装Boot2Docker:https://github.com/boot2docker/window-installer/releases/latest,

安装就是一路向前下一步

5.Docker镜像加速器

(1)国内从Docker Hub仓库(国外服务器)拉取镜像文件的速度可能会比较慢(甚至不能访问),Docker官方和国内很多云服务商都提供了国内加速服务。

配置国内镜像加速器需要修改docker的配置文件"/etc/docker/daemon.json",将镜像加速器的网址配置进去:如果没有这个文件,就新建daemon.json文件:

复制如下内容:

{

"registry-mirrors": [

"https://docker.registry.cyou",

"https://docker-cf.registry.cyou",

"https://dockercf.jsdelivr.fyi",

"https://docker.jsdelivr.fyi",

"https://dockertest.jsdelivr.fyi",

"https://mirror.aliyuncs.com",

"https://dockerproxy.com",

"https://mirror.baidubce.com",

"https://docker.m.daocloud.io",

"https://docker.nju.edu.cn",

"https://docker.mirrors.sjtug.sjtu.edu.cn",

"https://docker.mirrors.ustc.edu.cn",

"https://mirror.iscas.ac.cn",

"https://docker.rainbond.cc"

]

}

修改之后重启docker服务:

sudo systemctl daemon-reload

sudo systemctl restart docker

(2)Windows版的Docker更改国内镜像加速器

在系统右下角托盘Docker图标内右键菜单选择Settings,打开配置窗口左侧导航菜单选择Daemon,在Registrymirrors一栏中填写加速器地址:https://hub-mirror.c.163.com/,之后点击Apply保存后Docker就会重启并应用配置。

6.Docker的使用

(1)运行docker命令,可以看到docker的所有命令

(2)查看docker命令的语法:docker 命令 --help

(3)查询镜像:由于查询镜像是在国外的Docker Hub里面找,是不能访问的

docker search 镜像的名字

这样也不行:

不能找就直接通过镜像名下载即可,我们配置了国内镜像加速之后是可以下载的

(4)拉取镜像,即将镜像下载到本地,语法:

docker pull 镜像名[:版本号],如果省略版本号,则默认下载最新的版本

(5)查看本地已经下载的镜像:docker images

注意:在创建Docker容器的时候可以根据该镜像在仓库中的名字(redis)或其镜像ID(ad4b31aa2de6)来创建容器。

(6)根据镜像创建后台运行的容器(容器就是一个简易的Linux系统)

在大部分的应用场景中,我们希望Docker应用以服务的方式在容器的后台运行,可以通过"-d"参数(daemon,即守护进程/服务)来执行容器的运行模式,语法:

docker run -d --name 服务名称 [-p 端口映射] [-e 环境配置] [--restart=always] 镜像名称/镜像的ID

说明:

-d:以daemon(守护进程/服务)的方式是运行,即以服务方式存在

--name:指定该服务的名称

-p:指定该服务的通讯端口号,比如:-p6379:6379,第一个6379是安装Docker的CentOS服务器上的端口号,第二个6379是指Docker容器中该进程的端口号,这里就是将容器中该进程的6379端口号映射到外部的CentOS服务器的6379端口上

-e:环境设置

--restart=always:开机启动该服务

注意:如果使用了"-d"参数在容器中运行了镜像之后,不会直接进入到容器中,要进入到容器中需要使用后面讲的docker exec命令进入。

示例:

这样redis服务就在容器中运行起来了,并且设置了开启自启动。

(7)进入容器(容器就是一个简易的Linux系统)

docker exec -it 服务名 bash

参数:

-i:以交互式方式进入

-t:以终端方式进入

注意:如果我们进入容器之后再退出,容器不会停止运行,因为上面已经将容器运行成了服务的方式。

(8)退出容器:exit

(9)查看容器中运行的进程的状态:docker ps -a

(10)查看容器中进程的信息

docker top 容器ID

(11)启动一个容器(即启动容器中的服务):docker start 服务名或容器ID

(12)停止一个容器:docker stop 服务名或容器ID

(13)重启一个容器:docker restart 服务名或容器ID

(14)删除容器:docker [-f] rm 服务名或容器ID,其中-f表示强制删除

(15)删除本地镜像:docker rmi 镜像在仓库中的名字或镜像ID

(16)Docker容器的数据卷

Docker容器和安装Docker的CentOS服务器之间是不能直接交换数据的,需要通过数据卷来交互数据,数据卷是安装Docker的CentOS服务器的一个目录或文件,当容器的目录和数据卷绑定之后,对方的修改会立刻互相同步,一个数据卷可以被多个容器同时挂载。

注意:

1)目录必须是绝对路径

2)如果目录不存在,会自动创建

3)可以挂载多个数据卷

语法:

docker run ... -v 安装Docker的CentOS服务器的目录/文件:Docker容器目录/文件