shell编程脚本练习题
1.使用for循环在/oldboy目录下通过随机小写10个字母加固定字符串oldboy批量创建10个html文件,名称例如为: [root@oldboy oldboy]# sh /server/scripts/oldboy.sh [root@oldboy oldboy]# ls coaolvajcq_oldboy.html qnvuxvicni_oldboy.html vioesjmcbu_oldboy.html gmkhrancxh_oldboy.html tmdjormaxr_oldboy.html wzewnojiwe_oldboy.html jdxexendbe_oldboy.html ugaywanjlm_oldboy.html xzzruhdzda_oldboy.html qcawgsrtkp_oldboy.html vfrphtqjpc_oldboy.html
[root@www test]# cat shuijishu1.sh #!/sbin/bash path=/oldboy [ -d "$path" ]|| mkdir -p /oldboy for n in `seq 10` do randomnu=$(echo $RANDOM|md5sum |tr "[0-9]" "[a-z]"|cut -c 2-11) touch "$path/$randomnu"_oldboy.html done 注获取随机字符法2: openssl rand -base64 40|sed s#[^a-z]##g|cut -c 2-11
法一:[root@www oldboy]# rename "oldboy.html" "oldgirl.HTML" *.html 法二: [root@www test]# cat chongminming.sh #!/sbin/bash path=/oldboy cd $path for n in `ls` do name=$(echo ${n}|awk -F"_" '{print $1}') mv $n ${name}_oldgirl.HTML done 法三: ls /oldboy|xargs -n1|awk -F"_" '{print "mv " $0" "$1"_oldgirl.HTML"}'|bash
3.批量创建10个系统帐号oldboy01-oldboy10并设置密码(密码为随机8位字符串)。 法一: [root@www test]# cat creaccount.sh #!/sbin/bash [ $UID -ne 0 ]&&{ echo "please su - root" exit 1 } for n in `seq -w 10` do user=fengxiaoli$n word=`grep -w $user /etc/passwd|wc -l` if [ $word -eq 1 ];then echo "useradd $user already exists!" continue fi pass=$(echo $RANDOM|md5sum |cut -c 2-11) useradd $user && echo "$pass"|passwd --stdin $user &>/dev/null resut=$? if [ $resut -eq 0 ] then echo "$user create succss" echo "account=$user password=$pass" >>/tmp/acount.txt done
#Random number method #openssl rand -base64 40|cut -c 2-11 #echo $RANDOM|md5sum |cut -c 2-11" #double number method #seq -w 10 #echo {00..10}
法二: echo feng{01..10}|xargs -n1|sed -r ' s#(.*)#useradd 1;pass=$(echo $RANDOM|md5sum |cut -c 2-11);echo "$pass"|passwd --stdin 1;echo "1" t$pass>>/tmp/user.txt#g'|bash
[root@www test]# cat ping.sh 法一:此方法较慢,如果主机禁ping,则不能检测出主机 ip="192.168.1." cmd="ping -W 2 -c 2" for i in `seq 254` $cmd $ip$i &>/dev/null if [ $? -eq 0 ] echo "$ip$i is ok!" else echo "$ip$i is bad!" 法二:此方法较快,禁ping也能监测出主机,nmap功能很强大,建议了解 nmap -sP 192.168.1.*|grep "Nmap scan report for"|awk '{print $5 " is ok!"}'
5.写一个脚本解决DOS攻击生产案例 [ -f /etc/init.d/functions ] && . /etc/init.d/functions account=5 function ipt(){ awk '{print $1}' /application/nginx/logs/access.log |sort |uniq -c|sort -nr -k1 >>/tmp/ip.log#注意access.log日志需要按天或按小时分割出来,再来分析 exec </tmp/ip.log while read line IP=$(echo "$line"|awk '{print $2}') if [ `echo "$line"|awk '{print $1}'` -ge $account -a `iptables -L -n|grep "$IP" | wc -l` -lt 1 ];then iptables -I INPUT -s $IP -j DROP if [ $? -eq 0 ];then echo "$IP is DROP ok" echo "$IP" >>/tmp/ip_drop_`date +%F`.txt else echo "$IP is DROP false" function del(){ [ -f /tmp/ip_drop_`date +%F -d '-1day'`.txt ]||{ echo "the log is not exist" exec </tmp/ip_drop_`date +%F -d '-1day'`.txt if [ `iptables -L -n|grep "$line"|wc -l` -eq 1 ];then iptables -D INPUT -s $line -j DROP #main 函数也可以用计划任务替代 main(){ flag=0 while true sleep 180 #等待3分钟 ((flag++)) ipt [ $flag -ge 480 ]&&del&&flag=0 #当flag=480,也就是3*480分钟,等于24小时,意思是将前一天drop掉的ip允许访问 main 法二:注意这里的netstat.log是netstat命令里的内容 grep ESTABLISHED netstat.log |awk -F "[ :]+" '{print $6}'|sort |uniq -c |sort -rn -k1 法二只需将上面法一中IP获取方法替换即可
6.打印下面这句话中字母数不大于6的单词I am oldboy teacher welcome to oldboy training class echo "$word"|xargs -n1|awk 'length <6{print $1}' 法二: [root@www test]# tail 001.sh for word in ${array[*]} if [ `expr length $word` -lt 6 ];then #if [ ${#word} -lt 6 ];then #if [ `echo $word|wc -L` -lt 6 ];then echo $word 注:取单词长度方法 ${#变量} expr length 变量 echo 变量 |wc -L 7.开发shell脚本分别实现以脚本传参以及read读入的方式比较2个整数大小。以屏幕输出的方式提醒用户比较结果。注意:一共是开发2个脚本。当用脚本传参以及read读入的方式需要对变量是否为数字、并且传参个数做判断。 read -p "please input two int num:" a b if [ -z $a ]||[ -z $b ];then echo "please input two num!" expr $a + 10 >/dev/null 2>&1 if [ $? -ne 0 ];then echo "please input int num!" expr $b + 10 >/dev/null 2>&1 if [ $a -gt $b ];then echo "$a >$b" exit 0 elif [ $a -lt $b ];then echo "$a <$b" echo "$a=$b" 脚本传参方式只需将$a $b 替换会$1 $2即可
8.批量检查多个网站地址是否正常 要求:shell数组方法实现,检测策略尽量模拟用户访问思路 http://www.etiantian.org http://www.taobao.com http://oldboy.blog.51cto.com http://10.0.0.7 [root@www test]# cat 003.sh #!/sbin/bash [ -f /etc/init.d/functions ] && . /etc/init.d/functions array=( http://www.etiantian.org http://www.taobao.com http://10.117.33.193 ) for n in ${array[*]} do curl=$(wget --spider --timeout=3 --tries=2 $n &>/dev/null) if [ `echo $?` -eq 0 ];then action "curl $n" /bin/true else action "curl $n" /bin/false fi Done 9.企业案例:写网络服务独立进程模式下rsync的系统启动脚本 例如:/etc/init.d/rsyncd{start|stop|restart}。 [root@server ~]# cat 001.sh #!/bin/bash # chkconfig: 2345 3062 #将脚本添加进chkconfig时2345向需设置10-90之间,必须添加这句才能将该脚本添加进chkconfig pidfile=/var/run/rsyncd.pid judge(){ result=$? if [ $result = 0 ];then action "rsync is $1" /bin/true action "rsync is $1" /bin/false } start() { if [ -f $pidfile ];then echo "rsync is running" rsync --daemon judge started stop(){ if [ ! -f $pidfile ];then echo "rsync is stopping" kill `cat $pidfile` rm -f $pidfile judge stopd case "$1" in start) start ;; stop) stop restart) sleep 2 *) echo "usage:$0 {start|stop|restart}" exit 1 esac 注:添加进chkconfig 设置开机自启动 cp 001.sh /etc/init.d/rsyncd # chkconfig: 2345 10 90#将脚本添加进chkconfig时2345向需设置10-90之间 [root@server init.d]# ll /etc/rc.d/rc3.d/|grep 30#30没被使用 [root@server init.d]# ll /etc/rc.d/rc3.d/|grep 61#62没被使用 [root@server init.d]# chkconfig --add rsyncd [root@server init.d]# chkconfig --list|grep rsync rsyncd 0:off1:off2:on3:on4:on5:on6:off
10.好消息,老男孩培训学生外出企业项目实践机会(第6次)来了(本月中旬),但是,名额有限,队员限3人(班长带队)。 因此需要挑选学生,因此需要一个抓阄的程序: 要求: 1、执行脚本后,想去的同学输入英文名字全拼,产生随机数01-99之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能在出现相同数字。 2、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。 [root@server ~]# cat 002.sh #!/bin/bash file=/tmp/file.txt [ -f $file ]|| touch $file read -p "please input your English name:" name rename=$(grep "b$nameb" $file|wc -l) if [ -z $name ];then echo "Please do not enter empty characters" elif [ $rename -eq 1 ];then echo "The user already exists" ran_num=$(expr $RANDOM % 99 + 1) zhua_num=$(grep "b${ran_num}b" $file|wc -l) if [ $zhua_num -ne 1 ];then echo "$name $ran_num"|tee -a $file flag=1 [ $flag -eq 1 ] && break 已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果,请破解这些字符串对应的md5sum前的对应数字? 21029299 00205d1c a3da1677 1f6d12dd [root@www ~]# cat 003.sh array=( 21029299 00205d1c a3da1677 1f6d12dd ) for i in {0..32767} md5=$(echo $i|md5sum |cut -c 1-8) for n in ${array[*]} if [ $md5 == $n ];then echo "$i is $n"
11:用shell处理以下内容 1、按单词出现频率降序排序! 2、按字母出现频率降序排序! [root@www ~]# cat file.txt the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation 1、按单词出现频率降序排序! [root@www ~]# cat file.txt |tr "[.,]" " "|sed "s# #n#g"|grep -v "^$"|sort|uniq -c|sort -rn [root@www ~]# cat file.txt |sed "s#[.,]#n#g"|grep -v "^$"|sort |uniq -c|sort -rn 2、按字母出现频率降序排序! [root@www ~]# cat file.txt |tr "[,.]" " "|sed "s# ##g"|sed -r "s#(.)#1n#g"|sort|uniq -c|sort -rn 12.面试及实战考试题:监控web站点目录(/var/html/www)下所有文件是否被恶意篡改(文件内容被改了),如果有就打印改动的文件名(发邮件),定时任务每3分钟执行一次(10分钟时间完成)。 解决方案:如果是正常的代码上线,则暂时不监控,正常代码上线之后先执行001.sh建立指纹库和记录文件数目,再继续监控执行002.sh [root@web01 shell]# cat 001.sh path=/var/html/www/ [ -d /test ]|| mkdir /test -p md5_log=/test/md5_old.log num_log=/test/num_old.log find "$path" -type f -exec md5sum {} >$md5_log ; find "$path" -type f > $num_log [root@web01 shell]# cat 002.sh path=/var/html/www#检测站点路径 num=$(cat $num_log|wc -l) resultlog=/test/result.log [ ! -f $resultlog ] && touch $resultlog md5_check=$(md5sum -c $md5_log 2>/dev/null |grep FAILED|wc -l) new_num=$(find $path -type f|wc -l) find $path -type f >/test/num_new.log if [ $md5_check -ne 0 ]||[ $new_num -ne $num ];then echo "$(md5sum -c $md5_log 2>/dev/null | grep FAILED)" >$resultlog diff $num_log /test/num_new.log >>$resultlog # mail -s "web site is changed in $(date +%F %T)" 15683988767@163.com <$resultlog sleep 3 [root@web01 test]# ll /test/ total 16 -rw-r--r--. 1 root root 597 Jul 15 23:20 md5_old.log -rw-r--r--. 1 root root 223 Jul 15 23:24 num_new.log -rw-r--r--. 1 root root 223 Jul 15 23:20 num_old.log -rw-r--r--. 1 root root 29 Jul 15 23:24 result.log 13.请用shell或Python编写一个等腰三角形(oldboy2_triangle.sh),接收用户输入的数字。 例如: [root@web01 shell]# sh 004.sh pleash enter a number:6 * *** ***** ******* ********* *********** [root@web01 shell]# cat 004.sh read -p "pleash enter a number:" n for ((i=1;i<=$n;i++)) for((j=(($n-$i));j>0;j--)) echo -n " " for((m=0;m<$((2*$i-1));m++)) echo -n "*" echo [root@web01 shell]# sh 005.sh 2 6 * * * * * * * * * * * * * * * * * * * * [root@web01 shell]# cat 005.sh for ((n=$1;n<=$2;n++)) for ((m=1;m<$n;m++)) echo -n "* " if [ $m -eq $n ];then echo "* "
14.打印选择菜单,一键安装Web服务: [root@oldboyscripts]# sh menu.sh 1.[install lamp] 2.[install lnmp] 3.[exit] pls input the num you want: 、当用户输入时,输出“startinstalling lamp.”然后执行/server/scripts/lamp.sh,脚本内容输出"lampis installed"后退出脚本; 2startinstalling lnmp./server/scripts/lnmp.sh输出"lnmpis installed"后退出脚本; 3、当输入时,退出当前菜单及脚本; 4、当输入任何其它字符,给出提示“Input error”后退出脚本。 5、要对执行的脚本进行相关条件判断,例如:脚本是否存在,是否可执行等。 [root@web01 shell]# cat 006.sh lnmp=/server/scripts/lnmp.sh lamp=/server/scripts/lamp.sh echo "1.[install lamp]" echo "2.[install lnmp]" echo "3.[exit]" read -p "please input num:" num case $num in 1) [ -f $lamp -a -x $lamp ]||{ echo "$lamp is error!" echo "startinstalling lamp..." $lamp echo "lamp installed..." ;; 2) [ -f $lnmp -a -x $lnmp ]||{ echo "$lnmp is error!" echo "startinstalling lnmp..." $lnmp echo "lnmp installed..." 3) *) echo "input error" Esac 15.对MySQL数据库进行分库加分表备份,请用脚本实现 [root@mysql-01 ~]# cat 001.sh USER=root PASS=oldboy SOCK=/data/3306/mysql.sock LOGIN="mysql -u$USER -p$PASS -S $SOCK" DUMP="mysqldump -u$USER -poldboy -S $SOCK" DATABASE=$($LOGIN -e "show databases;"|sed 1d|grep -Ev "*_schema|mysql") for database in $DATABASE TABLES=$($LOGIN -e "use $database;show tables;"|sed 1d) for tables in $TABLES [ -d /opt/$database ]||mkdir -p /opt/$database $DUMP $database $TABLES |gzip > /opt/$database/${database}_${tables}_$(date +%F).sql.gz 16.对mysql实现分库备份 [root@mysql-01 ~]# cat 002.sh $DUMP $database -B |gzip > /opt/${database}_${tables}_$(date +%F).sql.gz done
17.开发mysql多实例启动脚本:已知mysql多实例启动命令为:mysqld_safe--defaults-file=/data/3306/my.cnf &停止命令为:mysqladmin -u root -poldboy123 -S /data/3306/mysql.sockshutdown请完成mysql多实例启动启动脚本的编写要求:用函数,case语句、if语句等实现。
[root@mysql-01 3306]# vim mysql #!/bin/sh #init port=3306 mysql_user="root" mysql_pwd="oldboy" CmdPath="/application/mysql/bin" mysql_sock="/data/${port}/mysql.sock" #startup function function_start_mysql() { if [ ! -e "$mysql_sock" ];then printf "Starting MySQL...n" /bin/sh ${CmdPath}/mysqld_safe --defaults-file=/data/${port}/my.cnf 2>&1 > /dev/null & printf "MySQL is running...n" exit #stop function function_stop_mysql() printf "MySQL is stopped...n" printf "Stoping MySQL...n" ${CmdPath}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S /data/${port}/mysql.sock shutdown #restart function function_restart_mysql() printf "Restarting MySQL...n" function_stop_mysql sleep 2 function_start_mysql case $1 in start) stop) restart) function_restart_mysql printf "Usage: /data/${port}/mysql {start|stop|restart}n" esac
18.企业面试题1:(生产实战案例):监控MySQL主从同步是否异常,如果异常,则发送短信或者邮件给管理员。提示:如果没主从同步环境,可以用下面文本放到文件里读取来模拟: [root@oldboy C13]# cat 13_6_3.sh ########################################### # this script function is : # check_mysql_slave_replication_status ############################################ path=/server/scripts MAIL_GROUP="1111@qq.com 2222@qq.com" PAGER_GROUP="18600338340 18911718229" LOG_FILE="/tmp/web_check.log" PASSWORD=oldboy123 PORT=3307 MYSQLCMD="mysql -u$USER -p$PASSWORD -S /data/$PORT/mysql.sock" error=(1008 1007 1062) RETVAL=0 [ ! -d $path ] && mkdir -p $path function JudgeError(){ for((i=0;i<${#error[*]};i++)) if [ "$1" == "${error[$i]}" ] echo "MySQL slave errorno is $1,auto repairing it." $MYSQLCMD -e "stop slave;set global sql_slave_skip_counter=1;start slave;" return $1 function CheckDb(){ status=($(awk -F ': ' '/_Running|Last_Errno|_Behind/{print $NF}' slave.log)) expr ${status[3]} + 1 &>/dev/null status[3]=300 if [ "${status[0]}" == "Yes" -a "${status[1]}" == "Yes" -a ${status[3]} -lt 120 ] #echo "Mysql slave status is ok" return 0 #echo "mysql replcation is failed" JudgeError ${status[2]} function MAIL(){ local SUBJECT_CONTENT=$1 for MAIL_USER in `echo $MAIL_GROUP` mail -s "$SUBJECT_CONTENT " $MAIL_USER <$LOG_FILE function PAGER(){ for PAGER_USER in `echo $PAGER_GROUP` TITLE=$1 CONTACT=$PAGER_USER HTTPGW=http://oldboy.sms.cn/smsproxy/sendsms.action #send_message method1 curl -d cdkey=5ADF-EFA -d password=OLDBOY -d phone=$CONTACT -d message="$TITLE[$2]" $HTTPGW function SendMsg(){ if [ $1 -ne 0 ] then RETVAL=1 NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"` SUBJECT_CONTENT="mysql slave is error,errorno is $2,${NOW_TIME}." echo -e "$SUBJECT_CONTENT"|tee $LOG_FILE MAIL $SUBJECT_CONTENT PAGER $SUBJECT_CONTENT $NOW_TIME echo "Mysql slave status is ok" return $RETVAL function main(){ CheckDb SendMsg $? sleep 300
19.将域名取出,并根据域名进行计数排序处理。 [root@fengxiaoli ~]# cat yuming.txt http://a.example.com/1.html http://b.example.com/1.html http://c.example.com/1.html http://a.example.com/2.html http://b.example.com/2.html http://a.example.com/3.html [root@fengxiaoli ~]# cat yuming.txt |awk -F "/" '{print $3}'|sort|uniq -c 3 a.example.com 2 b.example.com 1 c.example.com [root@fengxiaoli ~]# cat yuming.txt|awk -F / '{S[$3]++}END{for(k in S)print k,S[k]}'|sort a.example.com 3 b.example.com 2 c.example.com 1 [root@fengxiaoli ~]# cat yuming.txt|awk -F / '{++S[$3]}END{for(k in S)print k,255);">c.example.com 1 20.统计服务器上连接状态数量 [root@fengxiaoli ~]# netstat -n |awk '/^tcp/ {print $NF}' |sort |uniq -c|sort [root@fengxiaoli ~]# netstat -n |awk '/^tcp/ {++S[$NF]} END {for(k in S) print k,S[k]}' TIME_WAIT 9137 CLOSE_WAIT 207 FIN_WAIT1 547 ESTABLISHED 597 FIN_WAIT2 74 SYN_RECV 70 CLOSING 55 LAST_ACK 8 21.分析图片服务日志,把日志(每个图片访问次数*图片大小的总和)排行,取top10,也就是计算每个url的总访问大小 说明:这个功能可以用于IDC及CDN网站流量带宽很高,然后通过分析服务器日志哪些元素占用流量过大,进而进行优化裁剪该图片,压缩js等措施。 本题需要输出三个指标: 【访问次数】 【访问次数*单个文件大小】 【文件名(可以带URL)】 [root@fengxiaoli ~]# cat fs.txt 59.33.26.105 - - [08/Dec/2010:15:43:56 +0800] "GET /static/images/photos/2.jpg HTTP/1.1" 200 11299 "http://oldboy.blog.51cto.com/static/web/column/17/index.shtml?courseId=43" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)" 59.33.26.105 - - [08/Dec/2010:15:44:02 +0800] "GET /static/flex/vedioLoading.swf HTTP/1.1" 200 3583 "http://oldboy.blog.51cto.com/static/flex/AdobeVideoPlayer.swf?width=590&height=328&url=/[[DYNAMIC]]/2" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)" 124.115.4.18 - - [08/Dec/2010:15:44:15 +0800] "GET /?= HTTP/1.1" 200 46232 "-" "-" 124.115.4.18 - - [08/Dec/2010:15:44:25 +0800] "GET /static/js/web_js.js HTTP/1.1" 200 4460 "-" "-" 124.115.4.18 - - [08/Dec/2010:15:44:25 +0800] "GET /static/js/jquery.lazyload.js HTTP/1.1" 200 1627 "-" "-" [root@fengxiaoli ~]# awk '{print $7"t" $10}' fs.txt |sort |uniq -c|awk '{print $1*$3,$1,$2}'|sort -rn|head 46232 1 /?= 22598 2 /static/images/photos/2.jpg 4460 1 /static/js/web_js.js 3583 1 /static/flex/vedioLoading.swf 1627 1 /static/js/jquery.lazyload.js 通过两个数组来计算 因为我们要的最终结果是某个文件的访问次数和消耗的流量,所以考虑建立以文件名为索引的两个数组,一个存储访问次数,一个保存消耗的流量,这样当使用awk按行遍历文件时,对次数数组+1,同时对流量数组进行文件大小的累加,等文件扫描完成,再遍历输出两个数组既可以得到该文件的反问次数和总的流量消耗。 [root@fengxiaoli ~]# awk '{array_num[$7]++;array_size[$7]+=$10}END{for(x in array_num) print array_size[x],array_num[x],x}' fs.txt |sort -rn -k1 |head -10 1627 1 /static/js/jquery.lazyload.js (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |