Shell编程基础

一、Shell基本介绍

学习方法:基础命令+基础服务+经常练习+思路

1.定义

Shell是一种命令解释器,主要用于解析用户输入的指令并交给内核,由内核驱动硬件执行指令并返回信息;

Shell的执行方式:
交互式执行:执行一条指令,返回一次信息
非交互式执行:执行指令直接完成任务,不返回信息

2.Shell脚本

  • 将系统命令堆积在一起,顺序执行(简称:系统命令堆积)
  • 由特定的格式、特定的语法以及系统的命令共同组成的文件

3.Shell脚本的作用(Shell其实就是基于标准化之上的脚本工具)

注:Shell脚本主要的作用为简化操作步骤,提高效率,减少人为干预,减少系统故障

  • 基础配置:系统初始化、系统更新、内核调整、网络变更、时区调整、SSH优化
  • 安装程序:部署LNMP、LNMT、MySQL、Nginx、Redis、ELK等
  • 配置变更:Nginx Conf、PHP Conf、MySQL Conf、Redis Conf
  • 业务部署:Shell配合git、jenkins实现自动化部署php,java代码以及代码回滚
  • 日常备份:使用Shell脚本对MySQL进行每晚的全备与增量备份
  • 信息采集:Zabbix+Shell,硬件、系统、服务、网络等等;
  • 日志分析:取值->排序->去重->统计->分析
  • 服务扩容
  • 服务缩容

4.Shell脚本书写规范

  • 脚本存放固定目录 /scripts
  • 开头加#!/bin/bash
作用:告诉脚本使用的是哪种命令解释器。如不指定Shell,默认以bash解释器执行。
  • 附带作者及版权信(Author、Desc、E-mail、Version、Date)
  • 脚本扩展名为*.sh
  • 脚本尽量不使用中文
  • 成对的符号一次书写完成
  • 循坏格式一次性输入完成

附: Shell头部自动生成

编辑.vimrc文件
function AddTitle() #声明自定义函数
call setline(1,"#!/usr/bin/bash") #添加首行内容
call append(1,"#########################################") #以下部分为追加内容
call append(2,"#Author:作者")
call append(3,"#Email:邮箱")
call append(4,"#Date:" . strftime ("%Y-%m-%d"))
call append(5,"#Version:1.0")
call append(6,"#DESC:描述")
call append(7,"#########################################")
endf #声明自定义函数结束
map : call AddTitle() #定义按F2调用该函数
[root@shell ~]# vim .vimrc 
function AddTitle()
call setline(1,"#!/usr/bin/bash")
call append(1,"#########################################")
call append(2,"#Author:Aspen_Han")
call append(3,"#Email:aspen_han@sina.com")
call append(4,"#Date:" . strftime ("%Y-%m-%d"))
call append(5,"#Version:1.0")
call append(6,"#DESC:")
call append(7,"#########################################")
endf
map<F2> : call AddTitle() <cr>
[root@shell ~]# vim /tmp/new.txt
#!/usr/bin/bash
#########################################
#Author:Aspen_Han
#Email:aspen_han@sina.com
#Date:2019-10-15
#Version:1.0
#DESC:
#########################################

: call AddTitle()

5.Shell脚本执行方式

[root@shell ~]# ll /tmp/test.sh 
-rwxr-xr-x 1 root root 40 Oct 15 08:58 /tmp/test.sh
[root@shell ~]# cat /tmp/test.sh
echo "hello world"
print("Hello World")
[root@shell ~]# /tmp/test.sh
hello world
/tmp/test.sh: line 2: syntax error near unexpected token `"Hello World"'
/tmp/test.sh: line 2: `print("Hello World")'
[root@shell ~]# ll /tmp/test.sh
-rwxr-xr-x 1 root root 58 Oct 15 09:00 /tmp/test.sh
[root@shell ~]# cat /tmp/test.sh
#!/usr/bin/python
echo "hello world"
print("Hello World")
[root@shell ~]# /tmp/test.sh
  File "/tmp/test.sh", line 2
    echo "hello world"
                     ^
SyntaxError: invalid syntax

[root@shell ~]# cat /tmp/test.sh
#!/usr/bin/python
#echo "hello world"
print("Hello World")
[root@shell ~]# /tmp/test.sh
Hello World

二、变量

1.定义

变量是Shell传递数据的一种方法,简单来说就是用一个固定的字符串去表示不固定的值,便于后续引用;

2.命名规范

定义变量时建议使用:大写字母、小写字母、下划线几种符号组成,尽量以字母开头;

附:变量名最好具备一定的含义,不能以数字开头,变量名中不能存在"-"(中横线);
注:"="(等号)是为变量赋值,"="两边不能有空格;定义变量不要与系统命令出现冲突

3.Shell变量定义方式

  • 用户自定义变量:人为定义变量;
  • 系统环境变量:保存的是和系统操作环境相关的数据;
  • 位置参数变量:向脚本进行参数传递,变量名不能自定义,变量作用是固定的;
  • 预定义的变量:Bash中预先定义好的变量,变量名不能自定义,变量作用是固定的;

4.Shell变量定义

  • 用户自定义变量(仅对当前Shell有效)

step 01 定义变量

变量名="变量值"
[root@shell ~]# var1="hello world"  #为变量赋值时,如果变量值出现空格需要使用""(双引号)将其作为一个整体
[root@shell ~]# echo $var1
hello world

step 02 引用变量

$变量名${变量名}
[root@shell ~]# echo ${var1}_well   #引用变量时,使用{}(花括号)将变量名与字符串隔离开
hello world_well

step 03 查看变量

set|grep 变量名
set指令用于显示所有变量,包括自定义变量和环境变量
[root@shell ~]# set | grep var1
var1='hello world'

step 04 取消变量(仅在当前Shell有效)

unset 变量名
[root@shell ~]# unset var1
[root@shell ~]# echo $var1
注意事项:

"变量名"-双引号属于强引用,会解析引号中的变量;
'变量名'-单引号属于弱引用,不会解析引号中的变量;
[root@shell /var/log/nginx]# var=test123
[root@shell /var/log/nginx]# echo "$var"
test123
[root@shell /var/log/nginx]# echo '$var'
$var
[root@shell /var/log/nginx]# echo "\$var is $var"
$var is test123
[root@shell /var/log/nginx]# echo '$var' is "$var"
$var is test123
  • 系统环境变量(当前Shell以及子Shell有效)

step 01 使用系统已经定义好的环境变量

[root@shell /var/log/nginx]# echo $HOME $HOSTNAME $PWD
/root shell /var/log/nginx

step 02 人为定义环境变量

export变量,将自定义变量转换成环境变量
[root@shell ~]# var="hello world"
[root@shell ~]# vim /tmp/test.sh 
#!/usr/bin/bash
echo "$var"

[root@shell ~]# echo $var
hello world
[root@shell ~]# sh /tmp/test.sh 
[root@shell ~]# export var="hello world"
[root@shell ~]# cat /tmp/test.sh 
#!/usr/bin/bash
echo "$var"
[root@shell ~]# echo $var
hello world
[root@shell ~]# sh /tmp/test.sh 
hello world
  • 位置参数变量与预定义变量
$0 当前执行文件名称
$1 第一个位置参数
$2 第二个位置参数
$n 第n个位置参数(n为正整数)
$* 所有传递的位置参数
$@ 所有传递的位置参数

注:$*和$@的区别

$*和$@在不加""(引号)时 ,二者都是返回传入的参数;
$*和$@在添加""(引号)后,此时$*将参数作为一个字符串整体返回,$@把每个参数作为一个字符串返回;

$# 总共传递的参数个数
$$ 当前程序运行的PID
$? 上一个命令执行的返回结果

0表示上一个指令执行成功,非0表示上一个指令执行失败;
  • 将命令执行结果传递给变量(命令替换)
$()``

5.Shell变量赋值

除了自定义变量,以及系统内置变量,还可以使用read命令通过交互式传递变量
  • read语法
read -p "提示内容" 变量名
read -t n
超时时间(n为正整数,单位为s;)

6.Shell变量替换

变量 说明
${变量#匹配规则} 从头开始匹配,最短删除
${变量##匹配规则} 从头开始匹配,最长删除
${变量%匹配规则} 从尾开始匹配,最短删除
${变量%%匹配规则} 从尾开始匹配,最长删除
${变量/旧字符串/新字符串} 替换变量内旧字符串为新字符串,只能替换第一个
${变量//旧字符串/新字符串} 替换变量内旧字符串为新字符串,全部替换
[root@shell /scripts]# string="Bigdata process is Hadoop, Hadoop is open source project"
[root@shell /scripts]# echo "$string"
Bigdata process is Hadoop, Hadoop is open source project
[root@shell /scripts]# echo "${string#* }"
process is Hadoop, Hadoop is open source project
[root@shell /scripts]# echo "${string##* }"
project
[root@shell /scripts]# echo "${string%is*}"
Bigdata process is Hadoop, Hadoop 
[root@shell /scripts]# echo "${string%%is*}"
Bigdata process
[root@shell /scripts]# echo "${string/Hadoop/Linux}"
Bigdata process is Linux, Hadoop is open source project
[root@shell /scripts]# echo "${string//Hadoop/Linux}"
Bigdata process is Linux, Linux is open source project

6.Shell变量运算

Shell变量运算为整数运算,不支持小数运算。
运算声明:$(());$[];expr;
操作符 含义
num1 + num2 求和
num1 - num2 求差
num1 * num2 求积
num1 / num2 求商
num1 % num2 求余
[root@shell /scripts]# num1=10
[root@shell /scripts]# num2=5
[root@shell /scripts]# echo "$(($num1 + $num2))"
15
[root@shell /scripts]# echo "$(($num1 - $num2))"
5
[root@shell /scripts]# echo "$(($num1 * $num2))"
50
[root@shell /scripts]# echo "$(($num1 / $num2))"
2
[root@shell /scripts]# echo "$(($num1 % $num2))"
0

7.Shell取变量长度

${#变量名称}
[root@test /scripts]# Tele=1234567890
[root@test /scripts]# echo ${#Tele}
10
[root@test /scripts]# echo ${Tele} | tr -d '\n' | wc -c
10

三、IF语句(流程控制语句)

1.if基本概述

  • 单分支结构
if [ 判断条件 ];then

执行语句

fi

[root@shell /tmp]# cat test.sh 
#!/usr/bin/bash
if which $1 &>/dev/null;then
  echo "Command $1 is ok"
fi
[root@shell /tmp]# sh test.sh ls
Command ls is ok
[root@shell /tmp]# sh test.sh la
  • 双分支结构
if [ 判断条件 ];then

执行语句

else

执行语句

fi

[root@shell /tmp]# cat test.sh 
#!/usr/bin/bash
if which $1 &>/dev/null;then
  echo "Command $1 is ok."
else
  echo "Command $1 is error!"
fi
[root@shell /tmp]# sh test.sh ls
Command ls is ok.
[root@shell /tmp]# sh test.sh la
Command la is error!
  • 多分支结构
if [ 判断条件 ];then

执行语句

elif [ 判断条件 ];then

执行语句

...
else

执行语句

fi

[root@shell /tmp]# cat test.sh 
#!/usr/bin/bash
if grep $1 /etc/passwd &>/dev/null;then
  echo "User $1 is ok."
elif ls -d /home/$1 &>/dev/null;then
  echo "User $1 is error"
  echo "$1 Home dir is ok"
else 
  echo "User $1 is error"
  echo "$1 Home dir is error"
fi
[root@shell /tmp]# sh test.sh root
User root is ok.
[root@shell /tmp]# sh test.sh han
User han is error
han Home dir is ok
[root@shell /tmp]# sh test.sh Zheyu
User Zheyu is error
Zheyu Home dir is error

2.if文件比较

操作符 说明 示例
-e 如果文件或目录存在则为真 [ -e file ]
-s 如果文件存在且至少有一个字符则为真 [ -s file ]
-d 如果文件存在且为目录则为真 [ -d file ]
-f 如果文件存在且为普通文件则为真 [ -f file ]
-r 如果文件存在且可读则为真 [ -r file ]
-w 如果文件存在且可写则为真 [ -w file ]
-x 如果文件存在且可执行则为真 [ -x file ]

3.if整数比较

操作符 说明 示例
-eq 等于条件为真 [ 整数1 -eq 整数2 ]
-ne 不等于条件为真 [ 整数1 -ne 整数2 ]
-gt 大于条件为真 [ 整数1 -gt 整数2 ]
-ge 大于等于条件为真 [ 整数1 -ge 整数2 ]
-lt 小于条件为真 [ 整数1 -lt 整数2 ]
-le 小于等于条件为真 [ 整数1 -le 整数2 ]

4.if字符比较

字符串比对必须加""(双引号)
操作符 说明 示例 备注
== 字符串内容相同,条件为真 [ "$变量1" == "$变量2" ]
!= 字符串内容不同,条件为真 [ "$变量1" != "$变量2" ]
-z 字符串长度为0,条件为真 [ -z "$变量" ] 内容空则为真
-n 字符串条件不为0,条件为真 [ -n "$变量" ] 有内容则为真
> 字符串1大于字符串2,条件为真 [ "$变量1" > "$变量2" ]
< 字符串1小于字符串2,条件为真 [ "$变量1" < "$变量2" ]

5.if正则比较

使用正则比较,使用 [[ ]]
操作符:=~(匹配)

6.if多条件比较

  • 常规
    并且 [ 条件1 -a 条件2 ]
    或者 [ 条件1 -o 条件2 ]
  • 正则
    并且 [[ 条件1 && 条件2 ]]
    或者 [[ 条件1 || 条件2 ]]

四、case语句(流程控制语句)

case用来实现对程序流程的选择、循环等进行控制

1.语法

case 变量 in

值1)
命令序列 1
;;
值2)
命令序列 2
;;
值3)
命令序列 3
;;
*)
无匹配后命令序列

esac

[root@shell /scripts]# vim calculator.sh 
#!/usr/bin/bash
calsum () {
   case $2 in
       +)
           echo "$[ $1 + $3 ]"
           ;;
       -)
           echo "$[ $1 - $3 ]"
           ;;
       x)
           echo "$[ $1 * $3 ]"
           ;;
       /)
           echo "$[ $1 / $3 ]"
           ;;
       *)
       echo "您输入的运算符不正确"
   esac
calsum $1 $2 $3

[root@shell /scripts]# sh calculator.sh 4 x 5
20
[root@shell /scripts]# sh calculator.sh 4 + 5
9
[root@shell /scripts]# sh calculator.sh 4 - 5
-1
[root@shell /scripts]# sh calculator.sh 10 / 5
2

2.特点

case的本质上还是判断语句,但是它比if判断的更加准确;
case语句一般用来写服务的启动与停止的脚本以及自动化监控脚本

1.For语句

执行逻辑

语法

  • 语法1(shell 语法)
for 变量名 in [ 取值列表 ]
do

循环体

done

[root@shell /scripts]# vim for-01.sh
#!/usr/bin/bash
sum=0
for i in $(seq 100)
do
   sum=$(( $sum + $i ))
done
echo $sum
[root@shell /scripts]# sh for-01.sh 
5050
  • 语法2(C语言语法)
for ((变量名=初始值;取值范围;变量变化规则))
do

循环体

done

[root@shell /scripts]# vim for-01.sh
#!/usr/bin/bash
sum=0
for ((i=0;i<=100;i++))
do
   sum=$(( $sum + $i ))
done
echo $sum
[root@shell /scripts]# sh for-01.sh 
5050

分隔符

for循环的取值列表默认 以空格为分隔符
指定分隔符 IFS=分隔符
IFS=: #以冒号作为字段分隔符
IFS=:;" #以冒号,分号,双引号作为字段分隔符
IFS=$'\n' #以换行符作为字段分隔符
[root@shell /scripts]# vim for.sh
#!/usr/bin/bash
for i in $(cat /etc/hosts)
do
echo $i
done
echo -------------------------------
IFS=$'\n'
for i in $(cat /etc/hosts)
do
echo $i
done
[root@shell /scripts]# sh for.sh 
127.0.0.1
localhost
localhost.localdomain
localhost4
localhost4.localdomain4
::1
localhost
localhost.localdomain
localhost6
localhost6.localdomain6
-------------------------------
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

批量处理

"{ }&"并发处理标识符;
for 变量名 in [ 取值列表 ]
do

{
循环体
}&

done
wait

请注意:
批量处理中,不能将批量处理放在IF内执行;
批量处理与action语句连用时会产生错误``
#!/usr/bin/bash
echo "请输入您要检测的网段: "
while true
do
    read -p "IP Address: " Ip_Addr
    if [ -z $Ip_Addr ];then
       continue;
    elif [[ $Ip_Addr =~ ^((2[0-4][0-9]\.)|(25[0-5]\.)|(1[0-9][0-9]\.)|([1-9][0-9]\.)|([0-9]\.)){3}((2[0-4]
[0-9])|(25[0-5])|(1[0-9][0-9])|([1-9][0-9])|([0-9]))$ ]];then
       break;
    else
       echo "Input Error!"
    fi
done
for i in {1..254}
do
    {
    ping -c 1 -W 1 ${Ip_Addr%.*}.${i} &>/dev/null
    rc=$?
    if [ $rc -eq 0 ];then
        echo -e "${Ip_Addr%.}.{$i}   [ \e[32;1mOk\e[0m ]"
    fi
    }&
done
wait
exit

[root@shell /scripts]# time sh test_ip.sh 
请输入您要检测的网段: 
IP Address: 10.0.0.1
10.0.0.1.{1}   [ Ok ]
10.0.0.1.{201}   [ Ok ]
10.0.0.1.{254}   [ Ok ]

real    0m3.766s
user    0m0.140s
sys 0m0.355s

2.While语句

执行逻辑

while循环语句,只要条件成立就反复执行对应的命操作,直到条件为假或不成立

循环类型 特点
for 循环次数可控,读入文件时以空格为字段分隔符
while 通常用于一直循环,读入文件时以行为字段分隔符

语法

while 条件
do

循环体

done

读入文件
while read 变量
do

循环体

done<文件

注意事项

将文件内的值依次赋给指定变量
while读入文件是按行读入
[root@shell /scripts]# vim while.sh
#!/usr/bin/bash
mysql -uroot -p123456 -e "show databases;"| sed 1d >/tmp/.mariadb_dbname.tmp 2>/dev/null
while read i
do
  echo $i
done< /tmp/.mariadb_dbname.tmp
rm -rf /tmp/.mariadb_dbname.tmp

[root@shell /scripts]# sh while.sh 
information_schema
mysql
performance_schema
test
world

3.内置调出循环语句指令

[root@shell /scripts]# vim ecb.sh 
#!/usr/bin/bash
for i in $(seq 3)
do
  echo 123
  echo 456
done
echo TreeNB
[root@shell /scripts]# sh ecb.sh
123
456
123
456
123
456
TreeNB
  • exit
    作用:退出整个程序;当脚本运行至exit处时,直接退出脚本,剩余代码不再执行;
[root@shell /scripts]# vim ecb.sh 
#!/usr/bin/bash
for i in $(seq 3)
do
  echo 123
  exit
  echo 456
done
echo TreeNB
[root@shell /scripts]# sh ecb.sh
123
  • break
    作用:结束当前循环体,当脚本运行至break处时,跳出当前循环,执行循环后的剩余代码;

[root@shell /scripts]# vim ecb.sh 
#!/usr/bin/bash
for i in $(seq 3)
do
  echo 123
  break
  echo 456
done
echo TreeNB
[root@shell /scripts]# sh ecb.sh
123
TreeNB
  • continue
    作用:忽略本次循环剩余所有代码,直接进入下一次循环,直到循环结束,然后继续执行循环之后的代码

[root@shell /scripts]# vim ecb.sh 
#!/usr/bin/bash
for i in $(seq 3)
do
  echo 123
  continue
  echo 456
done
echo TreeNB
[root@shell /scripts]# sh ecb.sh
123
123
123
TreeNB

六、Shell函数

1.概述

  • 定义
    函数就是用于完成某些特定功能的代码块,你可以对它进行自定义命名,并且可以在脚本中任意位置使用这个函数。
调用自定义函数,仅需填写函数名即可;
  • 作用:
    1.使用函数可以代码模块化,便于代码的复用,并增加脚本的可读性。
    2.函数和变量类似,必须先定义才可以调用,若只定义函数但并未调用,则函数不会执行。

2.基本使用

定义函数

  • 方式1
函数名 () {

代码块

}

[root@shell /scripts]# vim function-01.sh
#!/usr/bin/bash
Display() {
    echo 123
}
  • 方式2
function 函数名 {

代码块

}

[root@shell /scripts]# vim function-01.sh
#!/usr/bin/bash
function Display {
    echo 123
}

调用函数
1.直接调用-函数名

[root@shell /scripts]# vim function-01.sh
#!/usr/bin/bash
function Display_1 {
    echo 123
}
Display_2() {
    echo 456
}
Display_1
echo ------------
Display_2
[root@shell /scripts]# sh function-01.sh 
123
------------
456

2.传参调用-函数名 \$1 \$2 \$3

[root@shell /scripts]# vim function-01.sh
#!/usr/bin/bash
function Display_1 {
    echo $1 $2 $3
}
Display_1 $1 $2 $3
[root@shell /scripts]# sh function-01.sh 4 5 6
4 5 6

3.参数传递

函数传参与脚本传参类似,都是使用位置参数的($1 $2 $3 $4 ...)方式
  • 使用变量方式传递固定值
[root@shell /scripts]# vim  function-01.sh 
#!/usr/bin/bash
function Display_1 {
    echo $num
}
num=20
Display_1
[root@shell /scripts]# sh function-01.sh 
20
  • 使用变量方式传递可变值
[root@shell /scripts]# vim  function-01.sh 
#!/usr/bin/bash
function Display_1 {
    echo $num
}
num=$1
Display_1
[root@shell /scripts]# sh function-01.sh 10
10
  • 传递多个位置参数
[root@shell /scripts]# vim  function-01.sh 
#!/usr/bin/bash
function Display_1 {
    echo $1
}
Display_1 $1
Display_1 $2
Display_1 $3
[root@shell /scripts]# sh function-01.sh 40 50 60
40
50
60
  • 传递多个函数参数
[root@shell /scripts]# vim  function-01.sh 
#!/usr/bin/bash
function Display_1 {
    echo $1 $2 $3
}
Display_1 $1 $2 $3
[root@shell /scripts]# sh function-01.sh 1 2 3
1 2 3

[root@shell /scripts]# vim  function-01.sh 
#!/usr/bin/bash
function Display_1 {
    echo $1 $1 $3
}
Display_1 $1 $2 $3
[root@shell /scripts]# sh function-01.sh 1 2 3
1 1 3
  • 将脚本位置参数与函数参数发生联动
[root@shell /scripts]# vim function-01.sh 
#!/usr/bin/bash
function Display_1 {
    echo $num_1 $num_2 $num_3
}
num_1=$1
num_2=$2
num_3=$3
Display_1
[root@shell /scripts]# sh function-01.sh 100 200 300
100 200 300

4.状态返回值

  • 作用
    Shell的函数返回值,也算是函数的退出状态。在shell中只有echo和return两种方式
1.return:使用return返回值,只能返回1-255的整数,函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1,0表示成功,1表示失败;
2.echo:使用echo返回值,可以返回任何字符串结果,通常用户返回数据,比如一个字符串值或者列表值;
[root@shell /scripts]# vim Game_Num_Func.sh 
#!/usr/bin/bash
id=0
num_1=$[ $RANDOM%100+1 ]
Check_Num() {
    if [ $num_2 -lt $num_1 ];then
        return 10
    elif [ $num_2 -gt $num_1 ];then
        return 20
    else
        return 30
    fi
}
Input_Num(){
    while true
    do
        read -p "请输入您的数字: " num_2
        if [ -z $num_2 ];then
           continue
        elif [ $num_2 == 'q' -o $num_2 == 'Q' ];then
           echo "退出游戏"
           exit
        elif [[ ! $num_2 =~ ^[0-9]+$ ]];then
           echo "非法输入,请重新输入"
           continue
        fi
        if [ $num_2 -ge 0 -a $num_2 -le 100 ];then
            break
        else
           echo "输入无效,请重新输入"
        fi
    done
clear
while true
do
    let id++
    Input_Num
    Check_Num
    rc=$?
    case $rc in
        10)
           echo "您的输入较小"
           ;;
        20)
           echo "您的输入较大"
           ;;
        *)
           break
    esac
done
echo "恭喜您猜中数字: $num_1"
echo "您一共猜了 $id 次,猜错 $[$id-1]次"

[root@shell /scripts]# sh Game_Num_Func.sh
请输入您的数字: 
请输入您的数字: qwe
非法输入,请重新输入
请输入您的数字: 123
输入无效,请重新输入
请输入您的数字: -1
非法输入,请重新输入
请输入您的数字: 50
您的输入较小
请输入您的数字: 75
您的输入较小
请输入您的数字: 88
您的输入较小
请输入您的数字: 95
您的输入较大
请输入您的数字: 91
您的输入较小
请输入您的数字: 92
您的输入较小
请输入您的数字: 93
恭喜您猜中数字: 93
您一共猜了 7 次,猜错 6次

七、其他

trap "" HUP INT TSTP
捕捉Ctrl+C,Ctrl+D,Ctrl+Z信号,保证脚本不被以上信号中断运行;
[root@test /scripts]# cat Jump_Server.sh 
#!/usr/bin/bash
lb01="10.0.0.15"
lb02="10.0.0.16"
web01="10.0.0.17"
web02="10.0.0.18"
Host_Dis(){
cat <<EOF
----------Host List----------
    1) lb01-10.0.0.15
    2) lb02-10.0.0.16
    3) web01-10.0.0.17
    4) web02-10.0.0.18
    h) HELP
-----------------------------
EOF
}
Host_Dis
while true
do
    trap "" HUP INT TSTP
    read -p "请选择您的操作: " Act
    case $Act in
        1)  
            echo "lb01正在连接......"
            sleep 1;
            ssh root@$lb01;
            ;;
        2)  
            echo "lb02正在连接......"
            sleep 1;
            ssh root@$lb02;
            ;;
        3)  
            echo "web01正在连接......"
            sleep 1;
            ssh root@$web01;
            ;;
        4)  
            echo "web02正在连接......"
            sleep 1;
            ssh root@$web02;
            ;;
        h)  
            Host_Dis
            ;;
        Quit)
            echo "程序退出......"
            exit 1;
            ;;
        *)
            echo "输入错误,请重新输入......"
            continue;
    esac
done 
action函数
action函数是系统内置函数,使用时需调用. /etc/init.d/functions
[root@test /scripts]# cat nginx_scripts.sh 
#!/usr/bin/bash
. /etc/init.d/functions
case $1 in 
start)
    /usr/sbin/nginx &>/dev/null
    rc_1=$?
    if [ $rc_1 -eq 0 ];then
        action "Nginx Starting:" /bin/true
    else    
        action "Nginx Starting:" /bin/false
    fi
    ;;
stop)
    /usr/sbin/nginx -s stop &>/dev/null
    rc_2=$?
    if [ $rc_2 -eq 0 ];then
        action "Nginx Stopping:" /bin/true
    else    
        action "Nginx Stopping:" /bin/false
    fi
    ;;
status)
    echo -e "Service nginx:";  [ -f /var/run/nginx.pid ] && echo -e "[ \e[32;1mRunning\e[0m ]" || echo -e "[ \e[31;1mStopped\e[0m ]"
    ;;
restart)
    /usr/sbin/nginx -s reload &>/dev/null
    rc_3=$?
    if [ $rc_3 -eq 0 ];then
        action "Nginx Restarting:" /bin/true
    else    
        action "Nginx Restarting:" /bin/false
    fi
    ;;
*)
    echo "Usage: /etc/sbin/nginx {start|stop|status|restart}"
esac