【脚本77】监控cpu使用率
用shell写一个监控服务器cpu使用率的监控脚本。
思路:
用top -bn1 命令,取当前空闲cpu百份比值(只取整数部分),然后用100去剑这个数值。参考代码:
#!/bin/bash
while :
do
idle=`top -bn1 |sed -n '3p' |awk '{print $5}'|cut -d . -f1`
use=$[100-$idle]
if [ $use -gt 90 ]
then
echo "cpu use percent too high."
#发邮件省略
fi
sleep 10
done
【脚本78】获取子进程
- 说明:
本shell题目是一个网友在公众号中提问的,正好利用这个每日习题的机会拿出来让大家一起做一做。
给出一个进程PID,打印出该进程下面的子进程以及子进程下面的所有子进程。(只需要考虑子进程的子进程,再往深层次则不考虑)
- 参考代码:
#!/bin/bash
read -p "please input a pid number: " p
ps -elf > /tmp/ps.log
is_ppid(){
awk '{print $5}' /tmp/ps.log > /tmp/ps1.log
if ! grep -qw "$1" /tmp/ps1.log
then
echo "PID $1 不是系统进程号,或者它不是父进程"
return 1
fi
}
is_ppid $p
if [ $? -eq "1" ]
then
exit
fi
print_cpid(){
p=$1
awk -v p1=$p '$5 == p1 {print $4}' /tmp/ps.log |sort -n |uniq >/tmp/p1.log
n=`wc -l /tmp/p1.log|awk '{print $1}'`
if [ $n -ne 0 ]
then
echo "PID $p 子进程 pid 如下:"
cat /tmp/p1.log
else
echo "PID $p 没有子进程"
fi
}
print_cpid $p
for cp in `cat /tmp/p1.log`
do
print_cpid $cp
done
另外,一条命令查询的方法是:
pstree -p pid
【脚本79】自动添加项目
- 需求背景:
服务器上,跑的lamp环境,上面有很多客户的项目,每个项目就是一个网站。 由于客户在不断增加,每次增加一个客户,就需要配置相应的mysql、ftp以及httpd. 这种工作是重复性非常强的,所以用脚本实现非常合适。
mysql增加的是对应客户项目的数据库、用户、密码,ftp增加的是对应项目的用户、密码(使用vsftpd,虚拟用户模式),httpd就是要增加虚拟主机配置段。
- 参考代码:
#!/bin/bash
webdir=/home/wwwroot
ftpudir=/etc/vsftpd/vuuser
mysqlc="/usr/bin/mysql -uroot -xxxxxx"
httpd_config_f="/usr/local/apache2/conf/extra/httpd-vhosts.conf"
add_mysql_user()
{
mysql_p=`mkpasswd -s 0 -l 12`
echo "$pro $mysql_p" >/tmp/$pro.txt
$mysqlc <<EOF
grant all on $p.* to "$pro"@'127.0.0.1' identified by "$mysql_p";
EOF
}
add_ftp_user()
{
ftp_p=`mkpasswd -s 0 -l 12`
echo "$pro" >> /root/login.txt
echo "$ftp_p" >> /root/login.txt
db_load -T -t hash -f /root/login.txt /etc/vsftpd/vsftpd_login.db
cd $ftpudir
cp aaa $pro //这里的aaa是一个文件,是之前的一个项目,可以作为配置模板
sed -i "s/aaa/$pro/" $pro //把里面的aaa改为新的项目名字
/etc/init.d/vsftpd restart
}
config_httpd()
{
mkdir $webdir/$pro
chown vsftpd:vsftpd $webdir/$pro
echo -e "<VirtualHost *:80> \n DocumentRoot "/home/internet/www/$pro/" \n ServerName $dom \n #ServerAlias \n</VirtualHost> " >> $httpd_config_f
/usr/local/apache2/bin/apachectl graceful
}
read -p "input the project name: " pro
read -p "input the domain: " dom
add_mysql_user
add_ftp_user
config_httpd
【脚本80】计算器
用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2
- 参考代码:
#!/bin/bash
if [ $# -ne 3 ]
then
echo "参数个数不为3"
echo "当使用乘法时,需要加上脱义符号,例如 $0 1 \* 2"
exit 1;
fi
num1=`echo $1|sed 's/[0-9.]//g'` ;
if [ -n "$num1" ]
then
echo "$1 不是数字" ;
exit 1
fi
num3=`echo $3|sed 's/[0-9.]//g'` ;
if [ -n "$num3" ]
then
echo "$3 不是数字" ;
exit 1
fi
case $2 in
+)
echo "scale=2;$1+$3" | bc
;;
-)
echo "scale=2;$1-$3" | bc
;;
\*)
echo "scale=2;$1*$3" | bc
;;
/)
echo "scale=2;$1/$3" | bc
;;
*)
echo "$2 不是运算符"
;;
esac
【脚本81】判断没有文件
判断所给目录内哪些二级目录下没有text.txt文件。
有text.txt文件的二级目录,根据文件计算选项中单词数最大的值(选项间以|分割,单词间以空格分隔)。
假如脚本名字为1.sh, 运行脚本的格式为 ./1.sh 123 root,其中123为目录名字,而root为要计算数量的单词。
说明:
这个shell脚本题目出的有点歧义。 原题给的描述不是很清楚,我另外又改了一下需求,依然不是很清晰。在这里我再做一个补充: 对于有test.txt的目录,计算出该test.txt文件里面所给出单词的次数。不用找最大。参考代码:
#!/bin/bash
if [ $# -ne 2 ]
then
echo "useage $0 dir word"
exit 1
fi
if [ -d $1 ]
then
cd $1
else
echo "$1目录不存在"
exit 1
fi
for f in `ls $1`
do
if [ -d $f ]
then
if [ -f $f/test.txt ]
then
n=`grep -cw "$2" $f/test.txt`
echo "$1/$f/test.txt 里面有$n个$2"
else
echo "$1/$f 下面没有test.txt"
fi
fi
done
【脚本82】打印正方形
交互式脚本,根据提示,需要用户输入一个数字作为参数,最终打印出一个正方形。
在这里我提供一个linux下面的特殊字符■,可以直接打印出来。
- 示例:
如果用户输入数字为5,则最终显示的效果为:
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
- 参考代码:
#!/bin/bash
read -p "please input a number:" sum
a=`echo $sum |sed 's/[0-9]//g'`
if [ -n "$a" ]
then
echo "请输入一个纯数字。"
exit 1
fi
for n in `seq $sum`
do
for m in `seq $sum`
do
if [ $m -lt $sum ]
then
echo -n "■ "
else
echo "■"
fi
done
done
【脚本83】问候用户
写一个脚本,依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么:
Hello,root,your UID is 0.
- 参考命令:
awk -F ':' '{print "Hello,"$1",your uid is "$3.}' /etc/passwd
【脚本84】按要求处理文本
linux系统 /home目录下有一个文件test.xml,内容如下:
<configuration>
<artifactItems>
<artifactItem>
<groupId>zzz</groupId>
<artifactId>aaa</artifactId>
</artifactItem>
<artifactItem>
<groupId>xxx</groupId>
<artifactId>yyy</artifactId>
</artifactItem>
<!-- </artifactItem><groupId>some groupId</groupId>
<version>1.0.1.2.333.555</version> </artifactItem>-->
</artifactItems>
</configuration>
请写出shell脚本删除文件中的注释部分内容,获取文件中所有artifactItem的内容,并用如下格式逐行输出 artifactItem:groupId:artifactId
分析:
这个文件比较特殊,但是却很有规律。注释部分内容其实就是<!– –>中间的内容,所以我们想办法把这些内容删除掉就ok了。而artifactItem的内容,其实就是获取<artifactItem></artifactItem>
中间的内容。然后想办法用提到的格式输出即可。参考代码:
#!/bin/bash
egrep -v '<!--|-->' 1.txt |tee 2.txt //这行就是删除掉注释的行
grep -n 'artifactItem>' 2.txt |awk '{print $1}' |sed 's/://' > /tmp/line_number.txt
n=`wc -l /tmp/line_number.txt|awk '{print $1}'`
get_value(){
sed -n "$1,$2"p 2.txt|awk -F '<' '{print $2}'|awk -F '>' '{print $1,$2}' > /tmp/value.txt
nu=`wc -l /tmp/value.txt|awk '{print $1}'`
for i in `seq 1 $nu`
do
x=`sed -n "$i"p /tmp/value.txt|awk '{print $1}'`
y=`sed -n "$i"p /tmp/value.txt|awk '{print $2}'`
echo artifactItem:$x:$y
done
}
n2=$[$n/2]
for j in `seq 1 $n2`
do
m1=$[$j*2-1]
m2=$[$j*2]
nu1=`sed -n "$m1"p /tmp/line_number.txt`
nu2=`sed -n "$m2"p /tmp/line_number.txt`
nu3=$[$nu1+1]
nu4=$[$nu2-1]
get_value $nu3 $nu4
done
【脚本85】判断函数
请使用条件函数if撰写一个shell函数 函数名为 f_judge,实现以下功能:
当/home/log 目录存在时 将/home目录下所有tmp开头的文件或目录移/home/log 目录。
当/home/log目录不存在时,创建该目录,然后退出。
- 参考代码:
#!/bin/bash
f_judge (){
if [ -d /home/log ]
then
mv /home/tmp* /home/log/
else
mkdir -p /home/log
exit
fi
}
【脚本86】批量杀进程
linux系统中,根目录/root/下有一个文件ip-pwd.ini,内容如下:
10.111.11.1,root,xyxyxy
10.111.11.1,root,xzxzxz
10.111.11.1,root,123456
10.111.11.1,root,xxxxxx
……
文件中每一行的格式都为linux服务器的ip,root用户名,root密码,请用一个shell批量将这些服务器中的所有tomcat进程kill掉。
- 讲解:
有了ip,用户名和密码,剩下的就是登录机器,然后执行命令了。批量登录机器,并执行命令,咱们课程当中有讲过一个expect脚本。所以本题就是需要这个东西来完成。
首先编辑expect脚本 kill_tomcat.expect:
#!/usr/bin/expect
set passwd [lindex $argv 0]
set host [lindex $argv 1]
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "killall java\r"
expect "]*"
send "exit\r"
编辑完后需要给这个文件执行权限:
chmod a+x kill_tomcat.expect
然后编辑shell脚本:
#!/bin/bash
n=`wc -l ip-pwd.ini`
for i in `seq 1 $n`
do
ip=`sed -n "$n"p ip-pwd.ini |awk -F ',' '{print $1}'`
pw=`sed -n "$n"p ip-pwd.ini |awk -F ',' '{print $3}'`
./kill_tomcat.expect $pw $ip
done
【脚本87】处理日志
写一个脚本查找/data/log目录下,最后创建时间是3天前,后缀是*.log的文件,打包后发送至192.168.1.2服务上的/data/log下,并删除原始.log文件,仅保留打包后的文件
- 参考代码:
#!/bin/bash
find /data/log -name “*.log” -mtime +3 > /tmp/file.list
cd /data/log
tar czvf log.tar.gz `cat /tmp/file.list|xargs`
rsync -a log.tar.gz 192.168.1.2:/data/log # 这一步需要提前做一个免密码登录
for f in `cat /tmp/file.list`
do
rm -f $f
done
【脚本88】处理文本
有如下文本,其中前5行内容为
1111111:13443253456
2222222:13211222122
1111111:13643543544
3333333:12341243123
2222222:12123123123
用shell脚本处理后,按下面格式输出:
[1111111]
13443253456
13643543544
[2222222]
13211222122
12123123123
[3333333]
12341243123
- 参考代码:
#! /bin/bash
sort -n filename |awk -F ':' '{print $1}'|uniq >id.txt
for id in `cat id.txt`; do
echo "[$id]"
awk -v id2=$id -F ':' '$1==id2 {print $2}' filename
#另外的方式为: awk -F ':' '$1=="'$id'" {print $2}' filename
done
【脚本89】清理日志
- 要求:
两类机器一共300多台,写个脚本自动清理这两类机器里面的日志文件。在堡垒机批量发布,也要批量发布到crontab里面。
A类机器日志存放路径很统一,B类机器日志存放路径需要用匹配(因为这个目录里除了日志外,还有其他文件,不能删除。匹配的时候可用.log)
A类:/opt/cloud/log/ 删除7天前的
B类: /opt/cloud/instances/ 删除15天前的
要求写在一个脚本里面。不用考虑堡垒机上的操作,只需要写出shell脚本。
- 参考代码:
#!/bin/bash
dir1=/opt/cloud/instances/
dir2=/opt/cloud/log/
if [ -d $dir1 ];then
find $dir1 -type f -name "*.log" -mtime +15 |xargs rm -f
elif [ -d $dir2 ];then
find $dir2 -type f -mtime +7 |xargs rm -f
fi
【脚本90】
贷款有两种还款的方式:等额本金法和等额本息法
简单说明一下等额本息法与等额本金法的主要区别:
等额本息法的特点是:每月的还款额相同,在月供中“本金与利息”的分配比例中,前半段时期所还的利息比例大、本金比例小,还款期限过半后逐步转为本金比例大、利息比例小。所支出的总利息比等额本金法多,而且贷款期限越长,利息相差越大。
等额本金法的特点是:每月的还款额不同,它是将贷款额按还款的总月数均分(等额本金),再加上上期剩余本金的月利息,形成一个月还款额,所以等额本金法第一个月的还款额最多 ,尔后逐月减少,越还越少。所支出的总利息比等额本息法少。
两种还款方式的比较不是我们今天的讨论范围,我们的任务就是做一个贷款计算器。
其中:等额本息每月还款额的计算公式是:
[贷款本金×月利率×(1+月利率)还款月数]÷[(1+月利率)还款月数-1]
- 参考代码:
#!/bin/bash
read -p "请输入贷款总额(单位:万元):" dkzewy
read -p "请输入贷款年利率(如年利率为6.5%,直接输入6.5):" dknll
read -p "请输入贷款年限(单位:年):" dknx
echo "贷款计算方式:"
echo "1)等额本金计算法"
echo "2)等额本息计算法"
read -p "请选择贷款方式(1|2)" dkfs
dkze=`echo "scale=2;$dkzewy*10000 " | bc -l`
dkll=`echo "scale=6;$dknll/100 " | bc -l`
dkyll=`echo "scale=6;$dkll/12 " | bc -l`
dkqc=$[$dknx*12]
echo "期次 本月还款额 本月利息 未还款额"
debjjsf()
{
yhbj=`echo "scale=2;($dkze/$dkqc)/1 " | bc -l`
whbj=$dkze
for((i=1;i<=$dkqc;i++))
do
bylx=`echo "scale=2;($whbj*$dkyll)/1 " | bc -l`
bybx=`echo "scale=2;($yhbj+$bylx)/1 " | bc -l`
yhke=`echo "scale=2;($yhbj*$i)/1 " | bc -l`
whbj=`echo "$dkze-$yhke " | bc -l`
if [ $i -eq $dkqc ]
then
yhbj=`echo "scale=2;($yhbj+$whbj)/1 " | bc -l`
whbj="0.00"
bybx=`echo "scale=2;($yhbj+$bylx)/1 " | bc -l`
fi
echo "$i $bybx $bylx $whbj"
done
}
debxjsf()
{
bybx=`echo "scale=2;(($dkze*$dkyll*((1+$dkyll)^$dkqc))/(((1+$dkyll)^$dkqc)-1))/1 " | bc -l`
whbj=$dkze
for((i=1;i<=$dkqc;i++))
do
bylx=`echo "scale=2;($whbj*$dkyll)/1 " | bc -l`
yhbj=`echo "scale=2;($bybx-$bylx)/1 " | bc -l`
whbj=`echo "scale=2;($whbj-$yhbj)/1 " | bc -l`
if [ $i -eq $dkqc ]
then
bybx=`echo "scale=2;($yhbj+$whbj)/1 " | bc -l`
whbj="0.00"
fi
echo "$i $bybx $bylx $whbj"
done
}
case $dkfs in
1) debjjsf
;;
2) debxjsf
;;
*) exit 1
;;
esac
【脚本91】监控磁盘io
阿里云的机器,今天收到客服来的电话,说服务器的磁盘io很重。于是登录到服务器查看,并没有发现问题,所以怀疑是间歇性地。
正要考虑写个脚本的时候,幸运的抓到了一个线索,造成磁盘io很高的幕后黑手是mysql。此时去show processlist,但未发现队列。原来只是一瞬间。
只好继续来写脚本,思路是,每5s检测一次磁盘io,当发现问题去查询mysql的processlist。
提示:
你可以用iostat -x 1 5 来判定磁盘的io,主要看%util参考代码:
#!/bin/bash
while :
do
n=`iostat -x 1 5 |tail -n3|head -n1 |awk '{print $NF}'|cut -d. -f1`
if [ $n -gt 70 ]
then
echo "`date` util% is $n%" >>/tmp/mysql_processlist.log
mysql -uroot -pxxxxxx -e "show full processlist" >> /tmp/mysql_processlist.log
fi
sleep 5
done