Shell
为什么要学习shell编程
- Linux/Unix系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。
- 减少重复性工作,提升运维人员的工作效率。
- Shell脚本是企业中Linux自动化运维必备不可替代的工具。
学好shell编程所需Linux基础
- 熟练掌握vim。
- 对Linux系统常用命令的掌握程度就直接决定运维人员Shell脚本编程的掌握高度。
- 正则表达式及三剑客(grep、sed、awk)。
如何才能学好shell编程
- 变量基础、条件表达式、if判断、for循环、While循环、case语句、循环控制命令
- 初学者,一定要从简单做起,最小化代码学习,复杂的程序都是由许多小的功能模块组合而成的。
- 多模仿、多练习、多思考。
- 锻炼编程思维:将需求理解透彻,然后把大的需求进行分解,逐步形成小的程序或模块。
什么是shell
shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户输入一条命令,Shell就解释执行一条。这种从键盘输入命令,就可以立即得到回应的对话方式,被称之为交互的方式。
shell存在于操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户,当我们输入系统用户名和密码,登录到Linux后的所有操作都是由Shell解释并执行的。
针对命令解释器shell在操作系统中所处的位置给了基本图解。
常用操作系统的默认shell
操作系统 | 默认使用的shell |
---|---|
Linux | bash(Bourne Again shell) |
Solaris、FreeBSD | sh(Bourne shell) |
AIX | ksh(Korn Shell) |
通过以下两种方法可查看CentOS linux系统默认的shell
# 方法一
[root@localhost ~]# echo $SHELL
/bin/bash
# 方法二
[root@localhost ~]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash
shell脚本的创建与执行
[root@localhost software]# cat test.sh
#!/bin/bash
echo "This is a test!"
一个规范的shell脚本在第一行会指出由哪个程序(解释器)来执行脚本中的内容,这一行内容在Linux bash变成中一般为:
#!/bin/bash
“#!”的作用:在执行bash脚本的时候,内容会根据 #! 后的解释器来确定该用哪个程序解释这个脚本中的内容。
执行方式
[root@localhost software]# bash test.sh
This is a test!
变量
变量是暂时存储数据的空间及其引用,所存储的数据存在于内容空间中,通过正确地引用内存空间中变量的名字就可以取出变量对应的数据。
变量分为:普通变量(局部变量)、环境变量(全局变量)
普通变量
普通变量也称为局部变量,只能在创建他们的shell函数或shell脚本中使用。
# 定义变量
[root@localhost software]# dog="My name is lion"
[root@localhost software]# echo $dog
My name is lion
# 取消变量
[root@localhost software]# unset dog
[root@localhost software]# echo $dog
局部变量定义及赋值的规则:
- 变量内容有空格且希望解析内容中的变量,使用双引号
[root@localhost ~]# a="My name is $USER" [root@localhost ~]# echo $a My name is root
- 希望原样输出变量的内容时使用单引号
[root@localhost ~]# a='My name is $USER' [root@localhost ~]# echo $a My name is $USER
- 要使用反引号将赋值的命令括起来,或者用$()
[root@localhost ~]# a="today is `date`" [root@localhost ~]# echo $a today is Sat Jun 5 10:57:40 CST 2021
环境变量
环境变量也可称为全局变量,可以在创建他们的shell及其派生出来的任意子进程shell中使用,环境变量又可分为自定义环境变量和bash内置环境变量。
# bash内置环境变量
[root@localhost software]# echo $USER
root
[root@localhost software]# echo $SHELL
/bin/bash
[root@localhost software]# echo $HOME
/root
# 自定义环境变量
[root@localhost software]# export test=1
[root@localhost software]# echo $test
1
# 环境变量永久生效(优先级)
/etc/bashrc >
~/.bashrc >
~/.bash_profile >
/etc/profile
export TMOUT=30000
显示当前环境变量名称及对应值
[root@localhost ~]# env
位置特殊参数变量
位置变量 | 作用说明 |
---|---|
$0 | 获取当前执行shell脚本的文件名,如果执行脚本带路径,那么就包括脚本路径 |
$n | 获取当前执行的shell脚本的第n个参数值,n=1..9,如果n大于9,则用大括号括起来,例如${10},接的参数以空格隔开 |
$* | 获取当前shell脚本所有传参的参数 |
$# | 参数的个数 |
[root@localhost script]# cat test.sh
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
echo $*
echo $#
[root@localhost script]# bash test.sh {a..z}
test.sh
a b c d e f g h i a0 a1 a2 a3 a4 a5
a b c d e f g h i j k l m n o
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
26
# 关于$#的用法
[root@localhost script]# cat network.sh
if [ "$#" -eq 0 ]
then
echo "Usage: ${0} {start|stop|restart}"
fi
echo $1
进程特殊状态变量
进程变量 | 作用说明 |
---|---|
$? | 获取执行上一个指令的执行状态返回值,0为成功,非零为失败 |
$$ | 获取当前执行的shell脚本的进程号(PID), |
# $? 的用法
[root@localhost script]# ls
network.sh test.sh
[root@localhost script]# echo $?
0
[root@localhost script]# l
-bash: l: command not found
[root@localhost script]# echo $?
127
# $$ 的用法
[root@localhost script]# echo $$
14615
字符串处理
# 计算字符串长度
[root@localhost ~]# var1="I love you,Do you love me"
[root@localhost ~]# echo ${#var1}
25
[root@localhost ~]# expr length "$var1"
25
# 获取字符索引位置
[root@localhost ~]# var1="quickstart is a app"
[root@localhost ~]# expr index "$var1" start
6
[root@localhost ~]# expr index "$var1" uniq
1
[root@localhost ~]# var1="qkuickstart is a app"
[root@localhost ~]# expr index "$var1" cnk
2
# 获取子串长度
[root@localhost ~]# expr match "$var1" .*app
19
[root@localhost ~]# expr match "$var1" quickstart
10
# 抽取字符串中的子串 expr索引是从1开始计算, postion索引是从0开始计算
[root@localhost ~]# var1="kafka hadoop yarn mapreduce"
[root@localhost ~]# echo ${var1:10}
op yarn mapreduce
[root@localhost ~]# echo ${var1:5:10}
hadoop ya
[root@localhost ~]# echo ${var1: -5}
educe
[root@localhost ~]# echo ${var1: -5:2}
ed
[root@localhost ~]# expr substr "$var1" 5 10
a hadoop y
变量替换
[root@localhost ~]# var1="I love you,Do you love me"
[root@localhost ~]# echo $var1
I love you,Do you love me
# 从头开始匹配,最短删除
[root@localhost ~]# v1=${var1#*ov}
[root@localhost ~]# echo $v1
e you,Do you love me
# 从头开始匹配,最长删除
[root@localhost ~]# v2=${var1##*ov}
[root@localhost ~]# echo $v2
e me
# 从尾部开始删除,最短匹配
[root@localhost ~]# v3=${var1%ov*}
[root@localhost ~]# echo $v3
I love you,Do you l
# 从尾部开始删除,最长匹配
[root@localhost ~]# v4=${var1%%ov*}
[root@localhost ~]# echo $v4
I l
# 替换变量内的旧字符串为新字符串,只替换一次
[root@localhost ~]# echo $PATH
/application/mysql/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# v5=${PATH/bin/BIN}
[root@localhost ~]# echo $v5
/application/mysql/BIN:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
# 替换变量内的旧字符串为新字符串,替换全部
[root@localhost ~]# echo $PATH
/application/mysql/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# v6=${PATH//bin/BIN}
[root@localhost ~]# echo $v6
/application/mysql/BIN:/usr/local/sBIN:/usr/local/BIN:/usr/sBIN:/usr/BIN:/root/BIN
综合练习脚本
[root@localhost software]# cat example.sh
#!/bin/bash
string="Bigdata process framework is Hadoop,Hadoop is an open source project"
function print_tips
{
echo "********************************"
echo "(1)打印string长度"
echo "(2)删除字符串中所有的Hadoop"
echo "(3)替换第一个Hadoop为Mapreduce"
echo "(4)替换全部Hadoop为Mapreduce"
echo "********************************"
}
function len_of_string
{
echo "${#string}"
}
function del_hadoop
{
echo "${string//Hadoop/}"
}
function rep_hadoop_mapreduce_first
{
echo "${string/Hadoop/Mapreduce}"
}
function rep_hadoop_mapreduce_all
{
echo "${string//Hadoop/Mapreduce}"
}
while true
do
echo "[string=$string]"
echo
print_tips
read -p "Pls input your choice(1|2|3|4|q|Q):" choice
case $choice in
1)
len_of_string
;;
2)
del_hadoop
;;
3)
rep_hadoop_mapreduce_first
;;
4)
rep_hadoop_mapreduce_all
;;
q|Q)
exit
;;
*)
echo "Error,input only in (1|2|3|4|q|Q)"
esac
done
命令替换
``和$()两者是等价的
$(())主要用来进行整数运算,包括加减乘除
# 获取系统所有用户并输出
[root@localhost ~]# cat user.sh
#!/bin/bash
#
index=1
for user in `cat /etc/passwd | cut -d ":" -f 1`
do
echo "This is $index user: $user"
index=$(($index + 1))
done
# 根据系统时间计算今年或明年
[root@localhost ~]# echo "This is $(($(date +%Y) + 1)) year"
This is 2022 year
# 根据系统时间获取今年还剩多少星期,已经过了多少星期
[root@localhost ~]# echo "This year have passed $(date +%j) days"
This year have passed 135 days
[root@localhost ~]# echo "This year have passed $(($(date +%j)/7)) weeks"
This year have passed 19 weeks
[root@localhost ~]# echo "There is $((365 -$(date +%j))) days before new year"
There is 230 days before new year
[root@localhost ~]# echo "There is $(((365 -$(date +%j))/7)) weeks before new year"
There is 32 weeks before new year
# 判断nginx 进程是否存在,若不存在则自动拉起该进程
[root@localhost ~]# cat nginx.sh
#!/bin/bash
#
nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)
if [$nginx_process_num -eq 0];then
systemctl start nginx
fi
expr
[root@localhost ~]# num1=17
[root@localhost ~]# num2=5
[root@localhost ~]# num3=`expr $num1 + $num2`
[root@localhost ~]# echo $num3
22
[root@localhost ~]# expr $num1 \* $num2
85
[root@localhost ~]# num3=$(($num1*$num2))
[root@localhost ~]# echo $num3
85