shanjayp
shanjayp
Published on 2025-02-11 / 2 Visits
0
0

1. Shell脚本编程

Shell概述

  • Shell是一门编程语言,如:C C++ java php Python Go等类似

  • 语言分类:

    编译型语言:C C++ Go等为编译型语言,程序运行需要提前编译,编译语言都有编译器

    解释型语言:Shell Python php等为解释型语言,程序运行不需要提前编译,一边执行,一边解释,每种解释型语言都有解释器

  • Shell语言支持大部分编程语言都具备的功能:if判断,for循环,变量,数组,函数,加减乘除,逻辑运算

规范Shell脚本组成

[root@test ~]# vim user.sh
#!/bin/bash(环境声明)
#注释信息
命令...

如何写好一个Shell脚本

  • 明确任务需求

  • 按需求整理好每一个步骤,先做什么,后做什么

  • 运行脚本,并根据运行结果排除错误

  • 优化脚本并达到最终效果

编写脚本

  • 编写第一个脚本

[root@localhost ~]# vim hello.sh
#!/bin/bash
#hello word
echo hello word
​
#赋予执行权限
[root@localhost ~]# chmod u+x hello.sh
​
#执行脚本
[root@localhost ~]# /root/hello.sh 
hello word

  • 编写创建用户脚本

[root@localhost ~]# vim user.sh
#!/bin/bash
useradd abc  
passwd abc
​
[root@localhost ~]# chmod u+x user.sh 
​
#非交互
[root@localhost ~]# vim user.sh
#!/bin/bash
useradd yyyy
echo 1 | passwd --stdin yyyy
​
[root@localhost ~]# ./user.sh 
更改用户 yyyy 的密码 。
passwd:所有的身份验证令牌已经成功更新。

  • 编写批量查看系统信息脚本

#查看系统版本信息,查看系统内核信息,查看系统内存信息,查看系统网卡信息,查看当前主机名
[root@localhost ~]# vim info.sh
cat /etc/redhat-release
uname -r
free -h
ifconfig ens32
hostname
​
#赋予执行权限
[root@localhost ~]# chmod u+x info.sh 
​
#执行脚本
[root@localhost ~]# ./info.sh 
CentOS Linux release 7.6.1810 (Core) 
3.10.0-957.el7.x86_64
              total        used        free      shared  buff/cache   available
Mem:           972M        480M        147M         16M        344M        260M
Swap:          2.0G        239M        1.8G
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.100  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::8903:cb8:127b:dbc8  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a0:e8:12  txqueuelen 1000  (Ethernet)
        RX packets 230110  bytes 325471733 (310.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20635  bytes 1385581 (1.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
​
localhost.localdomain
​

  • 编写搭建本地软件仓库的脚本

#编写搭建本地yum仓库脚本【版1,丢人版】
[root@localhost ~]# vim yum.sh 
#!/bin/bash
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
rm -rf /etc/yum.repos.d/*
touch  /etc/yum.repos.d/local.repo
echo "[local]" > /etc/yum.repos.d/local.repo
echo "name=local_centos" >> /etc/yum.repos.d/local.repo
echo "baseurl=file:///mnt/centos" >> /etc/yum.repos.d/local.repo
echo "enabled=1" >> /etc/yum.repos.d/local.repo
echo "gpgcheck=0" >> /etc/yum.repos.d/local.repo
​
#编写搭建本地yum仓库脚本【版2,标准版】
[root@localhost ~]# vim yum.sh 
#!/bin/bash
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
mount -a
rm -rf /etc/yum.repos.d/*
echo "[local] 
name=local_centos 
baseurl=file:///mnt/centos 
enabled=1 
gpgcheck=0" > /etc/yum.repos.d/local.repo
​
#编写搭建本地yum仓库脚本【升级版】
[root@localhost ~]# vim yum.sh 
#!/bin/bash
echo "正在配置本地yum仓库..."
mkdir /mnt/centos
mount /dev/cdrom /mnt/centos &> /dev/null
echo '/dev/cdrom /mnt/centos iso9660 defaults 0 0' >> /etc/fstab
mount -a
rm -rf /etc/yum.repos.d/*
echo "[local] 
name=local_centos 
baseurl=file:///mnt/centos 
enabled=1 
gpgcheck=0" > /etc/yum.repos.d/local.repo
echo "本地yum仓库配置以完成..."
yum clean all &> /dev/null
yum repolist | tail -1
​
​
#执行脚本
[root@localhost ~]# ./yum.sh
正在配置本地yum仓库...
本地yum仓库配置以完成...
repolist: 4,021
​
​
#带进度条版本
#!/bin/bash
echo "====正在搭建本地软件仓库===="
b=''
for ((i=0;$i<=20;i++))
do
let jinshu=$i*5
printf "[%-20s]%d%%\r" $b $jinshu
sleep 0.1
b=#$b
done
echo
​
rm -rf /etc/yum.repos.d/*
echo "[local]
name=local-centos-7.6
baseurl=file:///mnt/centos
enabled=1
gpgcheck=0" > /etc/yum.repos.d/centos.repo
x=`yum repolist | tail -1 | awk '{print $2}'`
echo "软件包数量为:$x"

脚本的执行方式

  • 执行一个脚本的方法有很多种

  • 方法一:赋予脚本执行权限后,可用绝对路径或者当前路径执行

  • 方法二:调用解释器执行脚本文件

#绝对路径执行脚本
[root@localhost ~]# /root/hello.sh 
​
#相对路径执行脚本
[root@localhost ~]# ./hello.sh 
​
#去除执行权限
[root@localhost ~]# chmod u-x hello.sh 
​
#执行脚本
[root@localhost ~]# /root/hello.sh
-bash: /root/hello.sh: 权限不够
​
[root@localhost ~]# ./hello.sh
-bash: ./hello.sh: 权限不够
​
#调用解释器执行脚本
[root@localhost ~]# bash hello.sh
hello word
​
[root@localhost ~]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
[root@localhost ~]# sh hello.sh
hello word
[root@localhost ~]# tcsh hello.sh
hello word
[root@localhost ~]# csh hello.sh
hello word

常用特殊符号补充

  • " " #双引号,引用整体

  • ' ' #单引号,引用整体并取消所有特殊字符含义

  • $[] #四则运算(+ - * / % 取余数)

  • $() #将命令的输出结果作为参数

  • `` #将命令的输出结果作为参数

#引用整体,不屏蔽特殊符号的功能
[root@localhost ~]# echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
​
#引用整体,屏蔽特殊符号的功能
[root@localhost ~]# echo '$PATH'
$PATH
​
#没有特殊符号单引双引都可以
[root@localhost ~]# echo "xxoo"
xxoo
[root@localhost ~]# echo 'xxoo'
xxoo
​
#四则运算
[root@localhost ~]# echo $[1+1]
2
[root@localhost ~]# echo $[1+5]
6
[root@localhost ~]# echo $[10-5]
5
[root@localhost ~]# echo $[10*5]
50
[root@localhost ~]# echo $[10/5]
2
[root@localhost ~]# echo $[1+3+4+5+7]
20
[root@localhost ~]# echo $[10/3]
3
[root@localhost ~]# echo $[10%3]
1
​
#$()取命令结果作为参数
root@localhost ~]# touch $(date +%F)-abc.txt
2021-05-09-abc.txt 
​
#``取命令结果作为参数
[root@localhost ~]# tar -czf "`date "+%F %X"`_log.tar.gz" /var/log/*.log
​

变量

  • 以固定的名称存放可能变化的值,提高脚本的灵活度来适应多变的环境

  • 定义变量:变量名=变量值,如:date=$(date +%F)(等号两边不要有空格)

  • 定义变量注意事项:

    • 变量名由字母/数字/下划线组成,区分大小写,不能以数字开头,不要使用命令和特殊符号

  • 若指定的变量名已经存在,相当于为此变量重新赋值

  • 取消变量:unset 变量名

num=5
echo $num
5
​
echo $[num+5]
10
​
#通过变量定义用户名
[root@localhost ~]# vim user.sh 
#!/bin/bash
user=wangxin
useradd $user   
echo 1 | passwd --stdin $user
​
[root@localhost ~]# ./user.sh 
更改用户 wangxin 的密码 。
passwd:所有的身份验证令牌已经成功更新。
​
[root@localhost ~]# vim user.sh 
#!/bin/bash
user=jiumei
useradd $user
echo 1 | passwd --stdin $user
​
[root@localhost ~]# ./user.sh 
更改用户 jiumei 的密码 。
passwd:所有的身份验证令牌已经成功更新。
​
[root@localhost ~]# vim user.sh 
#!/bin/bash
user=panghu
useradd $user
echo "用户$user创建成功"
echo 1 | passwd --stdin $user &> /dev/null
echo "用户$user密码设置成功"
​
[root@localhost ~]# ./user.sh 
用户panghu创建成功
用户panghu密码设置成功
​

read标准输入取值

  • read 读取用户在键盘上输入的内容,并把内容存放在变量里,可以降低脚本的使用难度

  • 命令格式:read -p “提示信息” 变量名

通过read创建用户
#!/bin/bash
read -p '请输入用户名:' user
useradd $user 
echo "用户$user创建成功"
read -p '请设置用户密码:' pass
echo $pass | passwd --stdin $user &> /dev/null
echo "用户$user密码设置成功"
​
​
​
​
通过read安装软件包
#!/bin/bash
#通过read标准输入取值,安装软件包
​
read -p 请输入你要安装的软件包名称: package
​
yum -y install $package  &> /dev/null
​
echo 正在安装软件包,请耐心等待...
b=''
for ((i=0;$i<=20;i++))
do
let jinshu=$i*5
printf "[%-20s]%d%%\r" $b $jinshu
sleep 0.1
b=#$b
done
echo
​
echo 软件包$package已经成功安装

变量种类

  • 环境变量:变量名一般都大写,用来设置用户/系统环境

  • 位置变量:bash内置,存储执行脚本时提供的命令参数

  • 预定义变量:bash内置,可直接调用的特殊值,不能直接修改

  • 自定义变量:用户自定义

  • env 命令查看系统所有环境变量

  • set 命令查看系统所有变量,包括用户自定义变量

  • 环境变量

[root@localhost etc]# env
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
SSH_CONNECTION=192.168.0.1 51791 192.168.0.100 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
DISPLAY=localhost:10.0
_=/usr/bin/env
OLDPWD=/root
​
#获取变量值
[root@localhost etc]# echo $SHELL
/bin/bash
​
[root@localhost ~]# echo $PWD
/root
​
#查看系统所有变量
[root@localhost ~]# set
[root@localhost ~]# set | grep $a

  • 位置变量

    $0 #脚本名称

    $1 #第一个参数

    $2 #第二个参数

    $3 #第三个参数

    $4 #第四个参数

    $n… #第n个参数

  • 预定义变量

    $0 #代表脚本本身

    $* #显示所有参数内容

    $# #显示有多少个参数

    $? #显示上一条命令的执行结果(0代表正确,非0代表错误)

    $$ #显示脚本进程号(PID)

[root@localhost ~]# vim test.sh 
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
echo $*
echo $#
echo $$
echo $?
​
#赋予执行权限,执行脚本
[root@localhost ~]# ./test.sh xx oo dd
./test.sh  $0
xx         $1
oo         $2
dd         $3
xx oo dd   $*
3          $#
15594      $$
0          $?
​
#通过位置变量创建用户并设置密码
#!/bin/bash
useradd $1 &> /dev/null
echo "用户$1创建成功"
echo  $2 | passwd --stdin $1 &> /dev/null
echo "用户$1的密码设置成功,密码为$2"

判断文件状态

  • -e #判断文档(文件/目录)是否存在,存在为真

  • -d #判断目录是否存在,存在为真

  • -f #判断文件是否存在,存在为真

  • -r #可读为真

  • -w #可写为真

  • -x #可执行为真

#判断文档是否存在
[root@localhost ~]# [ -e /etc/ ]
[root@localhost ~]# echo $?
0 #为真
​
#判断目录是否存在
[root@localhost ~]# [ -d /opt ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ -d /etc/passwd ]
[root@localhost ~]# echo $?
1
​
[root@localhost ~]# [ -f /etc/passwd ]
[root@localhost ~]# echo $?
0
​
#判断是否可读(以当前用户身份判断)
[root@localhost ~]# [ -r /etc/passwd ]
[root@localhost ~]# echo $?
0
​
#判断是否可写
[root@localhost ~]# [ -w /etc/passwd ]
[root@localhost ~]# echo $?
0
​
#判断是否可执行
[root@localhost ~]# [ -x /etc/passwd ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# ll /etc/passwd
-rw-r--r--. 1 root root 3294 5月   9 16:43 /etc/passwd

整数比较

  • -gt #大于

  • -ge #大于等于

  • -eq #等于

  • -lt #小于

  • -le #小于等于

  • -ne #不等于

[root@localhost ~]# [ 1 -gt 1 ]
[root@localhost ~]# echo $?
1
​
[root@localhost ~]# [ 1 -eq 1 ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ 1 -ge 1 ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ 1 -ge 2 ]
[root@localhost ~]# echo $?
1
​
[root@localhost ~]# [ 1 -lt 2 ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ 1 -le 2 ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ 1 -le 10 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ 10 -le 10 ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ 1 -ne 2 ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ 2 -ne 2 ]
[root@localhost ~]# echo $?
1

字符串对比

  • == #相等

  • != #不相等

[root@localhost ~]# [ root == xxoo ]
[root@localhost ~]# echo $?
1
​
[root@localhost ~]# [ root == $USER ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ $USER == root ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ abc == bcd ]
[root@localhost ~]# echo $?
1
​
[root@localhost ~]# [ abc != bcd ]
[root@localhost ~]# echo $?
0
​
[root@localhost ~]# [ $USER != root ]
[root@localhost ~]# echo $?
1

常用数值运算方式

  • $[] #四则运算(+ - * / % 取余数)

  • $(()) #数值运算工具

  • expr #数值运算工具

  • let #数值运算工具

[root@localhost ~]# echo $[10+5]
15
[root@localhost ~]# echo $[10-5]
5
[root@localhost ~]# echo $[10*5]
50
[root@localhost ~]# echo $[10/5]
2
[root@localhost ~]# echo $[10%3]
1
​
#$(())做数值运算
[root@localhost ~]# echo $((10+5))
15
[root@localhost ~]# echo $((10-5))
5
[root@localhost ~]# echo $((10*5))
50
[root@localhost ~]# echo $((10/5))
2
[root@localhost ~]# echo $((10%3))
1
​
#expr做数值运算
[root@localhost ~]# echo expr 2+3
expr 2+3
[root@localhost ~]# echo `expr 2+3`
2+3
​
#要求每一部分都要有空格
[root@localhost ~]# echo `expr 2 + 3`
5
[root@localhost ~]# echo `expr 10 - 3`
7
​
#当进行乘法运算时,需要实用“\”转义掉*的特殊功能
[root@localhost ~]# echo `expr 10 * 3`
expr: 语法错误
​
[root@localhost ~]# echo `expr 10 \* 3`
30
[root@localhost ~]# echo `expr 10 / 3`
3
​
#let做数值运算
# let unm=1+1
echo $num
​
#let简写表达式        #let完整表达式
let num++           let num=num+1
​
let num--           let num=num-1
​
let num+=5          let num=num+5
​
let num-=5          let num=num-5
​
let num*=2          let num=num*2
​
let num/=3          let num=num/3
​
let num%=3          let num=num%3

字符串判断

  • -z #字符串的值为空为真

  • -n #字符串的值非空为真(相当于 ! -z)

[ -z $num ]
echo $?
​
​
[ ! -z $num ]
echo $?



Comment