shell脚本实例入门精选系列

读取有效的电话号码

给定一个包含电话号码列表(一行一个电话号码)的文本文件 file.txt,写一个 bash 脚本输出所有有效的电话号码。

你可以假设一个有效的电话号码必须满足以下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)

你也可以假设每行前后没有多余的空格字符。

示例:

假设 file.txt 内容如下:

1
2
3
987-123-4567
123 456 7890
(123) 456-7890

你的脚本应当输出下列有效的电话号码:

1
2
987-123-4567
(123) 456-7890

实现脚本如下:

方法一:

1
sed -n -r '/^([0-9]{3}-|([0-9]{3}) )[0-9]{3}-[0-9]{4}$/p' file.txt

方法二:

1
2
3
grep -P '^(d{3}-|(d{3}) )d{3}-d{4}$' file.txt

grep -P '^([0-9]{3}-|([0-9]{3}) )[0-9]{3}-[0-9]{4}$' file.txt

方法三

1
awk '/^([0-9]{3}-|([0-9]{3}) )[0-9]{3}-[0-9]{4}$/' file.txt

其他参考

打印文件第十行

给定一个文本文件 file.txt,请只打印这个文件中的第十行。

示例:

假设 file.txt 有如下内容:

1
2
3
4
5
6
7
8
9
10
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10

你的脚本应当显示第十行:

1
Line 10

实现脚本如下:
方法一:

1
2
# Read from the file file.txt and output the tenth line to stdout.
sed -n '10p' file.txt

方法二:

1
sed -n '10{p;q}' file.txt

方法三:

1
awk "NR==10" file.txt

方法四:

1
cat file.txt | awk 'NR==10'

方法五:

1
cat file.txt | head -10 | tail -1

centos下常用参数

1.提取IP地址

1
$ ifconfig  | grep inet | grep -v 127.0.0.1 | grep -v inet6| awk -F ' ' '{print $2}'

2.格式化日期

1
DATE=$(date +%F" "%H:%M)

3.内存空闲情况查询

1
2
3
TOTAL=$(free -m | awk '/Mem/{print $2}')
USE=$(free -m | awk '/Mem/{print $3+$6}')
FREE=$(($TOTAL-$USE))

4.磁盘参数

1
2
TOTAL=$(fdisk -l | grep Disk | awk -F '[ ,]' 'NR==1{print $2,$3,$4,$5}')
PART_USE=$(df -h | grep "/dev/vda1" | awk -F '[ %]+' '{print $1,$5,$6}')

5.查看网络连接情况

1
sudo awk '{print $1}' |sort|uniq -c|sort -nr |head -10 /var/log/auth.log

6.按连接数查看客户端ip,根据ip分组计数

1
2
3
4
5
6
$ netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c
1 100.100.30.25
2 112.213.179.149
1 173.255.234.138
1 47.52.207.198
1 47.93.222.200

其他参考

检测服务是否启动成功

示例:检测ssh服务是否启动成功,有多种方法,这里只列举一种。

1
2
3
4
5
6
7
8
9
10
11
12
$ cat service.sh 
# 检查服务状态的脚本

# ss -anu 查看所有udp连接
PORT_C=$(ss -anu | grep -c 123)
PS_C=$(ps -ef | grep sshd | grep -vc grep)
# if中-o 布尔运算中的或运算 只要一个为true则都为true
if [ $PORT_C -eq 0 -o $PS_C -eq 0 ];then
echo "sshd启动失败" | mail -s "ssh服务" [email protected]
else
echo "ssh启动成功"
fi

执行脚本,结果如下:

1
2
$ ./service.sh 
ssh启动成功

检查主机存活状态

1.将错误次数存放在数组里面,以此来判断主机存活状态

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
# 检查主机存活状态
$ cat hostacting.sh
#!/bin/bash
IP_LIST="114.112.114.114 1.2.4.8"
for IP in $IP_LIST;do
NUM=1
while [ $NUM -le 3 ]
do
if ping -c 1 $IP > /dev/null;then
echo "$IP Ping is successful."
break
else
# ping三次,统计失败的次数
FAIL_COUNT[$NUM]=$IP
let NUM++
fi
done
#
echo "fail_count(数组元素个数为//3): ${#FAIL_COUNT[*]}"
# echo "failcount1(数组元素为//IP地址): ${FAIL_COUNT[1]}"
if [ ${#FAIL_COUNT[*]} -eq 3 ];then
echo "${FAIL_COUNT[1]} Ping is failure!!!"
# 清空数组
unset FAIL_COUNT[*]
fi
done

执行脚本,结果如下:

1
2
3
4
5
$ ./hostacting.sh   
# fail_count(数组元素个数为//3): 3
114.112.114.114 Ping is failure!!!
1.2.4.8 Ping is successful.
# fail_count(数组元素个数为//3): 0

2.通过计数判断主机存活状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat hostacting1.sh
#!/bin/bash
IP_LIST="114.114.114.114 124.123.12.134"
for IP in $IP_LIST;do
FAIL_COUNT=0
for((i=1;i<=3;i++));do
if ping -c 1 $IP >/dev/null;then
echo "$IP Ping is successful."
break
else
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ];then
echo "$IP Ping is failure!!!"
fi
done

执行脚本,结果如下:

1
2
3
$ ./hostacting1.sh 
114.114.114.114 Ping is successful.
124.123.12.134 Ping is failure!!!

3.通过跳出循环的方式来判断主机存活状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat hostacting2.sh 

(){
if ping -c 1 $IP >/dev/null;then
echo "$IP Ping is successful."
continue
fi
}
IP_LIST="114.114.114.114 123.13.13.23"
for IP in $IP_LIST;do
ping_success_status
ping_success_status
ping_success_status
echo "$IP Ping is failure!!!"
done

执行脚本,结果如下:

1
2
3
$ ./hostacting2.sh   
114.114.114.114 Ping is successful.
123.13.13.23 Ping is successful.

使用vmstat工具来分析CPU的统计信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ cat cpu.sh
#!/bin/bash
DATE=$(date +%F" "%H:%M)
IP=$(ifconfig | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk -F " " '{print $2}' )
MAIL="[email protected]"
# 如果vmstat不存在
if ! which vmstat &>/dev/null;then
echo "vmstat command no found,Please install procps package."
exit 1
fi
# NR==3 取第三行
US=$(vmstat | awk 'NR==3{print $13}')
SY=$(vmstat | awk 'NR==3{print $14}')
IDLE=$(vmstat | awk 'NR==3{print $15}')
WAIT=$(vmstat | awk 'NR==3{print $16}')
USE=$(($US+$SY))
# echo "use:$USE"
if [ $USE -ge 0 ];then
echo "
Date: $DATE
Host: $IP
Problem: CPU utilization $USE
" | mail -s "CPU Monitor" $MAIL
fi

执行脚本,结果如下:

1
2
3
4
5
$ ./cpu.sh 

Date: 2019-08-20 09:01
Host: 172.17.104.191
Problem: CPU utilization 0

使用free分析内存信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat memory.sh 
#!/bin/bash
# 格式化日期 后面不能有空格
DATE=$(date +%F" "%H:%M)
MAIL="[email protected]"
# 获取IP地址
IP=$(ifconfig | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk -F ' ' '{print $2}')
# awk '/Mem/' 模式匹配 匹配包含Mem的一行
TOTAL=$(free -m | awk '/Mem/{print $2}')
USE=$(free -m | awk '/Mem/{print $3+$6}')
FREE=$(($TOTAL-$USE))
# 内存小于1.0G输出信息
if [ $FREE -lt 1024 ];then
echo "
Date: $DATE
Host: $IP
Problem:Total=$TOTAL,Use=$USE,Free=$FREE
" | mail -s "Memory Monitor" $MAIL
fi

执行脚本,结果如下:

1
2
3
4
$ ./memory.sh 
Date: 2019-08-20 09:02
Host: 172.17.104.191
Problem:Total=1839,Use=890,Free=949

监控磁盘利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat fdisk.sh 
#!/bin/bash
DATE=$(date +%F" "%H:%M)
# grep -v 表示取反匹配
IP=$(ifconfig | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk -F ' ' '{print $2}')
# MAIL="[email protected]"
TOTAL=$(fdisk -l | grep Disk | awk -F '[ ,]' 'NR==1{print $2,$3,$4,$5}')
PART_USE=$(df -h | grep "/dev/vda1" | awk -F '[ %]+' '{print $1,$5,$6}')
PART=$(echo $PART_USE | cut -d " " -f1)
USE=$(echo $PART_USE | cut -d " " -f2)
MOUNT=$(echo $PART_USE | cut -d " " -f3)
if [ $USE -gt 3 ];then
echo "
Date: $DATE
Host: $IP
Total: $TOTAL
Problem: $PART'已使用:'$USE%
"
fi

执行脚本,结果如下:

1
2
3
4
5
6
$ ./fdisk.sh 

Date: 2019-08-20 11:20
Host: 172.17.104.191
Total: /dev/vda: 42.9 GB
Problem: /dev/vda1'已使用:'5%

判断url可用性

1.判断三次URL可用性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cat check_url.sh 

check_url(){
# curl
# -o 把输出写到文件中
# --connect-timeout 设置最大请求时间
# -s 静默模式,不输出任何东西
# -w 什么输出完成后
# $1 函数取第一个参数,这里取$URL
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $1)
if [ $HTTP_CODE -eq 200 ];then
echo "Suprise:$URL Access success."
continue
fi
}
URL_LIST="www.baidu.com www.google.com www.1211111111111.com"
for URL in $URL_LIST ;do
check_url $URL
check_url $URL
check_url $URL
echo "Warning: $URL Access failure!"
done

执行脚本,结果如下:

1
2
3
4
$ ./check_url.sh 
Suprise:www.baidu.com Access success.
Warning: www.google.com Access failure!
Warning: www.1211111111111.com Access failure!

2.通过将错误保存在数组判断url存活

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat check_url1.sh 
#!/bin/bash
URL_LIST="www.baidu.com www.1233333311111.com www.sougou.com"
for URL in $URL_LIST
do
FAIL_COUNT=0
for((i=1;i<=3;i++))
do
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $URL)
if [ $HTTP_CODE -ne 200 ];then
let FAIL_COUNT++
else
echo "Suprise: $URL access successful."
break
fi
done
if [ $FAIL_COUNT -eq 3 ];then
echo "Warning: $URL access failure!"
fi
done

执行脚本,结果如下:

1
2
3
4
$ ./check_url1.sh
Suprise: www.baidu.com access successful.
Warning: www.1233333311111.com access failure!
Suprise: www.sougou.com access successful.

3.通过将错误保存到变量来判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat check_url2.sh
#!/bin/bash
URL_LIST="www.sougou.com www.anne1111111.com www.baidu.com"
for URL in $URL_LIST;do
NUM=1
while [ $NUM -le 3 ];do
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $URL)
if [ $HTTP_CODE -ne 200 ];then
# 创建数组,以$NUM为下标,$URL为传入数组的元素
FAIL_COUNT[$NUM]=$URL
echo "array_value:${FAIL_COUNT[*]}"
let NUM++
else
echo "Suprise: $URL access success."
break
fi
done
if [ ${#FAIL_COUNT[*]} -eq 3 ];then
echo "Warning: $URL access failure!"
# 清空数组
unset FAIL_COUNT[*]
fi
done

执行脚本,结果如下:

1
2
3
4
5
6
7
$ ./check_url2.sh  
Suprise: www.sougou.com access success.
# array_value:www.anne1111111.com
# array_value:www.anne1111111.com www.anne1111111.com
# array_value:www.anne1111111.com www.anne1111111.com www.anne1111111.com
Warning: www.anne1111111.com access failure!
Suprise: www.baidu.com access success.