2.7 实战案例:单分支if语句
对于简单的条件判断,结合&&和||就可以完成大量的脚本。但是当脚本越写越复杂、功能越写越完善时,简单的&&和||就不足以满足需求了。
此时,选择使用if语句结合各种判断条件,功能会更加完善和强大。在Shell脚本中if语句有三种格式,分别是单分支if语句、双分支if语句和多分支if语句。下面是单分支if语句的语法格式。
if 条件测试 then 命令序列 fi
if和then可以写在同一行。同一行中如果需要编写多条命令,中间需要使用分号分隔命令。所以,单分支if语句也可以写成如下格式。
if条件测试;then 命令序列 Fi
单分支if语句会检查条件测试的结果,只要返回的结果为真,那么就会执行then后面的命令序列(可以包含一条或多条命令)。但如果测试条件返回的结果为假,那么if语句就什么命令也不执行。这里的条件测试除了可以是字符串的比较测试、数字的比较测试、文件或目录属性的测试,还可以是一条或多条命令。单分支if语句的工作流程如图2-1所示。
图2-1 单分支if语句的工作流程
下面我们看一个单分支if语句的例子,读取用户输入的用户名和密码后,脚本通过if判断用户名和密码是否非空,如果非空则创建账户并设置密码,否则脚本直接结束。执行脚本,当提示输入用户名和密码时,如果我们都不输入(直接按回车键),脚本就会退出。
但是,上面的脚本有一个问题。当执行脚本提示输入用户名时,直接按回车键,而当提示输入密码时,正常输入一个密码,这时运行脚本就会报错。因为这样导致在账户没有创建成功的情况下,修改账户密码,结果一定会报错。因此,还需要继续优化这个脚本,可以使用嵌套if语句(在if语句里面再使用if语句)来解决该问题。
这样做的好处是,如果账户名为空,则脚本就不会执行then后面的命令,也就不会对密码做任何测试动作,更不会修改账户密码,而是直接退出脚本。如果测试账户名为非空,则进一步对密码进行测试,如果密码也非空,那么就执行then后的命令,创建账户并设置密码。
因为在学习前面的测试语句时,可以同时对多个条件进行测试,所以上面的脚本可以继续修改为下面的版本。
或者,下面这样的版本。
又或者,下面这样的版本。虽然在[]中不允许使用&&和||符号进行多个条件的测试判断,但是,可以使用多次[]测试,中间使用&&和||进行逻辑判断。
提示:if语句后面的条件测试语句不一定非要是test或[]测试语句,任何有返回值的命令都可以写在if语句后面,命令返回值为0代表执行成功(即为真),返回值非0代表执行失败(即为假)。下面看案例。
脚本自动测试,如果某些操作无法完成则报错,这是很常用的脚本功能。
下面这个例子,可以通过if条件语句自动判断服务的各种状态,是否已经启动、是否为开机自启动项等。
下面介绍如何一键创建VNC服务器脚本。
如果你的Linux服务器有图形环境,而你又希望将自己的屏幕共享给其他人,这样就可以在没有投影设备的情况下,让其他人看到你的屏幕操作了。下面是一键配置VNC远程桌面的脚本案例。
在Linux系统中tigervnc-server软件可提供远程桌面服务,脚本首先检查系统中是否已经存在该软件。如果不存在,则脚本自动安装该软件。安装软件后,通过x0vncserver命令创建远程桌面服务,该命令的选项功能描述如下。
● AcceptKeyEvents=0,禁止其他人在远程操作本机时使用键盘。设置为1时,表示允许操作键盘。默认值为1。
● AcceptPointerEvents=0,禁止其他人在远程操作本机时使用鼠标。设置为1时,表示允许操作鼠标。默认值为1。
● AlwaysShared=1,当有多人远程操作本机时,永远支持共享。设置为0时,同时仅允许一个人远程操作本机。默认值为0。
● SecurityTypes=None,当其他人远程操作本机时,不需要输入密码。也可以设置为需要输入密码的方式连接本机。默认值为VncAuth,需要输入密码认证。
● rfbport=5908,设置远程桌面连接的端口号为5908,也可以设置为其他端口号。
配置完VNC服务器后,客户端可以通过下面的命令查看远程桌面。
[root@centos7~]# yum -y install tigervnc [root@centos7~]# vncviewer 服务器的IP地址:5908
2.8 实战案例:双分支if语句
与单分支if语句的格式一样,then和if可以写在同一行,也可以分开写在不同行。甚至在else和命令序列1中间添加分号将其写在同一行,但很少有人这样写,这将导致代码的可读性非常差。
if条件测试;then 命令序列1 else 命令序列2 Fi
双分支if语句会检查条件测试的结果,只要测试条件返回值结果为真,就会执行命令序列1(可以包含一条或多条命令)。但如果测试条件返回值结果为假,那么就会执行命令序列2。所以双分支if语句,不管条件是否成立,都会执行特定的命令。双分支if语句的工作流程如图2-2所示。
图2-2 双分支if语句的工作流程
看一个简单的双分支if语句的例子,使用if语句判断某台主机是否可以ping通。这是一个典型的双分支if语句案例。
因为RPM等类似的二进制软件往往不能提供最新的版本,并且不具备自定义安装选项,所以生产环境中经常需要采用源码的方式安装软件。但采用源码的方式安装软件的步骤又比较烦琐,所以编写脚本实现自动化安装软件是非常重要的。下面看一个采用源码的方式安装软件的脚本案例。
脚本解析如下。
脚本的第一个功能是通过使用变量的方式,定义echo回显的颜色属性。echo命令的-n选项,可以在回显数据后不按回车键即可换行,-e选项开启右斜线(\)转义的解释功能。
通过对系统环境变量UID的比较测试,判断当前执行脚本的用户是否为管理员。如果不是管理员,则脚本直接提示错误并退出。
使用rpm -q可以查询某个软件是否已经安装。再通过--quiet选项,设置无论软件是否已经安装都不在屏幕上回显结果,而是通过if语句自动判断命令的执行结果是真还是假。如果未安装wget,则脚本提示错误并退出。反之,在系统中已有wget工具的情况下,联网下载Nginx源码包软件。wget命令的-c选项可以开启断点续传的功能,下载过程中如果突然断网,联网后可以从上次的断点处继续下载,而不需要将文件全部重新下载。
启动Nginx服务时,以普通用户的身份登录会更安全。脚本通过Id命令检查nginx账户是否已经存在,如果不存在nginx账户,则脚本会自动创建该账户。
在编译源码安装Nginx时,首先需要安装该软件包依赖的相关软件包,脚本中安装了gcc、pcre-devel、zlib-devel、openssl-devel这四个软件包,这些软件都在CentOS标准的Yum中,并且在安装openssl-devel时会自动安装zlib-devel。所以,哪怕不通过Yum明确要求安装zlib-devel,也会在安装openssl-devel时自动安装zlib-devel。Nginx是模块化的软件,可以通过<--with-模块>的方式启动某个模块的功能,不需要的功能模块,可以通过<--without-模块>的方式禁用。