超级实用的shell脚本100例(二)

21. 使用 expect 工具自动交互密码远程其他主机安装 httpd 软件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

#删除~/.ssh/known_hosts 后,ssh 远程任何主机都会询问是否确认要连接该主机

rm ‐rf ~/.ssh/known_hosts

expect <<EOF

spawn ssh 192.168.4.254

expect "yes/no" {send "yes\r"}

#根据自己的实际情况将密码修改为真实的密码字串

expect "password" {send "密码\r"}

expect "#" {send "yum ‐y install httpd\r"}

expect "#" {send "exit\r"}

EOF

22.一键部署 LNMP(源码安装版本)

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/bin/bash

menu(){
clear
echo " ##############‐‐‐‐Menu‐‐‐‐##############"
echo "# 1. Install Nginx"
echo "# 2. Install MySQL"
echo "# 3. Install PHP"
echo "# 4. Exit Program"
echo " ########################################"
}

choice(){
read ‐p "Please choice a menu[1‐9]:" select
}

install_nginx(){
id nginx &>/dev/null
if [ $? ‐ne 0 ];then
useradd ‐s /sbin/nologin nginx
fi
if [ ‐f nginx‐1.8.0.tar.gz ];then
tar ‐xf nginx‐1.8.0.tar.gz
cd nginx‐1.8.0
yum ‐y install gcc pcre‐devel openssl‐devel zlib‐devel make
./configure ‐‐prefix=/usr/local/nginx ‐‐with‐http_ssl_module
make
make install
ln ‐s /usr/local/nginx/sbin/nginx /usr/sbin/
cd ..
else
echo "没有 Nginx 源码包"
fi
}
install_mysql(){
yum ‐y install gcc gcc‐c++ cmake ncurses‐devel perl
id mysql &>/dev/null
if [ $? ‐ne 0 ];then
useradd ‐s /sbin/nologin mysql
fi
if [ ‐f mysql‐5.6.25.tar.gz ];then
tar ‐xf mysql‐5.6.25.tar.gz
cd mysql‐5.6.25
cmake .
make
make install
/usr/local/mysql/scripts/mysql_install_db ‐‐user=mysql ‐‐ datadir=/usr/local/mysql/data/‐‐basedir=/usr/local/mysql/

chown ‐R root.mysql /usr/local/mysql
chown ‐R mysql /usr/local/mysql/data
/bin/cp ‐f /usr/local/mysql/support‐files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
/bin/cp ‐f /usr/local/mysql/support‐files/my‐default.cnf /etc/my.cnf
echo "/usr/local/mysql/lib/" >> /etc/ld.so.conf
ldconfig
echo 'PATH=\$PATH:/usr/local/mysql/bin/' >> /etc/profile
export PATH
else
echo "没有 mysql 源码包"
exit
fi
}
install_php(){
#安装 php 时没有指定启动哪些模块功能,如果的用户可以根据实际情况自行添加额外功能如‐‐with‐gd 等
yum ‐y install gcc libxml2‐devel
if [ ‐f mhash‐0.9.9.9.tar.gz ];then
tar ‐xf mhash‐0.9.9.9.tar.gz
cd mhash‐0.9.9.9
./configure
make
make install
cd ..
if [ ! ‐f /usr/lib/libmhash.so ];then
ln ‐s /usr/local/lib/libmhash.so /usr/lib/
fi
ldconfig
else
echo "没有 mhash 源码包文件"
exit
fi
if [ ‐f libmcrypt‐2.5.8.tar.gz ];then
tar ‐xf libmcrypt‐2.5.8.tar.gz
cd libmcrypt‐2.5.8
./configure
make
make install
cd ..
if [ ! ‐f /usr/lib/libmcrypt.so ];then
ln ‐s /usr/local/lib/libmcrypt.so /usr/lib/
fi
ldconfig
else
echo "没有 libmcrypt 源码包文件"
exit
fi

if [ ‐f php‐5.4.24.tar.gz ];then
tar ‐xf php‐5.4.24.tar.gz
cd php‐5.4.24
./configure ‐‐prefix=/usr/local/php5 ‐‐with‐mysql=/usr/local/mysql ‐‐enable‐fpm ‐‐enable‐mbstring ‐‐with‐mcrypt ‐‐with‐mhash ‐‐with‐config‐file‐path=/usr/local/php5/etc ‐‐with‐mysqli=/usr/local/mysql/bin/mysql_config
make && make install
/bin/cp ‐f php.ini‐production /usr/local/php5/etc/php.ini
/bin/cp ‐f /usr/local/php5/etc/php‐fpm.conf.default /usr/local/php5/etc/php‐fpm.conf
cd ..
else
echo "没有 php 源码包文件"
exit
fi
}
while :
do
menu
choice
case $select i
)
install_nginx
;;
2)
install_mysql
;;
3)
install_php
;;
4)
exit
;;
*)
echo Sorry!
esac
done

23. 编写脚本快速克隆 KVM 虚拟机

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/bin/bash
#本脚本针对 RHEL7.2 或 Centos7.2
#本脚本需要提前准备一个 qcow2 格式的虚拟机模板,名称为/var/lib/libvirt/images /.rh7_template 的虚
拟机模板
#该脚本使用 qemu‐img 命令快速创建快照虚拟机
#脚本使用 sed 修改模板虚拟机的配置文件,将虚拟机名称、UUID、磁盘文件名、MAC 地址
# exit code:
# 65 ‐> user input nothing
# 66 ‐> user input is not a number
# 67 ‐> user input out of range
# 68 ‐> vm disk image exists

IMG_DIR=/var/lib/libvirt/images
BASEVM=rh7_template
read ‐p "Enter VM number: " VMNUM
if [ $VMNUM ‐le 9 ];then
VMNUM=0$VMNUM
fi

if [ ‐z "${VMNUM}" ]; then
echo "You must input a number."
exit 65
elif [[ ${VMNUM} =~ [a‐z] ]; then
echo "You must input a number."
exit 66
elif [ ${VMNUM} ‐lt 1 ‐o ${VMNUM} ‐gt 99 ]; then
echo "Input out of range"
exit 67
fi
NEWVM=rh7_node${VMNUM}
if [ ‐e $IMG_DIR/${NEWVM}.img ]; then
echo "File exists."
exit 68
fi
echo ‐en "Creating Virtual Machine disk image......\t"
qemu‐img create ‐f qcow2 ‐b $IMG_DIR/.${BASEVM}.img $IMG_DIR/${NEWVM}.img &> /dev/null
echo ‐e "\e[32;1m[OK]\e[0m"
#virsh dumpxml ${BASEVM} > /tmp/myvm.xml
cat /var/lib/libvirt/images/.rhel7.xml > /tmp/myvm.xml
sed ‐i "/<name>${BASEVM}/s/${BASEVM}/${NEWVM}/" /tmp/myvm.xml
sed ‐i "/uuid/s/<uuid>.*<\/uuid>/<uuid>$(uuidgen)<\/uuid>/" /tmp/myvm.xml
sed ‐i "/${BASEVM}\.img/s/${BASEVM}/${NEWVM}/" /tmp/myvm.xml
#修改 MAC 地址,本例使用的是常量,每位使用该脚本的用户需要根据实际情况修改这些值
#最好这里可以使用便利,这样更适合于批量操作,可以克隆更多虚拟机
sed ‐i "/mac /s/a1/0c/" /tmp/myvm.xml
echo ‐en "Defining new virtual machine......\t\t"
virsh define /tmp/myvm.xml &> /dev/null
echo ‐e "\e[32;1m[OK]\e[0m"

24. 编写一个点名器脚本

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
#该脚本,需要提前准备一个 user.txt 文件
#该文件中需要包含所有姓名的信息,一行一个姓名,脚本每次随机显示一个姓名
while :
do
#统计 user 文件中有多少用户
line=`cat user.txt |wc ‐l`
num=$[RANDOM%line+1]
sed ‐n "${num}p" user.txt
sleep 0.2
clear
done

25. 查看有多少远程的 IP 在连接本机(不管是通过 ssh 还是 web 还是 ftp 都统计)

1
2
3
4
5
6
7
8
#!/bin/bash
#使用 netstat ‐atn 可以查看本机所有连接的状态,‐a 查看所有,‐t 仅显示 tcp 连接的信息,‐n 数字格式显示
# Local Address(第四列是本机的 IP 和端口信息)
#Foreign Address(第五列是远程主机的 IP 和端口信息)
#使用 awk 命令仅显示第 5 列数据,再显示第 1 列 IP 地址的信息
#sort 可以按数字大小排序,最后使用 uniq 将多余重复的删除,并统计重复的次数

netstat ‐atn | awk '{print $5}' | awk '{print $1}' | sort ‐nr | uniq ‐c

26. 对 100 以内的所有正整数相加求和(1+2+3+4…+100)

1
2
3
4
5
6
7
8
#!/bin/bash
#seq 100 可以快速自动生成 100 个整数
sum=0
for i in `seq 100`
do
sum=$[sum+i]
done
echo "总和是:$sum"

27. 统计 13:30 到 14:30 所有访问 apache 服务器的请求有多少个

1
2
3
4
5
#!/bin/bash
#awk 使用‐F 选项指定文件内容的分隔符是/或者:
#条件判断$7:$8 大于等于 13:30,并且要求,$7:$8 小于等于 14:30
#最后使用 wc ‐l 统计这样的数据有多少行,即多少个
awk ‐F "[ /:]" '$7":"$8>="13:30" && $7":"$8<="14:30"' /var/log/httpd/access_log |wc ‐l

28. 统计 13:30 到 14:30 所有访问本机 Aapche 服务器的远程 IP 地址是什么

1
2
3
4
5
#!/bin/bash
#awk 使用‐F 选项指定文件内容的分隔符是/或者:
#条件判断$7:$8 大于等于 13:30,并且要求,$7:$8 小于等于 14:30
#日志文档内容里面,第 1 列是远程主机的 IP 地址,使用 awk 单独显示第 1 列即可
awk ‐F "[ /:]" '$7":"$8>="13:30" && $7":"$8<="14:30"{print $1}' /var/log/httpd/access_log

29. 打印国际象棋棋盘,效果如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
#设置两个变量,i 和 j,一个代表行,一个代表列,国际象棋为 8*8 棋盘
#i=1 是代表准备打印第一行棋盘,第 1 行棋盘有灰色和蓝色间隔输出,总共为 8 列
#i=1,j=1 代表第 1 行的第 1 列;i=2,j=3 代表第 2 行的第 3 列
#棋盘的规律是 i+j 如果是偶数,就打印蓝色色块,如果是奇数就打印灰色色块
#使用 echo ‐ne 打印色块,并且打印完成色块后不自动换行,在同一行继续输出其他色块
for i in {1..8}
do
for j in {1..8}
do
sum=$[i+j]
if [ $[sum%2] ‐eq 0 ];then
echo ‐ne "\033[46m \033[0m"
else
echo ‐ne "\033[47m \033[0m"
fi
done
echo
done

30. 统计每个远程 IP 访问了本机 apache 几次?

1
2
#!/bin/bash
awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log

31. 统计当前 Linux 系统中可以登录计算机的账户有多少个

1
2
3
4
5
#!/bin/bash
#方法 1:
grep "bash$" /etc/passwd | wc ‐l
#方法 2:
awk ‐f: '/bash$/{x++}end{print x}' /etc/passwd

32. 统计/var/log 有多少个文件,并显示这些文件名

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
#使用 ls 递归显示所有,再判断是否为文件,如果是文件则计数器加 1
cd /var/log
sum=0
for i in `ls ‐r *`
do
if [ ‐f $i ];then
let sum++
echo "文件名:$i"
fi
done
echo "总文件数量为:$sum"

33. 自动为其他脚本添加解释器信息#!/bin/bash,如脚本名为 test.sh 则效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
#./test.sh abc.sh
自动为 abc.sh 添加解释器信息
#./test.sh user.sh
自动为 user.sh 添加解释器信息
#先使用 grep 判断对象脚本是否已经有解释器信息,如果没有则使用 sed 添加解释器以及描述信息
if ! grep ‐q "^#!" $1; then
sed '1i #!/bin/bash' $1
sed '2i #Description: '
fi
#因为每个脚本的功能不同,作用不同,所以在给对象脚本添加完解释器信息,以及 Description 后还希望
#继续编辑具体的脚本功能的描述信息,这里直接使用 vim 把对象脚本打开,并且光标跳转到该文件的第 2 行
vim +2 $1

34. 自动化部署 varnish 源码包软件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
#本脚本需要提前下载 varnish‐3.0.6.tar.gz 这样一个源码包软件,该脚本即可用自动源码安装部署软件

yum ‐y install gcc readline‐devel pcre‐devel
useradd ‐s /sbin/nologin varnish
tar ‐xf varnish‐3.0.6.tar.gz
cd varnish‐3.0.6

#使用 configure,make,make install 源码安装软件包
./configure ‐‐prefix=/usr/local/varnish
make && make install

#在源码包目录下,将相应的配置文件拷贝到 Linux 系统文件系统中
#默认安装完成后,不会自动拷贝或安装配置文件到 Linux 系统,所以需要手动 cp 复制配置文件
#并使用 uuidgen 生成一个随机密钥的配置文件

cp redhat/varnish.initrc /etc/init.d/varnish
cp redhat/varnish.sysconfig /etc/sysconfig/varnish
cp redhat/varnish_reload_vcl /usr/bin/
ln ‐s /usr/local/varnish/sbin/varnishd /usr/sbin/
ln ‐s /usr/local/varnish/bin/* /usr/bin
mkdir /etc/varnish
cp /usr/local/varnish/etc/varnish/default.vcl /etc/varnish/
uuidgen > /etc/varnish/secret

35. 编写 nginx 启动脚本

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash

#本脚本编写完成后,放置在/etc/init.d/目录下,就可以被 Linux 系统自动识别到该脚本
#如果是centos7以上的版本就是systemctl stop nginx,这种类型
#如果本脚本名为/etc/init.d/nginx,则 service nginx start 就可以启动该服务
#service nginx stop 就可以关闭服务
#service nginx restart 可以重启服务
#service nginx status 可以查看服务状态

program=/usr/local/nginx/sbin/nginx
pid=/usr/local/nginx/logs/nginx.pid
start(){
if [ ‐f $pid ];then
echo "nginx 服务已经处于开启状态"
else
$program
fi
stop(){
if [ ‐! ‐f $pid ];then
echo "nginx 服务已经关闭"
else
$program ‐s stop
echo "关闭服务 ok"
fi
}
status(){
if [ ‐f $pid ];then
echo "服务正在运行…"
else
echo "服务已经关闭"
fi
}
case $1 in
start)
start;;
stop)
stop;;
restart)
stop
sleep 1
start;;
status)
status;;
*)
echo "你输入的语法格式错误"
esac

36. 自动对磁盘分区、格式化、挂载

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
#!/bin/bash
#对虚拟机的 vdb 磁盘进行分区格式化,使用<<将需要的分区指令导入给程序 fdisk
#n(新建分区),p(创建主分区),1(分区编号为 1),两个空白行(两个回车,相当于将整个磁盘分一个区)
#注意:1 后面的两个回车(空白行)是必须的!
fdisk /dev/vdb << EOF
n
p
1


wq
EOF

#格式化刚刚创建好的分区
mkfs.xfs /dev/vdb1

#创建挂载点目录
if [ ‐e /data ]; then
exit
fi
mkdir /data

#自动挂载刚刚创建的分区,并设置开机自动挂载该分区
echo '/dev/vdb1 /data xfs defaults 1 2' >> /etc/fstab
mount ‐a

37. 自动优化 Linux 内核参数

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
#!/bin/bash
#脚本针对 RHEL7
cat >> /usr/lib/sysctl.d/00‐system.conf <<EOF
fs.file‐max=65535
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 5
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
#net.ipv4.tcp_keepalive_time = 120
net.ipv4.ip_local_port_range = 1024 65535
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 5010 641280 5010 128
net.core.wmem_default=262144
net.core.wmem_max=262144
net.core.rmem_default=4194304
net.core.rmem_max=4194304
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
EOF
sysctl –p

38. 切割 Nginx 日志文件(防止单个文件过大,后期处理很困难)

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
#mkdir /data/scripts
#vim /data/scripts/nginx_log.sh

#!/bin/bash
logs_path="/usr/local/nginx/logs/"
mv ${logs_path}access.log ${logs_path}access_$(date ‐d "yesterday" +"%Y%m%d").log
kill ‐USR1 `cat /usr/local/nginx/logs/nginx.pid`
# chmod +x /data/scripts/nginx_log.sh
#crontab ‐e #脚本写完后,将脚本放入计划任务每天执行一次脚本
0 1 * * * /data/scripts/nginx_log.sh

39. 检测 MySQL 数据库连接数量

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
#本脚本每 2 秒检测一次 MySQL 并发连接数,可以将本脚本设置为开机启动脚本,或在特定时间段执行
#以满足对 MySQL 数据库的监控需求,查看 MySQL 连接是否正常
#本案例中的用户名和密码需要根据实际情况修改后方可使用
log_file=/var/log/mysql_count.log
user=root
passwd=123456
while :
do
sleep 2
count=`mysqladmin ‐u "$user" ‐p "$passwd" status | awk '{print $4}'`
echo "`date +%Y‐%m‐%d` 并发连接数为:$count" >> $log_file
done

40. 根据 md5 校验码,检测文件是否被修改

1
2
3
4
5
6
7
8
9
#!/bin/bash

#本示例脚本检测的是/etc 目录下所有的 conf 结尾的文件,根据实际情况,您可以修改为其他目录或文件
#本脚本在目标数据没有被修改时执行一次,当怀疑数据被人篡改,再执行一次
#将两次执行的结果做对比,MD5 码发生改变的文件,就是被人篡改的文件
for i in $(ls /etc/*.conf)
do
md5sum "$i" >> /var/log/conf_file.log
done