Linux下的shell脚本

shell脚本的基本结构:

shell脚本示例:

1
2
3
4
5
6
7
8
9
[root@localhost ~]# cd /usr/local/sbin/
[root@localhost sbin]# vim first.sh
#! /bin/bash

## This is my first shell script.
## Writen by Cao 2018-7-2.

date
echo "Hello world!"

shell脚本用注意事项:

Shell脚本通常都是以.sh 为后缀名的**,这个并不是说不带.sh这个脚本就不能执行,只是大家的一个习惯而已。所以,遇见.sh结尾的文件通常都是脚本。

shell脚本中第一行要以 “#! /bin/bash” 开头,它代表的意思是,该文件使用的是bash语法。如果不设置该行,虽然shell脚本也可以执行,但是这不符合规范。

# 表示注释。后面跟一些该脚本的相关注释内容以及作者和创建日期或者版本等等。为了方便管理,写注释是非常必要的。

shell脚本执行方法:

  1. sh shell.sh

    另外使用sh命令去执行一个shell脚本的时候是可以加-x选项来查看这个脚本执行过程的,这样有利于我们调试这个脚本哪里出了问题:

  2. ./first.sh 该方法通常需要更改文件权限。chomod +x shell.sh

1
2
3
4
5
[root@localhost sbin]# sh -x first.sh 
+ date
2018年 07月 02日 星期一 15:05:17 CST
+ echo 'Hello word!'
Hello word!

命令date:

1
2
3
4
[root@localhost sbin]# date +"%Y-%m-%d %H:%M:%S"
2018-07-02 15:08:01
[root@localhost sbin]# date
2018年 07月 02日 星期一 15:08:04 CST

date在脚本中最常用的几个用法:

data +%Y 以四位数字格式打印年份

date +%y 以两位数字格式打印年份

date +%m 月份

date +%d 日期

date +%H 小时

date +%M 分钟

date +%S

date +%w 星期,如果结果显示0 则表示周日

有时在脚本中会用到一天前的日期:

1
2
[root@localhost sbin]# date -d "-1 day" +%d
23

或者一小时前:

1
2
[root@localhost sbin]# date -d "-1 hour" +%H
18

甚至1分钟前:

1
2
[root@localhost sbin]# date -d "-1 min" +%M
50

shell脚本中的变量:

变量就是和其他编程语言中的变量一样,为了简化和使代码更容易维护。

使用变量的脚本示例:

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost sbin]# cat variable.sh 
#! /bin/bash

## In this script we will use variables.
## Writen by Cao 2018-7-2.

d=`date +%H:%M:%S`
echo "The script begin at $d"
echo "Now we'll sleep 2 seconds."
sleep 2
d1=`date +%H:%M:%S`
echo "The script end at $d1."
1
2
3
4
[root@localhost sbin]# ./variable.sh 
The script begin at 15:21:23
Now we'll sleep 2 seconds.
The script end at 15:21:25.

脚本中使用了反引号 “ ` “ , 反引号的作用:在Linux中起着命令替换的作用。命令替换是指shell能够将一个命令的标准输出插在一个命令行中任何位置。

d’ 和 ‘d1’ 在脚本中作为变量出现,定义变量的格式为 变量名=变量的值
当在脚本中引用变量时需要加上 ‘$’ 符号,引用变量的符号。

使用shell计算两个数的和:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost sbin]# cat sum.sh 
#! /bin/bash

## For get the sum fo tow numbers.
## Cao 2018-7-2.

a=1
b=2
sum=$[$a+$b]
#数学计算要用[ ]括起来并且外头要带一个 ‘$’

echo "$a+$b=$sum"
[root@localhost sbin]# ./sum.sh
1+2=3

Shell脚本还可以和用户交互:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@localhost sbin]# cat read.sh 
#! /bin/bash

## Using 'read' in shell script.
## Writen by Cao 2018-7-2.

read -p "Please input a number:" x
read -p "please input another number:" y
sum=$[$x+$y]
echo "The sum of the tow number is:$sum"

[root@localhost sbin]# sh read.sh
Please input a number:20
please input another number:30
The sum of the tow number is:50

shell的预设变量:

shell中的预设变量$0,代表脚本本身的名字。

shell脚本的逻辑判断:

在shell中的判断的基本语法为:

1
2
3
4
5
6
7
if  判断语句一  ; then
command
elif 判断语句二; then
command
else
command
fi

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@localhost sbin]# cat if.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 socre is very high!"
fi
[root@localhost sbin]# sh if.sh
Please input your score:90
very good! Your socre is very high!
[root@localhost sbin]# sh if.sh
Please input your score:78
Good! You pass the exam.
[root@localhost sbin]# sh if.sh
Please input your score:49
You didn't pass the exam

在判断数值大小除了可以用 (( )) 的形式外,还可以使用 [ ] 但是就不能使用>, < , = 这样的符号了,要使用 -lt (小于),-gt (大于),-le (小于等于),-ge (大于等于),-eq (等于),-ne (不等于)。

1
2
3
4
5
6
7
8
[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

shell 脚本中if还经常判断关于档案属性,比如判断是普通文件还是目录,判断文件是否有读写执行权限等。常用的也就几个选项:

-e :判断文件或目录是否存在

-d :判断是不是目录,并是否存在

-f :判断是否是普通文件,并存在

-r :判断文档是否有读权限

-w :判断是否有写权限

-x :判断是否可执行

使用if判断时,具体格式为:

if [ -e filename ] ; then

1
2
3
4
5
6
7
8
root@localhost sbin]# if [ -f /root/test.txt ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -r /root/test.txt ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -w /root/test.txt ]; then echo ok; fi
ok
[root@localhost sbin]# if [ -x /root/test.txt ]; then echo ok; fi
[root@localhost sbin]# if [ -e /root/test1.txt ]; then echo ok; fi

case的使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case  变量  in
value1)
command
;;
value2)
command
;;
value3)
command
;;
*)
command
;;
esac

面的结构中,不限制value的个数, * 则代表除了上面的value外的其他值。

判断输入数值是奇数或者偶数的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[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
[root@localhost sbin]# sh case.sh
Input a number:79
The number is odd.
[root@localhost sbin]# sh case.sh
Input a number:90
The number is even.
[root@localhost sbin]# sh case.sh
Input a number:sd
The number is even.

case脚本常用于编写系统服务的启动脚本,例如/etc/init.d/iptables中就用到了。

shell脚本中的循环:

for循环的基本结构:

1
2
3
for 变量名 in 循环的条件; do
command
done

for循环示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost sbin]# cat for.sh 
#! /bin/bash

#脚本中的 seq 1 5 表示从1到5的一个序列。
for i in `seq 1 5`; do
echo $i
done
[root@localhost sbin]# sh for.sh
1
2
3
4
5
[root@localhost sbin]# for i in 1 2 3 a b; do echo $i; done
1
2
3
a
b

while循环:

1
2
3
4
while  条件; do

command
done

while使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[hadoop@localhost ~]$ cat while.sh 
#! /bin/bash

a=5
while [ $a -ge 1 ]; do
echo $a
a=$[$a-1]
done
[hadoop@localhost ~]$ sh while.sh
5
4
3
2
1
[hadoop@localhost ~]$

另外可以把循环条件拿一个冒号替代,这样可以做到死循环。

shell脚本中的函数:

在shell脚本函数的格式为:

1
2
3
4
5
function 函数名() {

command

}

在shell脚本中,函数一定要写在最前面,不能出现在中间或者最后,因为函数是要被调用的,如果还没有出现就被调用,肯定是会出错的。

函数使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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
[root@localhost sbin]# sh func.sh 4 5
9

shell脚本实例:

(1)计算1-100的和:

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost sbin]# cat sum1-100.sh 
#! /bin/bash

## Sum(1-100)
sum=0
for i in `seq 1 100`; do
sum=$[$i+$sum]
done

echo $sum
[root@localhost sbin]# sh sum1-100.sh
5050

(2)要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost sbin]# cat sum.sh 
#! /bin/bash

n=0
while [ $n -lt "1" ]; do
read -p "Please input a number, it must greater than "1":" n
done

sum=0

for i in `seq 1 $n`; do
sum=$[$i+$sum]
done

echo $sum
[root@localhost sbin]# sh sum.sh
Please input a number, it must greater than 1:50
1275
[root@localhost sbin]#

(3)把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@localhost sbin]# cat copydir.sh 
#!/bin/bash

cd /root
for f in `ls`; do
if [ -d $f ] ; then
cp -r $f /tmp
fi
done
[root@localhost sbin]# sh copydir.sh
[root@localhost sbin]# ls /tmp
Desktop
Documents
Downloads
Music
Pictures
Public

(4)批量建立用户user_00, user_01, … user_100并且所有用户同属于users组;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost sbin]# cat useradd.sh 
#! /bin/bash

groupadd users

for i in `seq 0 9`; do
useradd -g users user_0$i
done

for j in `seq 10 100`; do
useradd -g users user_$j
done
[root@localhost sbin]# sh useradd.sh
[root@localhost sbin]# cat /etc/passwd | grep user
user_00:x:1005:100::/home/user_00:/bin/bash
user_01:x:1006:100::/home/user_01:/bin/bash
user_02:x:1007:100::/home/user_02:/bin/bash
user_03:x:1008:100::/home/user_03:/bin/bash
user_04:x:1009:100::/home/user_04:/bin/bash
user_05:x:1010:100::/home/user_05:/bin/bash
user_06:x:1011:100::/home/user_06:/bin/bash

(5)截取文件test.log中包含关键词 ‘abc’ 的行中的第一列(假设分隔符为 ”:” ),然后把截取的数字排序(假设第一列为数字),然后打印出重复次数超过10次的列;

1
2
3
4
5
#! /bin/bash

awk -F':' '$0~/abc/ {print $1}' test.log >/tmp/n.txt
sort -n n.txt |uniq -c |sort -n >/tmp/n2.txt
awk '$1>10 {print $2}' /tmp/n2.txt

(6)判断输入的IP是否正确(IP的规则是,n1.n2.n3.n4,其中1<n1<255, 0<n2<255, 0<n3<255, 0<n4<255)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 #! /bin/bash

checkip() {

if echo $1 |egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' ; then
a=`echo $1 | awk -F. '{print $1}'`
b=`echo $1 | awk -F. '{print $2}'`
c=`echo $1 | awk -F. '{print $3}'`
d=`echo $1 | awk -F. '{print $4}'`

for n in $a $b $c $d; do
if [ $n -ge 255 ] || [ $n -le 0 ]; then
echo "the number of the IP should less than 255 and greate than 0"
return 2
fi
done
else

echo "The IP you input is something wrong, the format is like 192.168.100.1"
return 1
fi

}

rs=1
while [ $rs -gt 0 ]; do
read -p "Please input the ip:" ip
checkip $ip
rs=`echo $?`
done

echo "The IP is right!"
坚持原创技术分享,您的支持将鼓励我继续创作!