shell 脚本编程基础篇

一级标题

shell 脚本编程基础篇

二级标题

1.编程基础

Linus:Talk is cheap, show me the code

程序组成
程序:算法+数据结构
数据:是程序的核心
算法:处理数据的方式
数据结构:数据在计算机中的类型和组织方式

面向过程语言
 做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如
 果出现了情况B,做什么处理
 问题规模小,可以步骤化,按部就班处理
 以指令为中心,数据服务于指令
 C,shell

面向对象语言
 一种认识世界、分析世界的方法论。将万事万物抽象为各种对象
 类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合
 对象是类的具象,是一个实体
 问题规模大,复杂系统
 以数据为中心,指令服务于数据
 java,C#,python,golang等

编程语言
  
  计算机:运行二进制指令
  
  编程语言:人与计算机之间交互的语言。分为两种:低级语言和高级语言
  
  低级编程语言:
   
   机器:二进制的0和1的序列,称为机器指令。与自然语言差异太大,难懂、难写
   
   汇编:用一些助记符号替代机器指令,称为汇编语言
   如:ADD A,B 将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中
   汇编语言写好的程序需要汇编程序转换成机器指令
   汇编语言稍微好理解,即机器指令对应的助记符,助记符更接近自然语言
  
  高级编程语言:
  编译:高级语言-->编译器-->机器代码文件-->执行,如:C,C++
  解释:高级语言-->执行-->解释器-->机器代码,如:shell,python,php,JavaScript,perl

编程逻辑处理方式
   顺序执行
   选择执行
   循环执行

二级标题

2.脚本基本格式
shell 脚本的用途
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件

shell脚本基本结构

shell脚本编程:是基于过程式、解释执行的语言
编程语言的基本结构:
各种系统命令的组合
数据存储:变量、数组
表达式:a + b
控制语句:if
shell脚本:包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制

 #!/bin/bash
 #!/usr/bin/python
 #!/usr/bin/perl

创建shell脚本过程

第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列:#!

!/bin/bash

添加注释,注释以#开头
第二步:加执行权限
给予执行权限,在命令行上指定脚本的绝对或相对路径
第三步:运行脚本
直接运行解释器,将脚本作为解释器程序的参数运行

脚本注释规范
1、第一行一般为调用使用的语言
2、程序名,避免更改文件名为无法找到正确的文件
3、版本号
4、更改后的时间
5、作者相关信息
6、该程序的作用,及注意事项
7、最后是各版本的更新简要说明

参考文档:
https://zh.wikipedia.org/wiki/Hello_World

https://zh.wikipedia.org/wiki/Hello_World程序样例

[root@centos8 ~]#vim /data/hello.sh
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version:  1.0
# Date: 2017/06/01
# Author: wang
# Email:        @qq.com
# Website:           .com
# Description: This is the first script
# Copyright: 2017 
# License: GPL
# ------------------------------------------

经典写法

echo "hello, world"

流行写法

echo 'Hello, world!'

执行方法1

[root@centos8 ~]#bash /data/hello.sh

执行方法2

[root@centos8 ~]#cat /data/hello.sh | bash

执行方法3

[root@centos8 ~]#chmod +x /data/hello.sh

绝对路径

[root@centos8 ~]#/data/hello.sh

相法路径

[root@centos8 ~]#cd /data/;
[root@centos8 ~]#./hello.sh

执行方法4,本方法可以实现执行远程主机的shell脚本

[root@centos8 ~]#yum -y install httpd
[root@centos8 ~]#systemctl start httpd
[root@centos8 ~]#mv /data/hello.sh /var/www/html/
[root@centos8 ~]#curl -s http://10.0.0.8/hello.sh|bash

范例:备份脚本
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2019-12-20
#FileName: backup.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2019 All rights reserved
#********************************************************************
echo -e "\033[1;32mStarting backup...\033[0m"
sleep 2
cp -av /etc/ /data/etcdate +%F/
echo -e "\033[1;32mBackup is finished\033[0m"

脚本调试

只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本
  bash -n /path/to/some_script
 调试并执行
  bash -x /path/to/some_script

范例
 
 [root@centos8 script41]#cat -A f1.sh
 #!/bin/bash$
 #$
 #********************************************************************$
 #Author:^I^Iwangxiaochun$
 #QQ: ^I^I^I29308620$
 #Date: ^I^I^I2020-04-01$
 #FileNameM-oM-<M-^Z^I^If1.sh$
 #URL: ^I^I^Ihttp://www.magedu.com$
 #DescriptionM-oM-<M-^Z^I^IThe test script$
 #Copyright (C): ^I2020 All rights reserved$
 #********************************************************************$
 echo line1$
 hostnam$
 cat > test.txt <<EOF $
 aaa$
 bbb$
 ccc$
 EOF $
 $
 echo line22$
 [root@centos8 script41]#bash -n f1.sh
 f1.sh: line 20: warning: here-document at line 14 delimited by end-of-file
 (wanted `EOF')

总结:脚本错误常见的有三种

语法错误,会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的
命令错误,后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察
逻辑错误:只能使用 bash -x 进行观察

二级标题

3.变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

变量类型

内置变量,如:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE

用户自定义变量

不同的变量存放的数据不同,决定了以下
1. 数据存储方式
2. 参与的运算
3. 表示的数据范围

变量数据类型:
字符
数值:整型、浮点型,bash 不支持浮点数

编程语言分类
静态和动态语言

 静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c
 
 动态编译语言:不用事先声明,可随时改变类型,如:bash,Python

强类型和弱类型语言
 
 强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如java , c# ,
 python
 如:以下python代码
 print('magedu'+ 10) 提示出错,不会自动转换类型
 print('magedu'+str(10)) 结果为magedu10,需要显示转换类型
 
 弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会
 自动进行隐式类型转换;变量无须事先定义可直接调用
 如:bash ,php,javascript

Shell中变量命名法则
不能使程序中的保留字:如:if, for
只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反
见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM
统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName
变量名大写:STUDENT_NAME
局部变量小写
函数名小写

变量定义和引用

 变量的生效范围等标准划分变量类型
 
 普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell
 进程均无效
 
 环境变量:生效范围为当前shell进程及其子进程
 
 本地变量:生效范围为当前shell进程中某代码片断,通常指函数

 变量赋值:
  name='value'

  value 可以是以下多种形式
   直接字串:name='root'
   变量引用:name="$USER"
   命令引用:name=`COMMAND` 或者 name=$(COMMAND)

   注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚
   本结束,也会自动删除

变量引用:
$name
${name}

  弱引用和强引用
   "$name " 弱引用,其中的变量引用会被替换为变量值
   '$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

 范例
  [root@centos8 ~]#TITLE='cto'
  [root@centos8 ~]#echo $TITLE
  cto
  [root@centos8 ~]#echo I am $TITLE
  I am cto
  [root@centos8 ~]#echo "I am $TITLE"
  I am cto

  [root@centos8 ~]#echo 'I am $TITLE'
  I am $TITLE
  [root@centos8 ~]#NAME=$USER
  [root@centos8 ~]#echo $NAME
  root
  [root@centos8 ~]#USER=`whoami`
  [root@centos8 ~]#echo $USER
  root

  [root@centos8 ~]#FILE=`ls /run`
  [root@centos8 ~]#echo $FILE
  agetty.reload atd.pid auditd.pid autofs.fifo-misc autofs.fifo-net console
  cron.reboot cryptsetup dbus faillock fsck initctl initramfs lock log mount
  NetworkManager plymouth rsyslogd.pid screen sepermit setrans sshd.pid sssd.pid
  sudo systemd tmpfiles.d tuned udev user utmp vmware

  [root@centos8 ~]#FILE=/etc/*
  [root@centos8 ~]#echo $FILE
  /etc/adjtime /etc/aliases /etc/alternatives /etc/anacrontab /etc/at.deny
  /etc/audit /etc/authselect /etc/autofs.conf /etc/autofs_ldap_auth.conf
  
  [root@centos8 ~]#NAMES="wang
  > zhang
  > zhao
  > li"
  [root@centos8 ~]#echo $NAMES
  wang zhang zhao li
  [root@centos8 ~]#echo "$NAMES"
  wang
  zhang
  zhao
  li

 范例:变量的间接赋值和引用 
  [root@centos8 ~]#TITLE=cto
  [root@centos8 ~]#NAME=wang
  [root@centos8 ~]#TITLE=$NAME
  [root@centos8 ~]#echo $NAME
  wang
  [root@centos8 ~]#echo $TITLE
  wang
  [root@centos8 ~]#NAME=mage
  [root@centos8 ~]#echo $NAME
  mage
  [root@centos8 ~]#echo $TITLE
  wang

 范例:利用变量实现动态命令
  [root@centos8 ~]#CMD=hostname
  [root@centos8 ~]#$CMD
  centos8.wangxiaochun.com

 范例:显示系统信息
  [root@centos8 scripts]#cat systeminfo.sh
  #!/bin/bash
  #
  #********************************************************************
  #Author: wangxiaochun
  #QQ: 29308620
  #Date: 2019-12-23
  #FileName: systeminfo.sh
  #URL: http://www.magedu.com
  #Description: Show system information
  #Copyright (C): 2019 All rights reserved
  #********************************************************************
  RED="\E[1;31m"
  GREEN="\E[1;32m"
  END="\E[0m"
  echo -e  "$GREEN----------------------Host systeminfo--------------------$END"
  echo -e  "HOSTNAME:   $RED`hostname`$END"
  echo -e  "IPADDR:    $RED` ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]
  {1,3}' |head -n1`$END"
  echo -e  "OSVERSION:   $RED`cat /etc/redhat-release`$END"
  echo -e  "KERNEL:    $RED`uname -r`$END"
  echo -e  "CPU:     $RED`lscpu|grep 'Model name'|tr -s ' '|cut -d : -f2`$END"
  echo -e  "MEMORY:    $RED`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"
  echo -e  "DISK:     $RED`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$END"
  echo -e  "$GREEN---------------------------------------------------------$END"



  [root@centos8 scripts]#cat systeminfo.sh
  #!/bin/bash
  #
  #********************************************************************
  #Author: wangxiaochun
  #QQ: 29308620
  #Date: 2019-12-23
  #FileName: systeminfo.sh
  #URL: http://www.magedu.com
  #Description: Show system information
  #Copyright (C): 2019 All rights reserved
  #********************************************************************
  RED="\E[1;31m"
  GREEN="echo -e \E[1;32m"
  END="\E[0m"
  $GREEN----------------------Host systeminfo--------------------$END
  echo -e  "HOSTNAME:   $RED`hostname`$END"
  echo -e  "IPADDR:    $RED` ifconfig eth0|grep -Eo '([0-9]{1,3}\.){3}[0-9]
  {1,3}' |head -n1`$END"
  echo -e  "OSVERSION:   $RED`cat /etc/redhat-release`$END"
  echo -e  "KERNEL:    $RED`uname -r`$END"
  echo -e  "CPU:     $RED`lscpu|grep 'Model name'|tr -s ' '|cut -d : -f2`$END"
  echo -e  "MEMORY:    $RED`free -h|grep Mem|tr -s ' ' : |cut -d : -f2`$END"
  echo -e  "DISK:     $RED`lsblk |grep '^sd' |tr -s ' ' |cut -d " " -f4`$END"
  $GREEN---------------------------------------------------------$END

环境变量

   可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
   
   一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
   
   一般只在系统配置文件中使用,在脚本中较少使用

  变量声明和赋值
   #声明并赋值
   export name=VALUE
   declare -x name=VALUE
   #或者分两步实现
   name=VALUE
   export name

  显示所有环境变量:
    env
    printenv
    export
    declare -x

   删除变量:
    unset name

   bash内建的环境变量 
    PATH
    SHELL
    USER
    UID
    HOME
    PWD
    SHLVL #shell的嵌套层数,即深度
    LANG
    MAIL
    HOSTNAME
    HISTSIZE_       #下划线 表示前一命令的最后一个参数

只读变量
只读变量:只能声明定义,但后续不能修改和删除,即常量
声明只读变量:
readonly name
declare  -r name

查看只读变量
readonly [-p]
declare -r

范例
[root@centos8 ~]#readonly PI=3.14159
[root@centos8 ~]#echo $PI
3.14159
[root@centos8 ~]#PI=3.14
-bash: PI: readonly variable
[root@centos8 ~]#unset PI
-bash: unset: PI: cannot unset: readonly variable
[root@centos8 ~]#echo $PI
3.14159
[root@centos8 ~]#exit
logout
[root@centos8 ~]#echo $PI
[root@centos8 ~]#

位置变量
位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0 命令本身,包括路径
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异

清空所有位置变量
set --

        范例:
         [root@centos8 ~]#cat /data/scripts/arg.sh
         #!/bin/bash
         #
         #********************************************************************
         #Author: wangxiaochun
         #QQ: 29308620
         #Date: 2020-04-01
         #FileName: arg.sh
         #URL: http://www.magedu.com
         #Description: The test script
         #Copyright (C): 2020 All rights reserved
         #********************************************************************
         echo "1st arg is $1"
         echo "2st arg is $2"
         echo "3st arg is $3"
         echo "10st arg is ${10}"
         echo "11st arg is ${11}"
         echo "The number of arg is $#"
         echo "All args are $*"
         echo "All args are $@"
         echo "The scriptname is `basename $0`"

          [root@centos8 ~]#bash /data/scripts/arg.sh {a..z}
          1st arg is a
          2st arg is b
          3st arg is c
          10st arg is j
          11st arg is k
          The number of arg is 26
          All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
          All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
          The scriptname is arg.sh


        范例 删库跑路之命令rm的安全实现
         [root@centos8 ~]#cat /data/scripts/rm.sh
         #!/bin/bash
         #
         #********************************************************************
         #Author: wangxiaochun
         #QQ: 29308620
         #Date: 2020-04-01
         #FileName: /data/scripts/rm.sh
         #URL: http://www.magedu.com
         #Description: The test script
         #Copyright (C): 2020 All rights reserved
         #********************************************************************
         WARNING_COLOR="echo -e \E[1;31m"
         END="\E[0m"
         DIR=/tmp/`date +%F_%H-%M-%S`
         mkdir $DIR
         mv  $*  $DIR
         ${WARNING_COLOR}Move $* to $DIR $END
         [root@centos8 ~]#chmod a+x /data/scripts/rm.sh
         [root@centos8 ~]#alias rm='/data/scripts/rm.sh'
         [root@centos8 ~]#touch {1..10}.txt
         [root@centos8 ~]#rm *.txt
         Move 10.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt to /tmp/2020-
         04-01_15-15-28


        范例:$*和$@的区别
         [root@centos8 scripts]#cat f1.sh
         #!/bin/bash
         echo "f1.sh:all args are $@"
         echo "f1.sh:all args are $*"
         ./file.sh "$*"
         [root@centos8 scripts]#cat f2.sh
         #!/bin/bash
         echo "f2.sh:all args are $@"
         echo "f2.sh:all args are $*"
         ./file.sh "$@"
         [root@centos8 scripts]#cat file.sh
         #!/bin/bash
         echo "file.sh:1st arg is $1"
         [root@centos8 scripts]#./f1.sh a b c
         f1.sh:all args are a b c
         f1.sh:all args are a b c
         file.sh:1st arg is a b c
         [root@centos8 scripts]#./f2.sh a b c
         f2.sh:all args are a b c
         f2.sh:all args are a b c
         file.sh:1st arg is a

退出状态码变量
当我们浏览网页时,有时会看到下图所显示的数字,表示网页的错误信息,我们称为状态码,在shell脚
本中也有相似的技术表示程序执行的相应状态。

进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255

 $?的值为0 #代表成功
 $?的值是1到255  #代表失败

范例:
 [root@centos8 scripts]#curl http://www.wangxiaochun.com &> /dev/null
 [root@centos8 scripts]#echo $?

注意:
              
 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
              
 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

展开命令行
展开命令执行顺序
把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明 ~
命令替换$() 和 ``
再次把命令行分成命令词
展开文件通配*、?、[abc]等等
准备I/0重导向 <、>
运行命令

反斜线(\)会使随后的字符按原意解释

脚本安全和 set
set 命令:可以用来定制 shell 环境
$- 变量
h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选
项关闭
i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,
在脚本中,i选项是关闭的
m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
B:braceexpand,大括号扩展
H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的
一个历史命令,“!n”返回第 n 个历史命令

范例
[root@centos8 ~]#echo $-
himBHs
[root@centos8 ~]#set +h
[root@centos8 ~]#echo $-
imBHs
[root@centos8 ~]#hash
-bash: hash: hashing disabled

 [root@centos8 ~]#echo {1..10}
 1 2 3 4 5 6 7 8 9 10
 [root@centos8 ~]#echo $-
 imBHs
 [root@centos8 ~]#set +B
 [root@centos8 ~]#echo $-
 imHs
 [root@centos8 ~]#echo {1..10}
 {1..10}  

set 命令实现脚本安全
-u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset
-e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit
-o option 显示,打开或者关闭选项
显示选项:set -o
打开选项:set -o 选项
关闭选项:set +o 选项
-x 当执行命令时,打印命令及其参数,类似 bash -x

格式化输出 printf
常用格式替换符

说明:%s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字
符宽,- 表示左对齐

常用转义字符

范例
[root@centos8 ~]#printf "%s\n" 1 2 3 4
1
2
3
4
[root@centos8 ~]#printf "%f\n" 1 2 3 4
1.000000
2.000000
3.000000
4.000000

.2f 表示保留两位小数

[root@centos8 ~]#printf "%.2f\n" 1 2 3 4
1.00
2.00
3.00
4.00
[root@centos8 ~]#printf "(%s)" 1 2 3 4;echo
(1)(2)(3)(4)
[root@centos8 ~]#printf " (%s) " 1 2 3 4;echo ""
(1) (2) (3) (4)
[root@centos8 ~]#printf "(%s)\n" 1 2 3 4
(1)
(2)
(3)
(4)
[root@centos8 ~]#printf "%s %s\n" 1 2 3 4
1 2
3 4
[root@centos8 ~]#printf "%s %s %s\n" 1 2 3 4
1 2 3
4

%-10s 表示宽度10个字符,左对齐

[root@centos8 ~]#printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70
女 18 50
姓名   性别   年龄  体重
小明   男     20   70
小红   女     18   50

[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" $VAR
welcome
to
Magedu
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" "$VAR"
welcome to Magedu

二级标题

4.运算
算术运算
shell 支持算术运算,但只支持整数,不支持小数
bash中的算术运算
+

/
% 取模,即取余数,示例:9%4=1,5%3=2
** 乘方

乘法符号有些场景中需要转义

实现算术运算:
(1) let var=算术表达式
(2) ((var=算术表达式)) 和上面等价
(3) var=$[算术表达式]
(4) var=$((算术表达式))
(5) var=$(expr arg1 arg2 arg3 ...)
(6) declare –i var = 数值
(7) echo '算术表达式' | bc

内建的随机数生成器变量:
$RANDOM  取值范围:0-32767

范例

生成 0 - 49 之间随机数

echo $[$RANDOM%50]

随机字体颜色

[root@centos8 ~]#echo -e "\033[1;$[RANDOM%7+31]hello\033[0m"
magedu

增强型赋值
+= i+=10 相当于 i=i+10
-= i-=j  相当于 i=i-j
*=
/=
%=
++ i++,++i  相当于 i=i+1
-- i--,--i  相当于 i=i-1

范例
[root@centos8 ~]#let i=10*2
[root@centos8 ~]#echo $i
20
[root@centos8 ~]#((j=i+10))
[root@centos8 ~]#echo $j
30

自加3后自赋值

let count+=3
[root@centos8 ~]#i=10
[root@centos8 ~]#let i+=20 #相当于let i=i+20
[root@centos8 ~]#echo $i
30
[root@centos8 ~]#j=20
[root@centos8 ~]#let i*=j
[root@centos8 ~]#echo $i
600

自增,自减

let var+=1
let var++
let var-=1
let var--
[root@centos8 ~]#unset i j ; i=1; let j=i++; echo "i=$i,j=$j"
i=2,j=1
[root@centos8 ~]#unset i j ; i=1; let j=++i; echo "i=$i,j=$j"
i=2,j=2

[root@centos8 ~]#expr 2 * 3
expr: syntax error: unexpected argument ‘anaconda-ks.cfg’
[root@centos8 ~]#ls
anaconda-ks.cfg
[root@centos8 ~]#expr 2 \* 3
6

[root@centos8 ~]#echo "scale=3;20/3"|bc
6.666

[root@centos8 ~]#i=10
[root@centos8 ~]#j=20
[root@centos8 ~]#declare -i result=i*j
[root@centos8 ~]#echo $result
200

今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
[root@centos8 scripts]#cat chook_rabbit.sh
#!/bin/bash
HEAD=$1
FOOT=$2
RABBIT=$(((FOOT-HEAD-HEAD)/2))
CHOOK=$[HEAD-RABBIT]
echo RABBIT:$RABBIT
echo CHOOK:$CHOOK
[root@centos8 scripts]#./chook_rabbit.sh 30 80
RABBIT:10
CHOOK:20
[root@centos8 scripts]#

算出所有人的年龄总和
[root@centos8 ~]#cat /data/nianling.txt
xiaoming=20
xiaohong=18
xiaoqiang=22
[root@centos8 ~]#cut -d"=" -f2 /data/nianling.txt|tr '\n' + | grep -Eo ".[0-
9]"|bc
60
[root@centos8 ~]#grep -Eo "[0-9]+" /data/nianling.txt | tr '\n' + | grep -Eo ".

[0-9]"|bc
60
逻辑运算

true, false
1, 0

与:&:和0相与,结果为0,和1相与,结果保留原值
1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0

或:|:和1相或结果为1,和0相或,结果保留原值
1 或 1 = 1
  1 或 0 = 1
0 或 1 = 1
0 或 0 = 0

非:!
! 1 = 0 ! true
! 0 = 1 ! false

异或:^
异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出
另一个值Y
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

范例
[root@centos8 ~]#true
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#false
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! true
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! false
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
x=20,y=10
[root@centos8 ~]#x=10;y=20;x=$[xy];y=$[xy];x=$[x^y];echo x=$x,y=$y
x=20,y=10

短路运算

短路与
CMD1 短路与 CMD2
第一个CMD1结果为真 (1),第二个CMD2必须要参与运算,才能得到最终的结果
第一个CMD1结果为假 (0),总的结果必定为0,因此不需要执行CMD2

短路或
CMD1 短路或 CMD2
第一个CMD1结果为真 (1),总的结果必定为1,因此不需要执行CMD2
第一个CMD1结果为假 (0),第二个CMD2 必须要参与运算,,才能得到最终的结果

二级标题

5.条件测试
条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以便用在条件性环境下进行执行
若真,则状态码变量 $? 返回0
若假,则状态码变量 $? 返回1
条件测试命令

条件测试命令
test EXPRESSION
[ EXPRESSION ] #和test 等价,建议使用 [ ]
[[ EXPRESSION ]]
注意:EXPRESSION前后必须有空白字符

变量测试
 -v VAR 变量VAR是否设置
 -R VAR 变量VAR是否设置并引用

范例
  [root@centos8 ~]#unset x
  [root@centos8 ~]#test -v x
  [root@centos8 ~]#echo $?
  1
  [root@centos8 ~]#x=10
  [root@centos8 ~]#test -v x
  [root@centos8 ~]#echo $?
  0
  [root@centos8 ~]#y=
  [root@centos8 ~]#test -v y
  [root@centos8 ~]#echo $?
  0

 #注意 [ ] 需要空格,否则会报下面错误
  [root@centos8 ~]#[-v y]
  -bash: [-v: command not found
  [root@centos8 ~]#[ -v y ]
  [root@centos8 ~]#echo $?
  0

数值测试
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于

范例
[root@centos8 ~]#i=10
[root@centos8 ~]#j=8
[root@centos8 ~]#[ $i -lt $j ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ $i -gt $j ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ i -gt j ]
-bash: [: i: integer expression expected

字符串测试
test和 [ ]用法
-z STRING 字符串是否为空,没定义或空为真,不空为假,
-n STRING 字符串是否不空,不空为真,空为假
  STRING  同上
STRING1 = STRING2 是否等于,注意 = 前后有空格
STRING1 != STRING2 是否不等于

ascii码是否大于ascii码
< 是否小于
[[]] 用法,建议,当使用正则表达式或通配符使用,一般情况使用 [ ]
== 左侧字符串是否和右侧的PATTERN相同
注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
注意: 此表达式用于[[ ]]中;扩展的正则表达式

范例
[root@centos8 ~]#unset str
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=""
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=" "
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -n "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#unset str
[root@centos8 ~]#[ -n "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#str=magedu
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=magedu
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str1=magedu
[root@centos8 ~]#str2=mage
[root@centos8 ~]#[ $str1 = $str2 ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#str2=magedu
[root@centos8 ~]#[ $str1 = $str2 ]
[root@centos8 ~]#echo $?
0

在比较字符串时,建议变量放在“ ”中
[root@centos8 ~]#[ "$NAME" ]
[root@centos8 ~]#NAME="I love linux"
[root@centos8 ~]#[ $NAME ]
-bash: [: love: binary operator expected
[root@centos8 ~]#[ "$NAME" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ I love linux ]
-bash: [: love: binary operator expected

通配符

[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#FILE=test.txt
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[[ "$FILE" != *.log ]]
[root@centos8 ~]#echo $?
0

正则表达式

[root@centos8 ~]#[[ "$FILE" =~ .log$ ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" =~ .log$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#N=100
[root@centos8 ~]#[[ "$N" =~ [1]+$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#N=Magedu10
[root@centos8 ~]#[[ "$N" =~ [2]+$ ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#IP=1.2.3.4
[root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#IP=1.2.3.4567
[root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}
([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
[root@centos8 ~]#echo $?
1

通配符

[root@centos8 ~]#NAME="linux1"
[root@centos8 ~]#[[ "$NAME" == linux* ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[[ "$NAME" == "linux" ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#NAME="linux
"
[root@centos8 ~]#[[ "$NAME" == "linux*" ]]
[root@centos8 ~]#echo $?
0

结论:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*, 需要加“” 或转义

文件测试
-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

范例
[root@centos8 ~]#[ -a /etc/nologin ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! [ -a /etc/nologin ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -d /etc ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -d /etc/issue ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -L /bin ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -L /bin/ ]
[root@centos8 ~]#echo $?
1

文件权限测试
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

注意:最终结果由用户对文件的实际权限决定,而非文件属性决定

范例
[root@centos8 ~]#[ -w /etc/shadow ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x /etc/shadow ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -w test.txt ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#chattr +i test.txt
[root@centos8 ~]#lsattr test.txt
----i-------------- nianling.txt
[root@centos8 ~]#[ -w test.txt ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#chattr -i test.txt
[root@centos8 ~]#[ -w test.txt ]
[root@centos8 ~]#echo $?
0

文件属性测试
-s FILE #是否存在且非空
-t fd #fd 文件描述符是否在某终端已经打开
-N FILE #文件自从上一次被读取之后是否被修改过
-O FILE #当前有效用户是否为文件属主
-G FILE #当前有效用户是否为文件属组
FILE1 -ef FILE2 #FILE1是否是FILE2的硬链接
FILE1 -nt FILE2 #FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2 #FILE1是否旧于FILE2

关于 () 和 {}
CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash
搜索(list)
{ list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list; }

范例: () 和 {}
[root@centos8 ~]#name=mage;(echo $name;name=wang;echo $name );echo $name
mage
wang
mage
[root@centos8 ~]#name=mage;{ echo $name;name=wang;echo $name; } ;echo $name
mage
wang
wang
[root@centos8 ~]#umask
0022
[root@centos8 ~]#(umask 066;touch f1.txt)
[root@centos8 ~]#ll f1.txt
-rw------- 1 root root 0 Dec 23 16:58 f1.txt
[root@centos8 ~]#umask
0022
[root@centos8 ~]#( cd /data;ls )
test.log
[root@centos8 ~]#pwd
/root
[root@centos8 ~]#{ cd /data;ls; }
test.log
[root@centos8 data]#pwd
/data
[root@centos8 data]#

()会开启子shell

[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#( echo $BASHPID;sleep 100)
1979
[root@centos8 ~]#pstree -p
├─sshd(719)───sshd(1906)───sshd(1919)─┬─bash(1920)───bash(1979)───sleep(1980)

{ } 不会开启子shell

[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#{ echo $BASHPID; }
1920

组合测试条件
第一种方式 [ ]
[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为

[ ! EXPRESSION ] 取反

说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持

范例
[root@centos8 ~]#ll /data/scrips/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#chmod +x /data/scripts/test.sh
[root@centos8 ~]#ll /data/scripts/test.sh
-rwxr-xr-x 1 root root 382 Dec 23 09:32 /data/script40/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#chmod -x /data/scripts/test.sh
[root@centos8 ~]#ll /data/scripts/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
[root@centos8 ~]#[ -f $FILE -o -x $FILE ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x $FILE ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ ! -x $FILE ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#! [ -x $FILE ]
0

第二种方式 [[ ]]

COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE

如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2

! COMMAND  #非,取反

范例
[root@centos8 ~]#test "A" = "B" && echo "Strings are equal"
[root@centos8 ~]#test "A"-eq "B" && echo "Integers are equal"
[root@centos8 ~]#[ "A" = "B" ] && echo "Strings are equal"
[root@centos8 ~]#[ "$A" -eq "$B" ] && echo "Integers are equal"
[root@centos8 ~]#[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
[root@centos8 ~]#[ -z "$HOSTNAME" -o "$HOSTNAME" = "localhost.localdomain" ]&&
hostname www.magedu.com
[root@centos8 ~]#id wang &> /dev/null ||  useradd wang
[root@centos8 ~]#id zhang &> /dev/null ||  useradd zhang
[root@centos8 ~]#getent passwd zhang
zhang❌1002:1002::/home/zhang:/bin/bash
[root@centos8 ~]#grep -q no_such_user /etc/passwd || echo 'No such user'
No such user

[root@centos8 ~]#[ -f “$FILE” ] && [[ “$FILE”=~ .*\.sh$ ]] && chmod +x $FILE
[root@centos8 ~]#ping -c1 -W1 172.16.0.1 &> /dev/null && echo '172.16.0.1 is
up' || (echo '172.16.0.1 is unreachable'; exit 1)
172.16.0.1 is up
[root@centos8 ~]#IP=10.0.0.111;ping -c1 -W1 $IP &> /dev/null && echo $IP is up
|| echo $IP is down
10.0.0.111 is down
[root@centos8 ~]#IP=10.0.0.1;ping -c1 -W1 $IP &> /dev/null && echo $IP is up ||
echo $IP is down
10.0.0.1 is up

范例:&& 和 || 组合使用
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist"
wang is exist
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null || echo "$NAME is not
exist"
wange is not exist
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null && echo "$NAME is exist" ||
echo "$NAME is not exist"
wange is not exist
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist" ||
echo "$NAME is not exist"
wang is exist
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist" ||
echo "$NAME is not exist"
wang is exist
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null || echo "$NAME is not exist"
&& echo "$NAME is exist"
wang is exist
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null || echo "$NAME is not
exist" && echo "$NAME is exist"
wange is not exist
wange is exist

结论:如果&& 和 || 混合使用,&& 要在前,|| 放在后

[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null && echo "$NAME is exist" ||
useradd $NAME
[root@centos8 ~]#id wange
uid=1002(wange) gid=1002(wange) groups=1002(wange)
[root@centos8 ~]#NAME=wangge; id $NAME &> /dev/null && echo "$NAME is exist" ||
( useradd $NAME; echo $NAME is created )
wangge is created
[root@centos8 ~]#id wangge
uid=1003(wangge) gid=1003(wangge) groups=1003(wangge)
[root@centos8 ~]#NAME=wanggege; id $NAME &> /dev/null && echo "$NAME is exist"
|| { useradd $NAME; echo $NAME is created; }
wanggege is created

范例:网络状态判断
[root@centos8 ~]#cat /data/scripts/ping.sh
#!/bin/bash
IP=172.16.0.1
ping -c1 -W1 $IP &> /dev/null && echo "$IP is up" || {  echo "$IP is
unreachable"; exit; }
echo "Script is finished"
[root@centos8 ~]#bash /data/scripts/ping.sh
172.16.0.1 is up
Script is finished

磁盘空间的判断
[root@centos8 ~]#cat /data/script40/disk_check.sh
#!/bin/bash
WARNING=80
SPACE_USED=df|grep '^/dev/sd'|tr -s ' ' %|cut -d% -f5|sort -nr|head -1
[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $SPACE_USED,will be full"
| mail -s diskwaring root

磁盘空间和Inode号的检查脚本
 [root@centos8 scripts]#cat disk_check.sh
 #!/bin/bash
 WARNING=80
 SPACE_USED=`df | grep '^/dev/sd'|grep -oE '[0-9]+%'|tr -d %| sort -nr|head -1`
 INODE_USED=`df -i | grep '^/dev/sd'|grep -oE '[0-9]+%'|tr -d %| sort -nr|head
 -1`
 [ "$SPACE_USED" -gt $WARNING -o "$INODE_USED" -gt $WARNING ] && echo "DISK
 USED:$SPACE_USED%, INODE_USED:$INODE_USED,will be full" | mail -s "DISK Warning"
 [email protected] 

使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变
量,所有剩余单词都被分配给最后一个变量

常见选项:
 -p  指定要显示的提示
 -s  静默输入,一般用于密码
 -n N 指定输入的字符长度N
 -d '字符'  输入结束符
 -t N TIMEOUT为N秒

范例 
  [root@centos8 ~]#read
  wangxiaochun
  [root@centos8 ~]#echo $REPLY
  wangxiaochun
  [root@centos8 ~]#read NAME TITLE
  wang cto
  [root@centos8 ~]#echo $NAME
  wang
  [root@centos8 ~]#echo $TITLE
  cto
  [root@centos8 ~]#echo magedu | read NAME
  [root@centos8 ~]#echo $NAME
  [root@centos8 ~]#echo magedu | { read NAME; echo $NAME; }
  magedu
  [root@centos8 ~]#read -p "Please input your name: " NAME
  Please input your name: wang
  [root@centos8 ~]#echo $NAME
  wang

面试题 read和输入重定向
 [root@centos8 scripts]#cat test.txt
 1 2
 [root@centos8 scripts]#read i j < test.txt ; echo i=$i j=$j
 i=1 j=2
 [root@centos8 scripts]#echo 1 2 | read x y ; echo x=$x y=$y
 x= y=
 [root@centos8 ~]#echo 1 2 | ( read x y ; echo x=$x y=$y )
 x=1 y=2
 [root@centos8 ~]#echo 1 2 | { read x y ; echo x=$x y=$y; }
 x=1 y=2
 [root@centos8 ~]#man bash


 [root@centos8 scripts]#cat read.sh
 #!/bin/bash
 read -p "Are you rich?yes or no: " ANSWER
 [[ $ANSWER =~ ^[Yy]|[Yy][Ee][Ss]$ ]] && echo "You are rich" || echo "Good Good
 Study,Day Day Up!"

鸡兔同笼算法,今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
 [root@centos8 ~]#cat /data/script40/chook_rabbit.sh
 #!/bin/bash
 read -p "请输入头的数量: " HEAD
 read -p "请输入脚的数量: " FOOT
 RABBIT=$[FOOT/2-HEAD]
 CHOOK=$[HEAD-RABBIT]
 echo "兔子: " $RABBIT
 echo "鸡: " $CHOOK

实现运维工作菜单
 [root@centos8 scripts]#cat work_menu.sh
 #!/bin/bash
 echo -en "\E[$[RANDOM%7+31];1m"
 cat <<EOF
 请选择:
 1)备份数据库
 2)清理日志
 3)软件升级
 4)软件回滚
 5)删库跑路
 EOF
 echo -en '\E[0m'
 read -p  "请输入上面数字1-5: " MENU
 [ $MENU -eq 1 ] && ./backup.sh
 [ $MENU -eq 2 ] && echo "清理日志"
 [ $MENU -eq 3 ] && echo "软件升级"
 [ $MENU -eq 4 ] && echo "软件回滚"
 [ $MENU -eq 5 ] && echo "删库跑路"

二级标题

6.配置用户环境
按生全局配置效范围划分两类
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc

个人配置:
~/.bash_profile
~/.bashrc

shell登录两种方式分类
交互式登录
直接通过终端输入账号密码登录
使用 su - UserName 切换的用户
配置文件执行顺序:
/etc/profile.d/*.sh
/etc/bashrc
/etc/profile
/etc/bashrc  #此文件执行两次
.bashrc
.bash_profile

注意:文件之间的调用关系,写在同一个文件的不同位置,将影响文件的执行顺序

非交互式登录
u UserName
图形界面下打开的终端
执行脚本
任何其它的bash实例

/etc/profile.d/*.sh
/etc/bashrc
.bashrc

按功能划分分类
profile类
profile类为交互式登录的shell提供配置全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile

功用:
(1) 用于定义环境变量
(2) 运行命令或脚本

Bashrc类
 bashrc类:为非交互式和交互式登录的shell提供配置
 全局:/etc/bashrc
 个人:~/.bashrc
 功用:
 (1) 定义命令别名和函数
 (2) 定义本地变量

编辑配置文件生效
修改profile和bashrc文件后需生效两种方法:
1. 重新启动shell进程
2. source|. 配置文件

Bash 退出任务
保存在~/.bash_logout文件中(用户),在退出登录shell时运行
功能:
创建自动备份
清除临时文件

二级标题

7.条件选择
if 语句
if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else
COMMANDS; ] fi

单分支
if 判断条件;then
  条件为真的分支代码
fi

双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi

多分支
if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fi

说明:
多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
if 语句可嵌套

范例

根据命令的退出状态来执行命令

if ping -c1 -W2 station1 &> /dev/null; then  
echo 'station1 is UP'
elif  grep -q 'station1' ~/maintenance.txt;  then  
echo 'station1 is undergoing maintenance'
else
echo 'station1 is unexpectedly DOWN!'  
exit 1
fi

身体质量指数 (BMI
[root@centos8 ~]#cat if_bmi.sh
#!/bin/bash
read -p "请输入身高(m为单位): " HIGH
if [[ ! "$HIGH" =~ [3].?[0-9]{,2}$ ]];then
echo "输入错误的身高"
exit 1
fi
read -p "请输入体重(kg为单位): " WEIGHT
if [[ ! "$WEIGHT" =~ [4]{1,3}$ ]];then echo "输入错误的体重"; exit 1; fi
BMI=echo $WEIGHT/$HIGH^2|bc
if [ $BMI  -le 18 ] ;then
echo "太瘦了,多吃点"
elif [ $BMI  -lt 24 ] ;then
echo "身材很棒!"
else
echo "太胖了,注意节食,加强运动"
fi

条件判断 case 语句
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac

case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
|:  或,如 a或b

范例
[root@centos8 scripts]#cat case_yesorno.sh

!/bin/bash

read -p "Do you agree(yes/no)? " INPUT
INPUT=echo $INPUT | tr 'A-Z' 'a-z'
case $INPUT in
y|yes)
    echo "You input is YES"
   ;;
n|no)
    echo "You input is NO"
   ;;
*)
    echo "Input fales,please input yes or no!"
esac

[root@centos8 scripts]#cat case_yesorno2.sh

!/bin/bash

read -p "Do you agree(yes/no)? " INPUT
case $INPUT in
[yY]|[Yy][Ee][Ss])
   echo "You input is YES"
  ;;
[Nn]|[Nn][Oo])
   echo "You input is NO"
  ;;
*)
   echo "Input fales,please input yes or no!"                 
              
esac

运维菜单实现版本2
[root@centos8 scripts]#cat work_menu.sh

!/bin/bash

echo -en "\E[$[RANDOM%7+31];1m"
cat <<EOF
请选择:
1)备份数据库
2)清理日志
3)软件升级
4)软件回滚
5)删库跑路
EOF
echo -en '\E[0m'
read -p  "请输入上面数字1-5: " MENU
case $MENU in
1)
  ./backup.sh
  ;;
2)
   echo "清理日志"
;;
3)
   echo "软件升级"
  ;;
4)
   echo "软件回滚"
  ;;
5)
   echo "删库跑路"
  ;;
*)
   echo "INPUT FALSE!"
esac


  1. 0-9 ↩︎

  2. 0-9 ↩︎

  3. 0-2 ↩︎

  4. 0-9 ↩︎

猜你喜欢

转载自www.cnblogs.com/zhaihongyu/p/12640439.html