Linux shell 脚本基础介绍

Shell脚本
476
0
0
2022-05-14

介绍

shell 脚本是实现 Linux 系统自动化的重要工具,提高效率,避免重复劳动,例如如下场景

1、系统安装完后的优化、IP地址设置

2、系统安装完后服务的搭建

3、系统资源、服务的监控等

学习 shell 脚本最好有以下基础

1、Linux 中常用的命令

2、常见的服务和搭建、排除、优化,nginx、nfs等等

3、vim/vi 文本编辑器,grep sed awk

内容

1、变量

2、判断语句:ifcase

3、循环语句:forwhile

4、函数

5、流程控制语句:continuebreakexit

等等

什么是 shell 脚本

最简单的 shell 脚本就是命令的堆砌
严格的 shell 脚本会包含有命令、判断语句、循环语句、流程控制语句、变量、注释信息等等。

例子

现在要编写一个脚本清除日志,日志为 /access.log

root@test:/home/test# echo 123 > /access.log

root@test:/home/test# cat /access.log

123

root@test:/home/test# vim clean_log.sh

cd /

>/access.log

echo "日志清除完成"

root@test:/home/test# sh clean_log.sh

日志清除完成

root@kunjuee:/home/test# cat /access.log

上面的脚步是不规范的

#!/bin/bash
DIR=/
ROOT_UID=0
#只有root用户才能清除日志
if ["$UID" -ne "$ROOT_UID"]
then 
  echo "只有root用户才能清除日志" 
  exit 1
fi

cd $DIR || {
  echo "切换目录失败" 
  exit 2
}
>access.log && echo "清除日志成功"

介绍

#!/bin/bash
第一行一般来说用于指定命令解释器, sh script-name
脚本执行方式:
    1. sh scripts-name 或 /bin/bash scripts-name 脚步文件可以没有可执行权限
    2. /path/scripts-name 命令全路径,或者相对路径,必须要有可执行权限
    3. source /path/scripts-name 或 ./path/scripts-name 能够让脚本中的变量与函数在脚本执行完成后依然生效。
# 查看默认的命令解释器
root@test:~$ echo $SHELL
/bin/bash

在shell脚本中只要以 # 开头,表示注释

一般来说脚本名称会以.sh结尾,但这不是必须的

shell 脚本是按行执行的,并且默认情况下可以没有缩进,但是为了代码的易读性,所以人为的添加缩进

变量

在 shell 中有三种变量:环境变量,自定义全局变量、自定义局部变量

变量名可以由字母(大小写)、数字、下划线等组成,不能以数字开头

环境变量,例如$SHELL$UID 等,一般可以在 /etc/profile 或 /etc/bashrc等文件中看到

全局变量:export 变量名=value

能够对子 shell 生效

局部变量:变量名=value

定义完后只能当前shell生效

测试

$ aaa=123
$ export bbb=456
$ echo aaa
123
$ echo bbb
456
# 查看当前shell进程号
$ echo $$
12866
# 开启一个子shell
$ bash
$ echo $$
16990
$ echo $aaa

$ echo $bbb
456
$ exit
除了上面的变量外还有一些特殊功能的变量,$0 $? $n $#

$0:脚本名称
$?:上一条命令的执行结果
$n:n就是第几个参数,脚本传参功能
$#:参数的个数

除了以上功能,还有条件测试表达式、文件测试表达式、字符串测试表达式等等,man bash 来进行查看

判断语句 if

if 语句分为单分支语句、双分支语句、多分支语句,并且 if 语句是可以互相嵌套的。
  • 单分支语句格式:
if <条件表达式>
then
  指令1...
fi
  • 双分支语句格式:
if <条件表达式>
then
  指令1...
else
  指令2...
fi
  • 多分支语句格式:
if <条件表达式>
then
  指令1...
elif <条件表达式>
then
  指令2...
elif <条件表达式>
then
  ...
else
  指令3...
fi
<条件表达式>,这里的条件表达式可以是命令,test [] [[]] (())

测试

现在编写一个脚本,判断某个服务是否运行,如果已经运行则提示服务已经运行并退出,如果没有运行则运行,如果没有安装服务,则先进行安装再运行,在安装前将yum源设置为阿里云的yum源
# grep 是聚合草足,wc -l 是统计数量
$ jps -l | grep file | wc -l
# 查看服务是否已经启动
$ systemctl is-active mysql
# 查看上一条命令是否执行成功
$ echo $?
# 
$ ss -lntup
#!/bin/bash

if[$# -eq 1]
then 
 #判断服务是否安装    
 #rmp -qa | grep $1 | wc -l
 aa=`rpm -qa $1|wc -l`if[$aa -lt 1]
 then 
  #下载阿里云镜像源
  curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
  if [ $? -eq 0]
  then 
    #安装服务
    yum install -y $1
    systemctl start $1
    systemctl enable $1
    bb=`systemctl is-active $1`if [ $bb == 'active']
    then 
      echo "${1}服务安装并启动成功"else 
      echo "${1}服务安装失败,请检查" 
    fi 
  else 
     echo "安装yum源失败,请检查网络" 
     exit 1
   fi 
 else
   cc=`systemctl is-active $1`if [ $cc == "active" ]
   then 
     echo "${1}服务已经开启"else
     systemctl start $1if [$? -eq 0 ]
     then 
       echo "${1}服务已经启动成功"else 
       echo "${1}服务启动失败,检查配置是否正常" 
     fi
     systemctl enable $1 
   fi 
 fi
else 
  echo "请输入要运行的服务,格式为:if.sh 服务名称"
fi

for 循环

for 循环与 while 循环最大的区别在于循环的次数,一般来说 for 循环用于有限次数的循环,while 循环一般来说用于守护进程。

格式

for 变量名 in 变量取值表
do
  指令
  ...
done
例子:
现在有几个 KVM 虚拟机,配置文件是以 xml 结尾的文件,文件中记录着虚拟机的各种信息。现在需要获取虚拟机的名称与磁盘的对应关系,并且以空格分隔。
# 打印 xml 的第九行,| 将前面的结果丢给后面的命令,awk进行列输出,-F 指定分隔符,
$ sed -n 9p centos7-11.xml | awk -F "[<>]" '{print $3}'
#!/bin/bash
file_name=`ls /root/centos7-*.xml`
for n in $file_name
do
  kvm_name=`sed -n 9p $n | awk -F "[<>]" '{print $3}' `
  disk_name=`sed -n 41p $n | awk -F "'" '{print $2}'`
  echo "${n}:${kvm_name} ${disk_name}"

while 循环语句

格式

while 条件表达式(true)一直执行
do
 指令
done
例子:
猜随机数,系统随机生成一个1~60之间的数字,用户来猜这个数字,对用户输入的数字进行判断,如果不等于则提示大或小,正确后提示正确,并提示尝试次数。
# 生成随机数 0~32768 之间
$ echo $RANDOM
$ expr 1 + 1
2
$ echo $?
0
$ expr aa + 1
expr:非整数参数
$ echo $?
2
#!/bin/bash

try=0
num=$((RANDOM%61))

one(){
  # read 是交互式的    
  read -p "please input a num 0 ~ 60:" a

  # 判断输入的是否为数字    
  expr $a + 1 & > /dev/nullif [ $? -ne 0 ]
  then 
    echo "请输入正确的内容"
    one
fi
}

two(){((try++))
   if [ $a -eq $num ]
   then 
     echo "猜对了,数字为:${num}.尝试次数为${try}" 
     exit 0
   elif [ $a -gt $num ]
   then 
     echo "大了,请重试"
     one
   else 
     echo "小了,请重试"
     one
 fi
}

three(){
  one
  while truedo
    two
  done
}
three