IF 条件语句的知识与实践

7. if 条件语句的知识与实践

7.1 if 条件语句

if条件语句是Linux运维人员在实际生产工作中使用得最频繁也是最重要的语句,因此,请务必重视if条件语句的知识,并牢固掌握。

7.1.1 if 条件语句的语法

if条件语句,其语义类似于汉语里的"如果...那么"。

1. 单分支结构

第一种语法:

bash 复制代码
if <条件表达式>
  then 
  指令1
  指令2
  ...
fi

第二种语法:

bash 复制代码
if <条件表达式>;then
  指令1
  指令2
  ...
fi

上文的"<条件表达式>"部分可以是test、口、[[]]、(())等条件表达式,甚至可以直接使用命令作为条件表达式。每个if条件语句都以if开头,并带有then,最后以fi结尾。

第二种语法中的分号相当于命令换行,上面的两种语法含义是相同的,读者可根据习惯自行选择。

本书主要使用第二种语法格式。

在所有编程语言里,if条件语句几乎是最简单的语句格式,且用途最广。当if后面的<条件

表达式>成立时(真),就会执行then后面的指令或语句;否则,就会忽略then后面的指令或语句,

转而执行fi下面的程序。

if单分支语句执行流程逻辑图如下:

条件语句还可以嵌套(即if条件语句里面还有if条件语句),注意每个if条件语句中都要有一个与之对应的fi(if反过来写),每个if和它下面最近的fi成对搭配,语法示例如下:

bash 复制代码
if <条件表达式>;then
  if <条件表达式>;then
    指令
  fi
fi

提示:通常在书写Shell条件语句时,要让成对的条件语句关键字的缩进相对应,以便于阅读浏览。

前文曾讲解过的文件条件表达式:

bash 复制代码
[ ! -d /tmp/shizhan ] && mkdir /tmp/shizhan

等价于下面的if条件语句:

bash 复制代码
if [ ! -d /tmp/shizhan ];then
  mkdir /tmp/shizhan
fi

记忆小技巧:女孩对男孩说。

bash 复制代码
如果 你有房;那么
    我就嫁给你
果如
2. 双分支结构

if条件语句的双分支结构主体则为:"如果...,那么...,否则..."。

if条件语句的双分支结构语法为:

bash 复制代码
if <条件表达式>;then
  指令集1
else
  指令集2
fi

if 双分支语句执行流程逻辑图如下:

前文的文件测试条件表达式

bash 复制代码
[ -d /tmp/shizhan ] && echo /tmp/shizhan is exist || mkdir /tmp/shizhan

就相当于下面的双分支的if条件语句:

bash 复制代码
if [ -d /tmp/shizhan ];then
  echo /tmp/shizhan is exist
else
  mkdir /tmp/shizhan
fi

记忆小技巧:女孩对男孩说。

bash 复制代码
如果 你有房;那么
    我就嫁给你
否则
    我再考虑考虑
果如
3. 多分支结构

if条件语句多分支结构的主体为:"如果...,那么...,否则如果...,那么,否则如果...,那么...,否则..."。

if条件语句多分支语法为:

bash 复制代码
if <条件表达式1>;then
  指令1
elif <条件表达式2>;then
  指令2
else
  指令3
fi

多个elif

bash 复制代码
if <条件表达式1>;then
  指令
elif <条件表达式2>;then
  指令
elif <条件表达式3>;then
  指令
else
  指令
fi

提示:

  1. 注意多分支elif的写法,每个elif都要带有then。
  2. 最后结尾的else后面没有then。

if多分支语句执行流程对应的逻辑图如下:

记忆小技巧:女孩对男孩说。

bash 复制代码
如果 你有房;那么
    我就嫁给你
或者 你有钱;那么
    我也可以嫁给你
否则
    我再考虑考虑
果如

7.1.2 if 条件语句多种条件表达式语法

if条件语句(包括双多分支if)的"<条件表达式>"部分可以是test、[]、[[]]、(())等条件表达式,甚至还可以直接使用命令作为条件表达式,具体的语法如下。

1. test 条件表达式
bash 复制代码
if test 表达式;then
  指令
fi
2. [] 条件表达式
bash 复制代码
if [ 字符串 或 算术表达式 ];then
  指令
fi
3. [[]] 条件表达式
bash 复制代码
if [[ 字符串 或 算术表达式 ]];then
  指令
fi
4. (()) 条件表达式
bash 复制代码
if ((算术表达式));then
  指令
fi
5. 命令表达式
bash 复制代码
if 命令;then
  指令
fi

说明:以上表达式除了语法不同之外,具体的应用是一致的,实际工作场景中,读者只需选择一种适合自己习惯的表达式就好。

7.1.3 if 条件语句实践

示例1:检测sshd服务是否运行,如果未运行则启动sshd服务。

bash 复制代码
#!/bin/bash
systemctl is-active sshd &>/dev/null
if [ $? -ne 0 ];then
  echo "sshd is not running, I'll start sshd."
  systemctl start sshd
fi

示例2:检测sshd服务是否运行,如果未运行则启动sshd服务;如果运行,输出 "Running"。

bash 复制代码
#!/bin/bash
systemctl is-active sshd &>/dev/null
if [ $? -ne 0 ];then
  echo "sshd is not running."
  echo -n "Starting sshd ... ..."
  systemctl start sshd && echo DONE
else
  echo "sshd is running"
fi

示例3:通过传参控制sshd服务。

bash 复制代码
#!/bin/bash
if [ "$1" = "start" ];then
  systemctl start sshd
elif [ "$1" = "stop" ];then
  systemctl stop sshd
elif [ "$1" = "status" ];then
  systemctl status sshd
elif [ "$1" = "restart" ];then
  systemctl restart sshd
else
  echo "Usage: $0 start|stop|status|restart "
fi

或者

bash 复制代码
#!/bin/bash
if [ "$1" = "start" -o "$1" = "stop" -o "$1" = "status" -o "$1" = "restart" ];then
  systemctl $1 sshd
else
  echo "Usage: $0 start|stop|status|restart"
fi

示例4:任意给三个整数,对三个数进行从大到小排序并输出。

bash 复制代码
#!/bin/bash
a=10
b=20
c=30
# 如果a小于b,交换值,此时a大b小
if [ $a -lt $b ];then
  num=$b;b=$a;a=$num
fi
# 比较后两个值大小并交换,此时c值最小
if [ $b -lt $c ];then
  num=$c;c=$b;b=$num;
fi
# 比较前两个值大小并交换,此时a值最大
if [ $a -lt $b ];then
  num=$b;b=$a;a=$num;
fi
echo "$a>$b>$c"

示例5:每3分钟检查一次系统可用内存,如果空闲内存低于100M时给root用户发邮件。

对于开发程序而言,一般来说应该遵循下面的3步法则。

  1. 分析需求

    明白开发需求,是完成程序的大前提,因此,分析需求至关重要,一切不以需求为主的程序开发,都是不倡导的!

  2. 设计思路

    设计思路就是根据需求,把需求进行拆解,分模块逐步实现,例如本题可以分为如下几步:

    1. 获取当前系统剩余内存的值(先在命令行实现)。
    2. 配置邮件报警(可采用第三方邮件服务器)。
    3. 判断取到的值是否小于100MB,如果小于100MB,就报警(采用if语句)。
    4. 编码实现Shell脚本。
    5. 加入crond定时任务,每三分钟检查一次。
  3. 编码实现

    编码实现就是具体的编码及调试过程,工作中很可能需要先在测试环境下调试,调试好了,再发布到生产环境中。

本例的最终实现过程如下:

  1. 获取可用内存大小。

    bash 复制代码
    [shizhan@shell ~]$ free -m
                  total     used      free      shared  buff/cache   available
    Mem:           3931      327      3419          11         184        3388
    Swap:          3967        0      3967
    
    [shizhan@shell ~]$ free -m | awk 'NR==2 { print $4}'
    3419
  2. 发邮件的客户端常见的有mail或mutt;服务端有sendmail服务(CentOS5下默认的)、postfix服务(CentOS6下默认的)。这里不使用本地的邮件服务。

  3. 编写Shell脚本:monitor_mem.sh。

    bash 复制代码
    #!/bin/bash
    FreeMem=$(free -m | awk 'NR==2 { print $4}')
    if [ $FreeMem -lt 100 ];then
      echo  "Mem is lower than 100M" | mail -s "FreeMem is ${FreeMem}M" root@localhost
    fi
  4. 加入到计划任务

    bash 复制代码
    [shizhan@shell ~]$ chmod +x monitor_mem.sh
    [shizhan@shell ~]$ crontab -e 
    no crontab for shizhan - using an empty one
    crontab: installing new crontab
    [shizhan@shell ~]$ crontab -l
    */3 * * * * /home/shizhan/monitor_mem.sh

7.2 if 条件语句企业案例

7.2.1 监控 Web 和数据库

用if条件语句针对Nginx Web服务或MySQL数据库服务是否正常进行检测,如果服务未启动,则启动相应的服务。

这是企业级运维实战综合题,需要读者对NginxWeb服务或MySQL数据库服务很熟悉才行,本例同样适用于其他的Web服务和数据库服务。

大家还记得前面说过的开发程序前的三部曲吧?这里就采用这种方式来解答此题。

(1) 分析问题

监控Web服务和MySQL数据库服务是否异常的方法:

  • 端口监控

    1. 在服务器本地监控服务端口的常见命令有 netstat、ss、lsof
    2. 从远端监控服务器本地端口的命令有 telnet、nmap、nc
  • 监控服务进程或进程数,此方法适合本地服务器,注意,过滤的是进程的名字。命令为:

    复制代码
    ps -ef | grep nginx | wc -1
    ps -ef | grep mysql | wc -1
  • 客户端模拟用户访问

    • 使用wget或curl命令进行测试(如果监测数据库,则需要转为通过Web服务器去访问数据库),并对测试结果做三种判断:

      • 利用返回值($?)进行判断
      • 获取特殊字符串以进行判断(需要事先开发好程序)
      • 根据HTTP响应header的情况进行判断
    • 登录MySQL数据库判断

      • 通过MySQL客户端连接数据库,根据返回值或返回内容判断。例如:

        bash 复制代码
        mysql -u root -pshizhan -e "select version();" &>/dev/null;echo$?

此外,对端口进程等进行判断时,尽量先通过grep过滤端口和进程特殊标记字符串,然后结合wc将过滤到的结果转成行数再比较,这样相对简单有效,且经过wc-1命令处理之后的结果一定是数字,这样再进行判断就会比较简便。如果单纯地根据具体的列取具体的值判断会很麻烦,如果确实想采用取值判断的方法,那就尽量用字符串比较的语法。

提示:掌握技术思想比解决问题本身更重要。

(2) 监测 MySQL 数据库异常
  1. MySQL 数据库环境准备

    bash 复制代码
    [shizhan@shell ~]$ sudo yum install -y mariadb-server
    [shizhan@shell ~]$ sudo systemctl enable mariadb --now
    [shizhan@shell ~]$ sudo ss -lnt|grep 3306
    LISTEN     0      50           *:3306                     *:*
    # 关闭防火墙
    [shizhan@shell ~]$ sudo systemctl disable firewalld.service --now
  2. 通过命令行检测数据库服务是否正常,只有先确定命令行是正确的,才能确保将它放到脚本里也是正确的。

    • 首先采用端口监控的方式。

      在服务器本地监控端口的命令有netstat、ss、lsof,这里使用ss:

      bash 复制代码
      [shizhan@shell ~]$ ss -lnt|grep ':3306'|wc -l
      1

      从远端监控服务器监控本地端口的命令有telnet、nmap、nc,这里使用nmap:

      bash 复制代码
      [shizhan@shell ~]$ sudo yum install -y nmap nc telnet
      [shizhan@shell ~]$ nmap 127.0.0.1 -p 3306|grep open
      3306/tcp open  mysql
      [shizhan@shell ~]$ nmap 127.0.0.1 -p 3306|grep open|wc -l
      1

      本例为了统一IP地址,因此使用的都是同一个IP,即127.0.0.1,在实际工作中,应该用自己服务器的IP来替代。

    • 以下是在客户端模拟用户访问的方式进行监控。

      使用mysql连接数据库,根据执行命令的返回值判断成功与否。

      bash 复制代码
      [shizhan@shell ~]$ mysql -uroot -h 127.0.0.1 -e 'select version();' &>/dev/null
      [shizhan@shell ~]$ echo $?
      0
  3. 开发监控MySQL数据库的脚本。

    bash 复制代码
    #!/bin/bash
    if ss -lnt|grep -q ':3306';then
      echo "MySQL is Running."
    else
      echo "MySQL is Not Running."
    fi
(3) 监测 Web 服务器异常
  1. Web 服务器准备

    bash 复制代码
    [shizhan@shell ~]$ sudo yum install -y httpd
    [shizhan@shell ~]$ sudo systemctl enable httpd --now
    [shizhan@shell ~]$ sudo ss -lnt|grep ':80 '
    LISTEN     0      128       [::]:80                    [::]:* 
    # 关闭防火墙
    [shizhan@shell ~]$ sudo systemctl disable firewalld.service --now
  2. 通过命令行检测数据库服务是否正常,只有先确定命令行是正确的,才能确保将它放到脚本里也是正确的。

    • 首先采用端口监控的方式。

      在服务器本地监控端口的命令有netstat、ss、lsof,这里使用ss:

      bash 复制代码
      [shizhan@shell ~]$ ss -lnt|grep ':80'|wc -l
      1

      从远端监控服务器监控本地端口的命令有telnet、nmap、nc,这里使用nmap:

      bash 复制代码
      [shizhan@shell ~]$ sudo yum install -y nmap nc telnet
      [shizhan@shell ~]$ nmap 127.0.0.1 -p 80|grep open
      3306/tcp open  mysql
      [shizhan@shell ~]$ nmap 127.0.0.1 -p 80|grep open|wc -l
      1

      本例为了统一IP地址,因此使用的都是同一个IP,即127.0.0.1,在实际工作中,应该用自己服务器的IP来替代。

    • 以下是在客户端模拟用户访问的方式进行监控。

      使用wget或curl命令访问URL地址来测试。根据执行命令的返回值判断成功与否,本例的URL使用了网上的地址,在实际工作中应使用开发人员提供给我们的访问数据库的程序地址。

      bash 复制代码
      # 方式1
      [shizhan@shell ~]$ wget --timeout=10 --tries=2 www.redhat.com 2>/dev/null
      [shizhan@shell ~]$ echo $?
      0
      
      # 方式2
      [shizhan@shell ~]$ wget --timeout=10 --tries=2 www.redhat.com -q
      [shizhan@shell ~]$ echo $?
      0
      
      # 方式3
      [shizhan@shell ~]$ curl -s www.redhat.com
      [shizhan@shell ~]$ echo $?
      0
    1. 开发监控Web服务器的脚本

      bash 复制代码
      #!/bin/bash
      if wget --timeout=10 --tries=2 www.redhat.com &>/dev/null;then
        echo "Apache is Running."
      else
        echo "Apache is Not Running."
      fi

7.2.2 比较大小的经典拓展案例

使用if条件语句比较两个整数的大小。使用传参方法时,需要对传参个数及传入的参数是否为整数进行判断。

示例1:

bash 复制代码
#!/bin/bash

# 判断参数个数
if [ $# -ne 2 ];then
  echo "USAGE: $0 numl num2"
  exit 1
fi

# 赋值
a=$1
b=$2

# 判断参数是否为整数
expr $a + 1 &>/dev/null
RETVAL1=$?
expr $b + 1 &>/dev/null
RETVAL2=$?
if [ $RETVAL1 -ne 0 -o $RETVAL2 -ne 0 ];then
  echo "please provide two int number"
  exit 2
fi

# 比较
if [ $a -lt $b ];then
  echo "$a<$b"
elif [ $a -eq $b ];then
  echo "$a=$b"
else
  echo "$a>$b"
fi

示例2:

bash 复制代码
#!/bin/sh
read -p "Pls input two num:" a b
expr $a + 0 & >/dev/null
RETVAL1=$?
expr $b + 0 & >/dev/null
RETVAL2=$?
if [ -z "$a" ] || [ -z "$b" ];then
  echo "Pls input two num again.
  exit 1
elif test $RETVAL1 -ne 0 -o $RETVAL2 -ne 0;then
  echo "Pls input two int num again.
  exit 2
elif [ $a -lt $b ];then
  echo "$a < $b"
elif [ $a -eq $b ];then
  echo "$a = $b"
else
  echo "$a > $b"
fi
exit 0

7.2.3 判断字符串是否为数字的多种思路

示例1:删除字符串中的所有数字,看字符串的长度是否为0 , 如果不为0,则说明不是整数。

sed替换:

bash 复制代码
[shizhan@shell ~]$ [ -n "$(echo shizhan123|sed 's/[0-9]//g')" ] && echo char || echo int
char

[shizhan@shell ~]$ [ -n "$(echo 123|sed 's/[0-9]//g')" ] && echo char || echo int
int

[shizhan@shell ~]$ [ -z "$(echo 123|sed 's/[0-9]//g')" ] && echo int || echo char
int

[shizhan@shell ~]$ [ -z "$(echo shizhan123|sed 's/[0-9]//g')" ] && echo int || echo char
char

使用变量的子串替换

bash 复制代码
[shizhan@shell ~]$ string=shizhan123
[shizhan@shell ~]$ [ -n "${string//[0-9]/}" ] && echo char || echo int
char

[shizhan@shell ~]$ string=123
[shizhan@shell ~]$ [ -n "${string//[0-9]/}" ] && echo char || echo int
int

使用tr替换:

bash 复制代码
[shizhan@shell ~]$ string=123
[shizhan@shell ~]$ [ -z "$(echo $string | tr -d 0-9)" ] && echo int || echo char
int

[shizhan@shell ~]$ string=abc123
[shizhan@shell ~]$ [ -z "$(echo $string | tr -d 0-9)" ] && echo int || echo char
char

示例2:如果num的长度不为0,并且把num中的非数字部分删除,然后再看结果是不是等于num本身,如果两者都成立,则num就是数字。

bash 复制代码
[shizhan@shell ~]$ num=abc123
[shizhan@shell ~]$ [ -n "$num" -a  "$num" = "${num//[^0-9]/}" ] && echo int || echo char
char
[shizhan@shell ~]$ num=123
[shizhan@shell ~]$ [ -n "$num" -a  "$num" = "${num//[^0-9]/}" ] && echo int || echo char
int

示例3:通过 expr 计算判断

bash 复制代码
[shizhan@shell ~]$ expr abc + 1 &>/dev/null
[shizhan@shell ~]$ echo $?
2

[shizhan@shell ~]$ expr 1 + 1 &>/dev/null
[shizhan@shell ~]$ echo $?
0

示例4:通过"=~"符号判断

bash 复制代码
[shizhan@shell ~]$ [[ 123 =~ ^[0-9]+$ ]] && echo int || echo char
int
[shizhan@shell ~]$ [[ abc123 =~ ^[0-9]+$ ]] && echo int || echo char
char

7.2.4 判断字符串长度是否为0的多种思路

示例1:使用字符串条件表达式判断

bash 复制代码
[shizhan@shell ~]$ [ -z "shizhan" ] && echo true || echo false
false
[shizhan@shell ~]$ [ -n "shizhan" ] && echo false || echo true
false

示例2:使用变量子串判断

bash 复制代码
[shizhan@shell ~]$ str=shizhan
[shizhan@shell ~]$ [ ${#str} -eq 0 ] && echo true || echo false
false

示例3:使用 expr length 函数判断

bash 复制代码
[shizhan@shell ~]$ [ $(expr length "shizhan") -eq 0 ] && echo true || echo false
false

示例4:使用wc -L命令统计判断

bash 复制代码
[shizhan@shell ~]$ [ $(echo "shizhan"|wc -L) -eq 0 ] && echo true || echo false 
false

示例5:使用 awk length 函数判断

bash 复制代码
[shizhan@shell ~]$ [ $(echo "shizhan"|awk '{print length}') -eq 0 ] && echo true || echo false
false

7.2.5 监控 memcached 服务是否正常

监控memcached服务是否正常,模拟用户(Web客户端)检测。

此题需要读者了解并可以搭建memcached服务(memcached是运维场景中常用的内存缓存软件),且可以用nc或telnet命令访问memcached服务,加上用set/get来模拟检测。

  1. 环境准备

    bash 复制代码
    [root@shell ~]# yum install -y nc memcached
    [root@shell opt]# systemctl enable memcached.service --now
  2. 参考解答

    bash 复制代码
    [shizhan@shell scripts]$ cat check_memcache.sh
    #!/bin/bash
    # Author: shizhan
    # Time: 2022-12-10 14:21:37
    # Name: check_memcache.sh
    systemctl is-active memcached.service &>/dev/null
    RetVal=$?
    
    if [ $RetVal -ne 0 ];then
      echo "Memcached is not running."
    else
      # 删除缓存中的 key 及对应的值
      printf "del key\r\n"|nc 127.0.0.1 11211  &>/dev/null
      # 添加新值
      printf "set key 0 0 10 \r\nshizhan1234\r\n"|nc 127.0.0.1 11211 &>/dev/null
      # 查询新值
      McCount=$(printf "get key\r\n"|nc 127.0.0.1 11211|wc -l)
      [ $McCount -eq 1 ] && \
      echo "Memcached status is ok." || \
      echo "Memcached status is error."
    fi

7.2.6 开发 rsync 服务的启动脚本

rsync是运维场景中最常用的数据同步软件,本例就是要完成一个类似系统的启动rsync服务的方法,即使用/etc/init.d/rsyncd{start|stop|restart}即可启动和停止rsync服务,这里是用if条件语句来实现相应效果的,其实通过case语句来实现效果最佳,不过由于还没讲解到case语句,因此这里主要练习if语句。

  1. 分析问题。要想开发出rsync服务的启动脚本,就需要熟悉rsync服务的配置,以及rsync服务是如何启动,以及如何停止的。

  2. 要实现/etc/init.d/rsyncd{start|stop|restart}的操作语法,就需要用到脚本的传参。根据传入的参数,进行判断,然后执行对应的启动和停止命令。

    实现过程如下:

    • 第1步,rsync 服务准备。
    bash 复制代码
    # 安装软件
    [shizhan@shell ~]$ sudo yum install -y rsync
    
    # 启动服务
    [shizhan@shell ~]$ sudo rsync --daemon
    
    # 检测端口
    [shizhan@shell ~]$ ss -lnt|grep ':873'
    LISTEN     0      5            *:873                      *:*              
    LISTEN     0      5         [::]:873                   [::]:*  
    • 第2步,rsync服务停止和端口检测。
    bash 复制代码
    [shizhan@shell ~]$ sudo pkill rsync
    [shizhan@shell ~]$ ss -lnt|grep ':873'
    • 第3步,判断rsync服务是否启动的方法。

      • 常规方法有检测端口以及进程是否存在
      • 还可以当服务启动时,创建一个锁文件(/var/lock/rsync/locker),而当服务停止时,就删除这个锁文件,这样就可以通过判断这个文件有无,来确定服务是否是启动状态,这是一些系统脚本常用的手法。
    • 第4步,开发rsync服务的启动脚本。

      bash 复制代码
      [shizhan@shell ~]$ sudo vim /etc/init.d/rsyncd
      #!/bin/bash
      # Author: shizhan
      # Time: 2022-12-12 18:10:15
      # Name: rsyncd
      
      # 判断参数个数
      if [ $# -ne 1 ];then
        echo "Usage: $0 [ start | stop | restart | status ]"
        exit 1
      fi
      
      # 根据参数1做出相应动作
      if [ "$1" = "start" ];then
        rsync --daemon
        sleep 2
        
        # 判断当前状态
        if ss -lnt|grep -q ':873';then
          echo "rsyncd is started."
          exit 0
        fi
      elif [ "$1" = "stop" ];then
        pkill rsync &>/dev/null
        sleep 2
        
        # 判断当前状态
        if ! ss -lnt|grep -q ':873';then
          echo "rsyncd is stoped."
          exit 0
        fi
      elif [ "$1" = "status" ];then
        # 判断当前状态
        if ! ss -lnt|grep -q ':873';then
          echo "rsyncd is stoped."
        else
          echo "rsyncd is started."
        fi
      elif [ "$1" = "restart" ];then
        pkill rsync &>/dev/null
        retval_1=$?
        sleep 1
        rsync --daemon
        retval_2=$?
        sleep 1
        # 判断停止和启动状态
        if [ $retval_1 -eq 0 -a $retval_2 -eq 0 ];then
          echo "rsyncd is restarted."
          exit 0
        fi
      else
        echo "Usage: $0 [ start | stop | restart | status ]"
        exit 1
      fi

    执行结果:

    bash 复制代码
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd start
    rsyncd is started.
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd status
    rsyncd is started.
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd stop
    rsyncd is stoped.
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd status
    rsyncd is stoped.
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd restart
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd status
    rsyncd is started.
    
    [shizhan@shell ~]$ sudo bash /etc/init.d/rsyncd hello
    Usage: /etc/init.d/rsyncd [ start | stop | restart | status ]
    [shizhan@shell ~]$ echo $?
    1

补充案例

输出脚本,模拟mysql_secure_installation执行过程的root密码修改流程

bash 复制代码
[root@shell bin 17:11:58]# vim mysql_secure_installation_my.sh
#!/bin/bash
read -s -p "Enter current password for root (enter for none): " root_old_password
echo

if [ -z "${root_old_password}" ];then
  mysql_cmd="mysql -uroot"
  mysqladm_cmd="mysqladmin -uroot password "
else
  mysql_cmd="mysql -uroot -p${root_old_password}"
  mysqladm_cmd="mysqladmin -uroot -p${root_old_password} password "
fi

if ${mysql_cmd} -e 'select 1;' &>/dev/null ;then
  echo 'OK, successfully used password, moving on...'
else
  echo "ERROR 1045 (28000): Access denied for user 'root'@'localhost' "
  exit
fi

read -p "Change the root password? [Y/n] " set_root_password

# Y y
if [[ "${set_root_password}" =~ [Y|y] ]] ; then
  read -s -p "New password: " root_new_password1
  echo
  read -s -p "Re-enter new password:  " root_new_password2
  echo

  # 校验两次密码是否一致
  if [ "${root_new_password1}" == "${root_new_password2}" ]; then
    root_new_password=${root_new_password1}
    ${mysqladm_cmd} ${root_new_password} && echo "Password updated successfully!"
  else
    echo "Sorry, passwords do not match."
    exit;
  fi

# N n
elif [[ "${set_root_password}" =~ [N|n]  ]]; then
  echo "... skipping."

# other
else
  "you must input Y or y or N or n"

测试

bash 复制代码
# 旧密码输入错误
[root@shell bin 17:14:06]# ./mysql_secure_installation_my.sh 
Enter current password for root (enter for none): 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' 

# 不修改密码
[root@shell bin 17:15:23]# ./mysql_secure_installation_my.sh 
Enter current password for root (enter for none): 
OK, successfully used password, moving on...
Change the root password? [Y/n] n
... skipping.

# 新密码两次不一致
[root@shell bin 17:15:41]# ./mysql_secure_installation_my.sh 
Enter current password for root (enter for none): 
OK, successfully used password, moving on...
Change the root password? [Y/n] y
New password: 
Re-enter new password:  
Sorry, passwords do not match.

# 密码修改成功
[root@shell bin 17:16:14]# ./mysql_secure_installation_my.sh 
Enter current password for root (enter for none): 
OK, successfully used password, moving on...
Change the root password? [Y/n] Y
New password: 
Re-enter new password:  
Password updated successfully!
相关推荐
池央1 小时前
中小企业私有云存储的跨网访问解决方案:Nextcloud 与 CPolar 的协同部署
运维·服务器
郝学胜-神的一滴1 小时前
Linux信号四要素详解:从理论到实践
linux·服务器·开发语言·网络·c++·程序人生
熊猫钓鱼>_>1 小时前
TRAE在企业级工作流中的深度集成:构建高效统一的开发与运维体系
运维
赖small强1 小时前
【Linux驱动开发】DDR 内存架构与 Linux 平台工作机制深度解析
linux·驱动开发·ddr·sdram·ddr controller
阿干tkl1 小时前
CentOS Stream 8 网络绑定(Bonding)配置方案
linux·网络·centos
Leon-Ning Liu1 小时前
【系列实验二】RAC 19C集群:CentOS 7.9 原地升级至 Oracle Linux 8.10 实战笔记
linux·数据库·oracle·centos
大聪明-PLUS1 小时前
C++编程中存在的问题
linux·嵌入式·arm·smarc
pingzhuyan1 小时前
linux运维异常(总) - 排查与修复(系统yum,docker,网络dns解析等)
linux·运维·docker·centos·shell
Ribou1 小时前
LDAP安装docker版
运维·docker·容器