12.1.1 shell 脚本的创建和执行
编写第一个shell脚本
[root@localhost ~]# cd /usr/local/sbin/
[root@localhost sbin]# ll
total 0
[root@localhost sbin]# vim first.sh
#! /bin/bash
## This is my first shell script.
## Writen by Aming 2020.3.26.
date
echo "Hello world!"
ps:shell的脚本通常以.sh为后缀名,并不是说不加.sh的脚本就不能执行
[root@localhost sbin]# sh first.sh
Thu Mar 26 01:16:33 EDT 2020
Hello world!
[root@localhost sbin]#
执行脚本的两种方法//
[root@localhost sbin]# ./first.sh
-bash: ./first.sh: Permission denied //执行前提是脚本本身有权限,所以需要给脚本加一个x权限
[root@localhost sbin]# chmod +x first.sh
[root@localhost sbin]# ./first.sh
Thu Mar 26 01:18:26 EDT 2020
Hello world!
-
x:查看脚本的执行过程
[root@localhost sbin]# sh -x first.sh + date Thu Mar 26 02:32:50 EDT 2020 + echo 'Hello world!' Hello world! [root@localhost sbin]#
12.1.2 命令 date
- date +%Y:表示以四位数字格式打印年份
- date +%y:表示以两位数字格式打印年份
- date +%m:表示月份
- date +%d:表示日期
- date +%H:表示小时
- date +%M:表示分钟
- date +%S:表示秒
- date +%w:表示星期,结果显示0则表示周日
举例如下:
[root@localhost ~]# date +"%Y-%m-%d %H:%M:%S"
2020-03-26 03:13:02
[root@localhost ~]# date -d "-1 day" +%d //前一天的日期
25
[root@localhost ~]# date -d "-1 hour" +%H //前一小时
02
[root@localhost ~]# date -d "-1 min" +%M //前一分钟
14
[root@localhost ~]#
12.2 shell 脚本中的变量
定义变量的格式为:“变量名=变量的值”,在脚本中引用变量时需要加上符号$
[root@localhost sbin]# cat variable.sh
#! /bin/bash
## In this script we will use variables.
##Writen by Aming 2020.3.26.
d=`date +%H:%M:%S`
echo "The script begin at $d."
echo "Now we'll sleep 2 seconds."
sleep2
d1=`date +%H:%M:%S`
echo "The script end at $d1."
[root@localhost sbin]#
ps:反引号的作用是将引号中的字符串当成shell命令执行,返回命令的执行结果。d和d1在脚本中作为变量出现
[root@localhost sbin]# sh variable.sh //执行结果
The script begin at 03:40:04.
Now we'll sleep 2 seconds.
The script end at 03:40:06.
12.2.1 数学运算
示例如下:
[root@localhost sbin]# cat sum.sh
#! /bin/bash
## For get the sum of two numbers.
## Aming 2020-03-26
a=1
b=2
sum=$[$a+$b]
echo "$a+$b=$sum"
[root@localhost sbin]#
ps:数学计算要用[ ]括起来,并且前面要加符号。
[root@localhost sbin]# sh sum.sh
1+2=3
[root@localhost sbin]#
12.2.2 和用户交互
示例如下:
[root@localhost sbin]# cat read.sh
#! /bin/bash
## Using 'read' in shell script
## Aming 2020-3-26
read -p "Please input a number:"x
read -p "Please input another number:"y
sum=$[$x+$y]
echo "The sum of the two numbers is: $sum"
ps:read命令用于和用户交互,它把用户输入的字符串作为变量值。
[root@localhost sbin]# sh read.sh
Please input a number:2 //输入值
Please input another number:10 //输入值
The sum of the two numbers is: 12 //计算
ps:加上-x选项:
[root@localhost sbin]# sh -x read.sh
+ read -p 'Please input a number:' x
Please input a number:22
+ read -p 'Please input another number:' y
Please input another number:15
+ sum=37
+ echo 'The sum of the two numbers is: 37'
The sum of the two numbers is: 37
12.2.3 shell 脚本预设变量
有时会用到/etc/init.d/iptables restart的命令,前面的/etc/init.d/iptables文件其实就是一个shell脚本。实际上,shell脚本在执行时,后面可以跟一个或者多个参数:
[root@localhost sbin]# cat option.sh
#! /bin/bash
sum=$[$1+$2]
echo "sum=$sum"
[root@localhost sbin]#sh -x option.sh 1 2
+ sum=3
+ echo sum=3
sum=3
ps:脚本中的$1和$2其实就是shell脚本的预设变量。$1和$2的值就是在执行时分别输入的1和2,$1就是脚本的第一个参数,$2是脚本的第二个参数,以此类推,当然一个shell脚本的预设变量是没有限制的
另外还有一个$0,它代表脚本本身的名字。
[root@localhost sbin]# cat option.sh
#! /bin/bash
echo "$1 $2 $0"
[root@localhost sbin]# sh option.sh 1 2
1 2 option.sh
[root@localhost sbin]#
12.3 shell脚本中的逻辑判断
12.3.1 不带 else
格式:
if 判断语句;then
command
fi
示例:
[root@localhost sbin]# cat if1.sh
#! /bin/bash
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
fi
if1.sh中出现了((a<60))这样的形式,这是shell脚本特有的格式
只用一个小括号或者不用都会报错。
[root@localhost sbin]# sh if1.sh
Please input your score: 95
[root@localhost sbin]# sh if1.sh
Please input your score: 45
You didn't pass the exam.
[root@localhost sbin]#
12.3.2 带有 else
格式:
if 判断语句;then
command
else
command
fi
示例:
[root@localhost sbin]# cat if2.sh
#! /bin/bash
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
else
echo "Good! You passed the exam."
fi
[root@localhost sbin]# sh if2.sh
Please input your score: 150
Good! You passed the exam.
[root@localhost sbin]# sh if2.sh
Please input your score: 25
You didn't pass the exam.
ps:脚本if2.sh和脚本f1.sh唯一的区别是:如果输入大于或等于60的数字会有提示
12.3.3 带有 elif
格式:
if 判断语句1; then
command
elif 判断语句2; then
command
else
command
fi
示例:
[root@localhost sbin]# cat if3.sh
#! /bin/bash
read -p "Please input your score: " a
if ((a<60)); then
echo "You didn't pass the exam."
elif ((a>=60)) && ((a<85)); then
echo "Good! You pass the exam."
else
echo "Very good! Your score is very high!"
fi
ps:这里的&&表示“并且”的意思,当然也可以使用||表示“或者”
[root@localhost sbin]# sh if3.sh
Please input your score: 90
Very good! Your score is very high!
[root@localhost sbin]# sh if3.sh
Please input your score: 60
Good! You pass the exam.
[root@localhost sbin]#
判断数值大小除了可以用(())的形式外,还可以使用[]。但是不能使用>、<、=这样的符号了,要使用-lt(小于)、gt(大于)、le(小于或等于)、-ge(大于或等于)、-eq(等于)、-ne(不等于)。
用命令行的形式简单比较一下:
[root@localhost sbin]# a=10; if [ $a -lt 5 ]; then echo ok; fi
[root@localhost sbin]# a=10; if [ $a -gt 5 ]; then echo ok; fi
ok
[root@localhost sbin]# a=10; if [ $a -ge 10 ]; then echo ok; fi
ok
[root@localhost sbin]# a=10; if [ $a -eq 10 ]; then echo ok; fi
ok
[root@localhost sbin]# a=10; if [ $a -ne 10 ]; then echo ok; fi
[root@localhost sbin]#
下面是在if语句中使用&&和||的情况,示例代码如下:
[root@localhost sbin]# a=10; if [ $a -lt 1 ] || [ $a -gt 5 ]; then echo ok; fi
ok
[root@localhost sbin]# a=10; if [ $a -gt 1 ] || [ $a -lt 10 ]; then echo ok; fi
ok
12.3.4 和文档相关的判断
shell脚本中if还经常用于判断文档的属性,比如判断是普通文件还是目录,判断文件是否有读、写、执行权限等。
-
-e:判断文件或目录是否存在
-
-d:判断是不是目录以及是否存在
-
-f:判断是不是普通文件以及是否存在
-
-r:判断时候有读权限
-
-w:判断是否有写权限
-
-x:判断是否可执行
使用if判断时的格式: if [ -e filename ] ; then command fi
示例:
[root@localhost sbin]# if [ -d /home/ ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -f /home/ ]; then echo ok; fi
ps:因为/home/是目录而非文件,所以并不会显示ok
[root@localhost sbin]# if [ -f /root/1.txt ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -r /root/1.txt ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -w /root/1.txt ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -x /root/1.txt ]; then echo ok; fi
[root@localhost sbin]# if [ -e /root/1.txt ]; then echo ok; fi
ok
[root@localhost sbin]#
12.3.5 case逻辑判断
在shell脚本中,除了用if来判断逻辑外,还有一种常用的方式——case
格式为:
case 变量 in
value1)
command
;;
value2)
command
;;
value3)
command
;;
*)
command
;;
esac
上面的结构中,不限制value的个数,*代表其他值
判断输入数值是奇数还是偶数:
[root@localhost sbin]# cat case.sh
#! /bin/bash
read -p "Input a number: " n
a=$[$n%2]
case $a in
1)
echo "The number is odd."
;;
0)
echo "The number is even."
;;
*)
echo "It's not a number!"
;;
esac
脚本中$a的值为1或0,执行结果如下:
[root@localhost sbin]# sh case.sh
Input a number: 100
The number is even.
[root@localhost sbin]# sh case.sh
Input a number: 101
The number is odd.
[root@localhost sbin]#
ps:case脚本常用于编写系统服务的启动脚本。例如/etc/init.d/network中就用到了。
12.4 shell脚本中的循环
常用到的循环有for循环和while循环
12.4.1 for 循环
[root@localhost sbin]# cat for.sh
#! /bin/bash
for i in `seq 1 5`; do
echo $i
done
脚本中的seq 1 5表示从1到5的一个序列:
[root@localhost sbin]# sh for.sh
1
2
3
4
5
[root@localhost sbin]#
for循环的基本结构,具体格式:
for 变量名 in 循环的条件; do
command
done
这里“循环的条件”可以是一组字符串或者数字(用一个或者多个空格隔开),也可以是一条命令的执行结果:
[root@localhost sbin]# for i in 1 2 3 a b; do echo $i; done
1
2
3
a
b
“循环的条件”还可以引用系统命令的执行结果(seq 1 5),
但必须用反引号括起来:
[root@localhost sbin]# for file in `ls`; do echo $file; done
case.sh
first.sh
for.sh
if1.sh
if2.sh
if3.sh
option.sh
read.sh
sum.sh
variable.sh
12.4.2 while 循环
格式为:
while 条件; do
command
done
示例:
[root@localhost sbin]# cat while.sh
#! /bin/bash
a=5
while [ $a -ge 1 ]; do
echo $a
a=$[$a-1]
done
[root@localhost sbin]# sh while.sh
5
4
3
2
1
另外可以用一个冒号来代替循环条件,这样可以做到死循环
[root@localhost sbin]# cat while.sh
#! /bin/bash
while :; do
command
sleep 3
done
12.5 shell脚本中的函数
shell脚本中的函数就是先把一段代码整理到一个小单元中,并给这个小单元命名,当用到这段代码时直接调用这个小单元的名字即可。有时候脚本中的某段代码总是重复使用,如果写成函数,每次用到时直接用函数名代替即可,不仅节省时间还节省空间。
[root@localhost sbin]# cat func.sh
#! /bin/bash
function sum()
{
sum=$[$1+$2]
echo $sum
}
sum $1 $2
[root@localhost sbin]# sh func.sh 1 2
3
func.sh中的summ()为自定义的函数。
格式为:
function 函数名()
{
command1
command2
}
ps:值得注意的是,在shell脚本中,函数一定要写在最前面,不能出现在中间或者最后。因为函数是要被调用的,如果还没有出现就被调用,肯定会出错。
12.6 shell脚本中的中断和继续
12.6.1 break
break用在循环中,不管是for或者while都可以。在脚本中使用它,表示退出该层循环。之所以说层,是因为有时我们会用到嵌套循环,大循环里面还有小循环,而break仅仅是退出那一层循环,它的上层循环不受影响。
[root@localhost sbin]# cat break.sh
#! /bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
break
fi
echo $i
done
echo aaaaaa
脚本中,要把1~5数值赋予i,当i等于3时,会跳出循环,
后面的4和5都不会再执行了
[root@localhost sbin]# sh break.sh
1
1
2
2
3
aaaaaa
[root@localhost sbin]#
12.6.2 continue
continue也是使用在循环中的,但和break不同的是,当在shell脚本中遇到contiune时,结束的不是整个循环,而是本次循环。
[root@localhost sbin]# cat continue.sh
#! /bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
continue
fi
echo $i
done
echo $1
脚本执行:
[root@localhost sbin]# sh continue.sh
1
1
2
2
3
4
4
5
5
ps:当i=3时,出现了continue,所以结束本次循环,continue后面的语句不再执行,继续下一次循环
12.6.3 exit
exit的作用范围更大,直接退出整个shell脚本
[root@localhost sbin]# cat exit.sh
#! /bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
exit
fi
echo $i
done
echo aaaaaa
[root@localhost sbin]# sh exit.sh
1
1
2
2
3