本文用於記錄學習和平常中使用過的shell腳本php

【腳本1】打印形狀

打印等腰三角形、直角三角形、倒直角三角形、菱形css

#!/bin/bash # 等腰三角形 read -p "Please input the length: " n for i in `seq 1 $n` do for ((j=$n;j>i;j--)) do echo -n " " done for m in `seq 1 $i` do echo -n "* " done echo done # 倒直角三角形 read -p "Please input the length: " len for i in `seq 1 $len` do for j in `seq $i $len` do echo -n "* " done echo done # 直角三角形 read -p "Please input the length: " len for i in `seq 1 $len` do for((j=1;j<=$i;j++)) do echo -n "* " done echo done # 菱形 read -p "Please input the length: " n for i in `seq 1 $n` do for ((j=$n;j>i;j--)) do echo -n " " done for m in `seq 1 $i` do echo -n "* " done echo done for i in `seq 1 $n` do for((j=1;j<=$i;j++)) do echo -n " " done for((k=$i;k<=$len-1;k++)) do echo -n "* " done echo done

【腳本2】截取字符串

現有一個字符串以下:html

http://www.aaa.com/root/123.htm前端

請根據如下要求截取出字符串中的字符:java

1.取出www.aaa.com/root/123.htmnode

2.取出123.htmpython

3.取出http://www.aaa.com/rootmysql

4.取出http:linux

5.取出http://ios

6.取出www.aaa.com/root/123.htm

7.取出123

8.取出123.htm

#!/bin/bash var="http://www.aaa.com/root/123.htm" #1. echo $var |awk -F '//' '{print $2}' #2. echo $var |awk -F '/' '{print $5}' #3. echo $var |grep -o 'http.*root' #4. echo $var |awk -F '/' '{print $1}' #5. echo $var |grep -o 'http://' #6. echo $var |grep -o 'www.*htm' #7. echo $var |grep -o '123' #8. echo $var |grep -o '123.htm'

【腳本3】tomcat啓動腳本

emm。。這個腳本是由於tomcat沒有自帶的可以給service開機啓動的腳本,我就琢磨着本身寫了一個簡單的啓動腳本,以下:

#!/bin/bash # chkconfig:2345 64 36 # description: Tomcat start/stop/restart script. ### BEGIN INIT INFO # Provides: tomcat # Required-Start: # Should-Start: # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop Tomcat # Description: Tomcat Service start&restart&stop script ### END INIT INFO ##Written by zero.## JAVA_HOME=/usr/local/jdk1.8/ JAVA_BIN=/usr/local/jdk1.8/bin JRE_HOME=/usr/local/jdk1.8/jre PATH=$PATH:/usr/local/jdk1.8/bin:/usr/local/jdk1.8/jre/bin CLASSPATH=/usr/local/jdk1.8/jre/lib:/usr/local/jdk1.8/lib:/usr/local/jdk1.8/jre/lib/charsets.jar TOMCAT_BIN=/usr/local/tomcat/bin RETVAL=0 prog="Tomcat" start() { echo "Starting $prog......" /bin/bash $TOMCAT_BIN/startup.sh RETVAL=$? return $RETVAL } stop() { echo "Stopping $prog......" /bin/bash $TOMCAT_BIN/shutdown.sh RETVAL=$? return $RETVAL } restart(){ echo "Restarting $prog......" stop start } case "$1" in start) start ;; stop) stop ;; restart) restart ;; *) echo $"Usage: $0 {start|stop|restart}" RETVAL=1 esac exit $RETVAL

【腳本4】自定義rm命令

linux系統的rm命令太危險,一不當心就會刪除掉系統文件。 寫一個shell腳原本替換系統的rm命令,要求當刪除一個文件或者目錄時,都要作一個備份,而後再刪除。下面分兩種狀況,作練習:

1. 簡單的實現:

假設有一個大的分區/data/,每次刪除文件或者目錄以前,都要先在/data/下面建立一個隱藏目錄,以日期/時間命名,好比/data/.201703271012/,而後把全部刪除的文件同步到該目錄下面,可使用rsync -R 把文件路徑一同同步,示例:

#!/bin/bash fileName=$1 now=`date +%Y%m%d%H%M` read -p "Are you sure delete the file or directory $1? yes|no: " input if [ $input == "yes" ] || [ $input == "y" ] then mkdir /data/.$now rsync -aR $1/ /data/.$now/$1/ /bin/rm -rf $1 elif [ $input == "no" ] || [ $input == "n" ] then exit 0 else echo "Only input yes or no" exit fi

2.複雜的實現:

不知道哪一個分區有剩餘空間,在刪除以前先計算要刪除的文件或者目錄大小,而後對比系統的磁盤空間,若是夠則按照上面的規則建立隱藏目錄,並備份,若是沒有足夠空間,要提醒用戶沒有足夠的空間備份並提示是否放棄備份,若是用戶輸入yes,則直接刪除文件或者目錄,若是輸入no,則提示未刪除,而後退出腳本,示例:

#!/bin/bash fileName=$1 now=`date +%Y%m%d%H%M` f_size=`du -sk $1 |awk '{print $1}'` disk_size=`LANG=en; df -k |grep -vi filesystem |awk '{print $4}' |sort -n |tail -n1` big_filesystem=`LANG=en; df -k |grep -vi filesystem |sort -n -k4 |tail -n1 |awk '{print $NF}'` if [ $f_size -lt $disk_size ] then read -p "Are you sure delete the file or directory: $1 ? yes|no: " input if [ $input == "yes" ] || [ $input == "y" ] then mkdir -p $big_filesystem/.$now && rsync -aR $1 $big_filesystem/.$now/ && /bin/rm -rf $1 elif [ $input == "no" ] || [ $input == "n" ] then exit 0 else echo "Only input 'yes' or 'no'." fi else echo "The disk size is not enough to backup the file: $1." read -p "Do you want to delete "$1"? yes|no: " input if [ $input == "yes" ] || [ $input == "y" ] then echo "It will delete "$1" after 5 seconds whitout backup." for i in `seq 1 5`; do echo -ne "."; sleep 1; done echo /bin/rm -rf $1 elif [ $input == "no" ] || [ $input == "n" ] then echo "It will not delete $1." exit 0 else echo "Only input 'yes' or 'no'." fi fi

【腳本5】數字求和

編寫shell腳本,要求輸入一個數字,而後計算出從1到輸入數字的和,要求,若是輸入的數字小於1,則從新輸入,直到輸入正確的數字爲止,示例:

#!/bin/bash while : do read -p "Please enter a positive integer: " n if [ $n -lt 1 ] then echo "It can't be less than 1" else break fi done num=1 for i in `seq 2 $n` do num=$[$num+$i] done echo $num

【腳本6】拷貝目錄

編寫shell腳本,把/root/目錄下的全部目錄(只須要一級)拷貝到/tmp/目錄下:

#!/bin/bash cd /root/ list=(`ls`) for i in ${list[@]} do if [ -d $i ] then cp -r $i /tmp/ fi done

【腳本7】批量創建用戶

編寫shell腳本,批量創建用戶user_00, user_01, ... user_100而且全部用戶同屬於users組:

#!/bin/bash group=`cat /etc/group |grep -o users` if [ $group == "users" ] then for i in `seq 0 100` do if [ $i -lt 10 ] then useradd -g users user_0$i else useradd -g users user_$i fi done else echo "users group not found!" exit 1 fi

刪除以上腳本批量添加的用戶:

#!/bin/bash for i in `seq 0 100` do if [ $i -lt 10 ] then userdel -r user_0$i else userdel -r user_$i fi done

【腳本8】每日生成一個文件

要求:請按照這樣的日期格式(xxxx-xx-xx)每日生成一個文件,例現在天生成的文件爲)2017-07-05.log, 而且把磁盤的使用狀況寫到到這個文件中,(不用考慮cron,僅僅寫腳本便可)

#!/bin/bash fileName=`date +%F` c=`df -h` echo "$c" > /root/$fileName.log

【腳本9】統計ip

有一個日誌文件,日誌片斷:以下:

112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com 「/seccode.php?update=0.5593110133088248″ 200″http://formula-x.haotui.com/registerbbs.php」 「Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)」
61.147.76.51 – [25/Sep/2013:16:08:31 +0800]xyzdiy.5d6d.com 「/attachment.php?aid=4554&k=9ce51e2c376bc861603c7689d97c04a1&t=1334564048&fid=9&sid=zgohwYoLZq2qPW233ZIRsJiUeu22XqE8f49jY9mouRSoE71″ 301″http://xyzdiy.×××thread-1435-1-23.html」 「Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)」

要求: 統計出每一個IP的訪問量有多少?

awk '{print $1}' 1.log |sort -n |uniq -c |sort -n

解釋:sort -n會按照數值而不是ASCII碼來排序awk截取出來的IP。而後uniq命令用於報告或忽略文件中的重複行,加上-c選項後會在每列旁邊顯示該行重複出現的次數,在這一步就完成了統計。不過最後還得再讓sort -n排序一下uniq -c統計出來的結果。


【腳本10】統計內存使用

寫一個腳本計算一下linux系統全部進程佔用內存大小的和。

實現代碼:

#!/bin/bash count=0 # 這個循環會遍歷出每一個進程佔用的內存大小 for i in `ps aux |awk '{print $6}' |grep -v 'RSS'` do # 將遍歷出來的數字進行累加 count=$[$count+$i] done # 就獲得全部進程佔用內存大小的和了 echo "$count/kb"

也可使用awk 一條命令計算:

ps aux |grep -v 'RSS TTY' |awk '{sum=sum+$6};END{print sum}'

解釋:grep -v是忽略 'RSS TTY' 所存在的那一行,後面的awk聲明瞭一個變量sum,sum將前面命令列出來的數字進行累加,END以後就將累加後的sum打印出來,就獲得全部進程佔用內存大小的和了。


【腳本11】簡單的監控腳本

設計一個簡單的腳本,監控遠程的一臺機器(假設ip爲123.23.11.21)的存活狀態,當發現宕機時發一封郵件給你本身。

#!/bin/bash ip="123.23.11.21" email="user@example" while 1 do ping -c10 $ip > /dev/null 2>/dev/null if [ $? != "0" ] then # 調用一個用於發郵件的腳本 python /usr/local/sbin/mail.py $email "$ip down" "$ip is down" fi sleep 30 done

mail.py 腳本代碼:

#!/usr/bin/env python #-*- coding: UTF-8 -*- import os,sys reload(sys) sys.setdefaultencoding('utf8') import getopt import smtplib from email.MIMEText import MIMEText from email.MIMEMultipart import MIMEMultipart from subprocess import * def sendqqmail(username,password,mailfrom,mailto,subject,content): # 郵箱的服務地址 gserver = 'smtp.qq.com' gport = 25 try: msg = MIMEText(unicode(content).encode('utf-8')) msg['from'] = mailfrom msg['to'] = mailto msg['Reply-To'] = mailfrom msg['Subject'] = subject smtp = smtplib.SMTP(gserver, gport) smtp.set_debuglevel(0) smtp.ehlo() smtp.login(username,password) smtp.sendmail(mailfrom, mailto, msg.as_string()) smtp.close() except Exception,err: print "Send mail failed. Error: %s" % err def main(): to=sys.argv[1] subject=sys.argv[2] content=sys.argv[3] #定義QQ郵箱的帳號和密碼,你須要修改爲你本身的帳號和密碼 sendqqmail('1234567@qq.com','aaaaaaaaaa','1234567@qq.com',to,subject,content) if __name__ == "__main__": main() #####腳本使用說明###### #1. 首先定義好腳本中的郵箱帳號和密碼 #2. 腳本執行命令爲:python mail.py 目標郵箱 "郵件主題" "郵件內容"

【腳本12】批量更改文件名

需求:

  • 找到/123目錄下全部後綴名爲.txt的文件
  • 批量修改.txt爲.txt.bak
  • 把全部.bak文件打包壓縮爲123.tar.gz
  • 批量還原文件的名字,即把增長的.bak再刪除

代碼:

#!/bin/bash now=`date +%F_%T` mkdir /tmp/123_$now for txt in `ls /123/*.txt` do mv $txt $txt.bak for f in $txt do cp $txt.bak /tmp/123_$now done done cd /tmp/ tar czf 123.tar.gz 123_$now/ for txt in `ls /123/*.txt.bak` do name=`echo $txt |awk -F '.' '{OFS="."} {print $1,$2}'` mv $txt $name done

【腳本13】監控80端口

需求:
寫一個腳本,判斷本機的80端口(假如服務爲httpd)是否開啓着,若是開啓着什麼都不作,若是發現端口不存在,那麼重啓一下httpd服務,併發郵件通知你本身。腳本寫好後,能夠每一分鐘執行一次,也能夠寫一個死循環的腳本,30s檢測一次。
發郵件的腳本參考【腳本11】的示例代碼。
代碼:

#!/bin/bash email="user@example.com" if netstat -lntp |grep ':80' |grep 'httpd' then echo "80 port no problem" exit else /usr/local/apache2.4/bin/apachectl restart python mail.py $email "check_80port" "The 80 port is down." n=`ps aux |grep httpd|grep -cv grep` if [ $n -eq 0 ] then /usr/local/apache2/bin/apachectl start 2>/tmp/apache_start.err fi if [ -s /tmp/apache_start.err ] then python mail.py $mail 'apache_start_error' `cat /tmp/apache_start.err` fi fi

【腳本14】備份數據庫

需求:

設計一個shell腳原本備份數據庫,首先在本地服務器上保存一份數據,而後再遠程拷貝一份,本地保存一週的數據,遠程保存一個月。

假定,咱們知道mysql root帳號的密碼,要備份的庫爲discuz,本地備份目錄爲/bak/mysql, 遠程服務器ip爲192.168.123.30,遠程提供了一個rsync服務,備份的地址是 192.168.123.30::backup . 寫完腳本後,須要加入到cron中,天天凌晨3點執行。
腳本代碼:

#!/bin/bash PATH=$PATHi:/usr/local/mysql/bin week=`date +%w` today=`date +d` passwd="123456" backdir="/data/mysql" r_backupIP="192.168.123.30::backup" exec 1>/var/log/mysqlbak.log 2>/var/log/mysqlbak.log echo "mysql backup begin at `date +%F %T`." # 本地備份 mysqldump -uroot -p$passwd --default-character-set=utf8 discuz >$backdir/$week.sql # 同步備份到遠程機器 rsync -az $backdir/$week.sql $r_backupIP/$today.sql echo "mysql backup end at `date +%F %T`."

而後加入cron
0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh


【腳本15】自動重啓php-fpm服務

服務器上跑的是LNMP環境,近期老是有502現象。502爲網站訪問的狀態碼,200正常,502錯誤是nginx最爲普通的錯誤狀態碼。因爲502只是暫時的,而且只要一重啓php-fpm服務則502消失,但不重啓的話,則會一直持續很長時間。因此有必要寫一個監控腳本,監控訪問日誌的狀態碼,一旦發生502,則自動重啓一下php-fpm。

咱們設定:

  1. access_log /data/log/access.log
  2. 腳本死循環,每10s檢測一次(假設每10s鐘的日誌條數爲300左右)
  3. 重啓php-fpm的方法是 /etc/init.d/php-fpm restart

腳本代碼:

#!/bin/bash access_log="/data/log/access.log" N=10 while : do # 由於10秒大概產生300條日誌記錄 tail -n300 $access_log > /tmp/log # 拿出log中包含502的日誌行數 n_502=`grep -c "502" /tmp/log` # 若是行數大於10 if [ $n_502 -ge $N ] then # 就記錄一下系統狀態 top -bn1 > /tmp/`date +%H%M%S`-top.log vmstat 1 5 > /tmp/`date +%H%M%S`-vm.log # 而後才重啓服務,並把錯誤信息重定向 /etc/init.d/php-fpm restart 2> /dev/null # 重啓php-fpm服務後,應先暫緩1分鐘,然後繼續每隔10s檢測一次 sleep(60) fi sleep(10) done

【腳本16】文本替換

將memcached裏的數據導出到文件中,而後再導入memcached裏卻發現數據過時了,這是由於導出的數據是帶有一個時間戳的,這個時間戳就是該條數據過時的時間點,若是當前時間已經超過該時間戳,那麼是導入不進去的。不過能夠修改文件中的時間戳來保證導入時數據的有效期。能夠寫一個簡單的腳本批量替換這些文件中的時間戳:

#!/bin/bash hour=`date -d "+1 hour" +%s` # 一個小時以後的時間戳 data_time=`cat data.txt |grep add |awk '{print $4}' |sort -n |uniq` for i in $data_time do sed -i "s/$i/$hour/g" `grep $i -rl /root/data.txt` done

【腳本17】啓動容器

docker每次關閉都會連帶着將運行中的容器關閉,因此每次啓動docker後都須要逐個去啓動容器,很麻煩,因爲是實驗用的虛擬機不是線上的機器,因此就直接寫了一個很簡單的循環來啓動容器:

#!/bin/bash /usr/bin/systemctl start docker for i in `docker ps -a |grep 'Exited' |awk '{print $1}'` do /usr/bin/docker start $i done

【腳本18】刪除文本中的字母

要求:把一個文本文檔的前5行中包含字母的行刪除掉,同時把6到10行中的所有字母刪除掉。

參考答案:假設文本名字叫作1.txt,而且文本行數大於10,腳本以下:

#!/bin/bash ## 先獲取該文本的行數 rows=`wc -l 1.txt |awk '{print $1}'` ## 對前5行進行處理 for i in `seq 1 5` do ## 使用sed把每一行的內容賦值給變量 row=`sed -n "$i"p 1.txt` ## 用grep 斷定是否匹配字母,-v取反,-q不輸出內容 if echo $row |grep -vq '[a-zA-Z]' then echo $row fi done ## 對6-10行作刪除字母處理 for i in `seq 6 10` do row=`sed -n "$i"p 1.txt` echo $row |sed 's/[a-zA-Z]//g' done ## 剩餘的直接輸出 for i in `seq 11 $rows` do sed -n "$i"p 1.txt done ##若想把更改內容寫入到1.txt,還須要把以上內容重定向到一個文本中,而後刪除1.txt,再把剛剛重定向的文件改名爲1.txt

【腳本19】查找字母數小於6的單詞

用shell打印下面這句話中字母數小於6的單詞。
Bash also interprets a number of multi-character options.

腳本以下:

#!/bin/bash for s in Bash also interprets a number of multi-character options do n=`echo $s |wc -c` if [ $n -lt 6 ] then echo $s fi done

【腳本20】輸入數字執行對應命令

寫一個腳本實現以下功能: 輸入一個數字,而後運行對應的一個命令。顯示命令以下:

*cmd meau** 1—date 2–ls 3–who 4–pwd

當輸入1時,會運行date, 輸入2時運行ls, 依此類推。

實現腳本以下:

#!/bin/bash echo "*cmd meau** 1—date 2–ls 3–who 4–pwd" read -p "please input a number 1-4: " n case $n in 1) date ;; 2) ls ;; 3) who ;; 4) pwd ;; *) echo "Please input a number: 1-4" ;; esac

【腳本21】批量建立用戶並設置密碼

用shell腳本實現以下需求:
添加user_00 – user_09 10個用戶,而且給他們設置一個隨機密碼,密碼要求10位包含大小寫字母以及數字,注意須要把每一個用戶的密碼記錄到一個日誌文件裏。

提示:

  1. 隨機密碼使用命令 mkpasswd
  2. 在腳本中給用戶設置密碼,可使用echo 而後管道passwd命令

實現腳本以下:

#!/bin/bash for i in `seq 00 09` do useradd user_$i p=`mkpasswd -s 0 -l 10` echo "user_$i $p" >> /tmp/user0_9.pw echo $p |passwd -stdin user_$i done

【腳本22】監控httpd進程

在服務器上,寫一個監控腳本。

  1. 每隔10s去檢測一次服務器上的httpd進程數,若是大於等於500的時候,就須要自動重啓一下apache服務,並檢測啓動是否成功?
  2. 若沒有正常啓動還需再一次啓動,最大不成功數超過5次則須要理解發郵件通知管理員,而且之後不須要再檢測!
  3. 若是啓動成功後,1分鐘後再次檢測httpd進程數,若正常則重複以前操做(每隔10s檢測一次),若仍是大於等於500,那放棄重啓並須要發郵件給管理員,而後自動退出該腳本。假設其中發郵件腳本爲mail.py

實現腳本以下:

#!/bin/bash check_service(){ n=0 for i in `seq 1 5` do # apachectl命令所在路徑 /usr/local/apache2/bin/apachectl restart 2> /tmp/apache.err if [$? -ne 0 ] then n=$[$n-1] else break fi done if [ $n -eq 5 ] then ## mail.py的內容參考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py python mail.py "123@qq.com" "httpd service down" `cat /tmp/apache.err` exit fi } while : do t_n=`ps -C httpd --no-heading |wc -l` if [ $t_n -ge 500 ] then /usr/local/apache2/bin/apachectl restart if [ $? -ne 0 ] then check_service fi sleep 60 t_n=`ps -C httpd --no-heading |wc -l` if [ $t_n -ge 500] then python mail.py "123@qq.com" "httpd service somth wrong" "the httpd process is budy." exit fi fi sleep 10 done

【腳本23】封ip

需求: 根據web服務器上的訪問日誌,把一些請求量很是高的ip給拒絕掉!

分析: 咱們要作的,不只是要找到哪些ip請求量不合法,而且還要每隔一段時間把以前封掉的ip(若再也不繼續請求了)給解封。 因此該腳本的關鍵點在於定一個合適的時間段和閾值。

好比, 咱們能夠每一分鐘去查看一下日誌,把上一分鐘的日誌給過濾出來分析,而且只要請求的ip數量超過100次那麼就直接封掉。 而解封的時間又規定爲每半小時分析一次,把幾乎沒有請求量的ip給解封!

參考日誌文件片斷:

157.55.39.107 [20/Mar/2015:00:01:24 +0800] www.aminglinux.com 「/bbs/thread-5622-3-1.html」 200 「-」 「Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)」 61.240.150.37 [20/Mar/2015:00:01:34 +0800] www.aminglinux.com 「/bbs/search.php?mod=forum&srchtxt=LNMP&formhash=8f0c7da9&searchsubmit=true&source=hotsearch」 200 「-」 「Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)」

腳本實現以下:

#!/bin/bash ## 日誌文件路徑 log_file="/home/logs/client/access.log" ## 當前時間減一分鐘的時間 d1=`date -d "-1 minute" +%H:%M` ## 當前時間的分鐘段 d2=`date +%M` ## iptables命令所在的路徑 ipt="/sbin/iptables" ## 用於存儲訪問日誌裏的ip ips="/tmp/ips.txt" ## 封ip block(){ ## 把日誌文件中的ip過濾出來,去掉重複的ip,並統計ip的重複次數以及對ip進行排序,最後將結果寫到一個文件中 grep "$d1:" $log_file |awk '{print $1}' |sort -n |uniq -c |sort -n > $ips ## 將文件裏重複次數大於100的ip迭代出來 for ip in `awk '$1 > 100 {print $2}' $ips` do ## 經過防火牆規則對這些ip進行封禁 $ipt -I INPUT -p -tcp --dport 80 -s $ip -j REJECT ## 將已經封禁的ip輸出到一個文件裏存儲 echo "`date +%F-%T` $ip" >> /tmp/badip.txt done } ## 解封ip unblock(){ ## 將流量小於15的規則索引過濾出來 for i in `$ipt -nvL --line-number |grep '0.0.0.0/0' |awk '$2 < 15 {print $1}' |sort -nr` do ## 經過索引來刪除規則 $ipt -D INPUT $i done ## 清空規則中的數據包計算器和字節計數器 $ipt -Z } ## 爲整點或30分鐘就是過了半個小時,就須要再進行分析 if [ $d2 == "00" ] || [ $d2 == "30" ] then unblock block else block fi

【腳本24】部署前端項目

最近作了一個web前端的項目,須要編寫一個腳本完成項目的上線。

腳本實現以下:

#!/bin/bash # # 使用方法: # mmall:front_deploy.sh mmall-fe # admin:front_deploy.sh admin-fe # GIT_HOME=/developer/git-repository/ # 從git倉庫拉取下來的源碼的存放路徑 DEST_PATH=/product/frontend/ # 項目打包後的發佈路徑 # cd dir if [ ! -n "$1" ] then echo -e "請輸入要發佈的項目!" exit fi if [ $1 = "mmall-fe" ] then echo -e "===========Enter mall-fe=============" cd $GIT_HOME$1 elif [ $1 = "admin-fe" ] then echo -e "===========Enter mall-fe=============" cd $GIT_HOME$1 else echo -e "輸入的項目名沒有找到!" exit fi # clear git dist echo -e "===========Clear Git Dist=============" rm -rf ./dist # git操做 echo -e "===========git checkout master=============" git checkout master echo -e "===========git pull=============" git pull # npm install echo -e "===========npm install=============" npm install --registry=https://registry.npm.taobao.org # npm run dist echo -e "===========npm run dist=============" npm run dist if [ -d "./dist" ] then # backup dest echo -e "===========dest backup=============" mv $DEST_PATH$1/dist $DEST_PATH$1/dist.bak # copy echo -e "===========copy=============" cp -R ./dist $DEST_PATH$1 # echo result echo -e "===========Deploy Success=============" else echo -e "===========Deploy Error=============" fi

【腳本25】找規律打印數字

請詳細查看以下幾個數字的規律,並使用shell腳本輸出後面的十個數字。

10 31 53 77 105 141 …….

試題解析:
我想大多數人都會去比較這些數字的差值:

10  31  53  77  105  141
21   22   24   28   36

可是這個差值看,並無什麼規律,而咱們再仔細看的時候,發現這個差值的差值是有規律的:

10  31  53  77  105  141
21   22   24   28   36
1      2     4     8

腳本實現:

#! /bin/bash x=21 m=10 echo $m for i in `seq 0 14`; do j=$[2**$i] m=$[$m+$x] echo $m x=$[$x+$j] done

【腳本26】統計普通用戶

寫個shell,看看你的Linux系統中是否有自定義用戶(普通用戶),如果有,一共有幾個?

假設全部普通用戶都是uid大於1000的

腳本實現:

#!/bin/bash n=`awk -F ':' '$3>1000' /etc/passwd|wc -l` if [ $n -gt 0 ] then echo "There are $n common users." else echo "No common users." fi

【腳本27】監控磁盤使用率

寫一個shell腳本,檢測全部磁盤分區使用率和inode使用率並記錄到以當天日期爲命名的日誌文件裏,當發現某個分區容量或者inode使用量大於85%時,發郵件通知你本身。

思路:就是先df -h 而後過濾出已使用的那一列,而後再想辦法過濾出百分比的整數部分,而後和85去比較,同理,inode也是同樣的思路。

實現代碼:

#!/bin/bash ## This script is for record Filesystem Use%,IUse% everyday and send alert mail when % is more than 85%. log=/var/log/disk/`date +%F`.log date +'%F %T' > $log df -h >> $log echo >> $log df -i >> $log for i in `df -h|grep -v 'Use%'|sed 's/%//'|awk '{print $5}'`; do if [ $i -gt 85 ]; then use=`df -h|grep -v 'Use%'|sed 's/%//'|awk '$5=='$i' {print $1,$5}'` echo "$use" >> use fi done if [ -e use ]; then ##這裏可使用我們以前介紹的mail.py發郵件 mail -s "Filesystem Use% check" root@localhost < use rm -rf use fi for j in `df -i|grep -v 'IUse%'|sed 's/%//'|awk '{print $5}'`; do if [ $j -gt 85 ]; then iuse=`df -i|grep -v 'IUse%'|sed 's/%//'|awk '$5=='$j' {print $1,$5}'` echo "$iuse" >> iuse fi done if [ -e iuse ]; then mail -s "Filesystem IUse% check" root@localhost < iuse rm -rf iuse fi

思路:

  1. df -h、df -i 記錄磁盤分區使用率和inode使用率,date +%F 日誌名格式
  2. 取出使用率(第5列)百分比序列,for循環逐一與85比較,大於85則記錄到新文件裏,當for循環結束後,彙總超過85的一併發送郵件(郵箱服務因未搭建,發送本地root帳戶)。

此腳本正確運行前提:

  • 該系統沒有邏輯卷的狀況下使用,由於邏輯卷df -h、df -i 時,使用率百分比是在第4列,而不是第5列。若有邏輯卷,則會漏統計邏輯卷使用狀況。

【腳本28】獲取文件列表

有一臺服務器做爲web應用,有一個目錄(/data/web/attachment)不定時地會被用戶上傳新的文件,可是不知道何時會上傳。因此,須要咱們每5分鐘作一次檢測是否有新文件生成。

請寫一個shell腳本去完成檢測。檢測完成後如果有新文件,還須要將新文件的列表輸出到一個按年、月、日、時、分爲名字的日誌裏。請不要想的太複雜,核心命令只有一個 find /data/web/attachment -mmin -5

思路: 每5分鐘檢測一次,那確定須要有一個計劃任務,每5分鐘去執行一次。腳本檢測的時候,就是使用find命令查找5分鐘內有過更新的文件,如果有更新,那這個命令會輸出東西,不然是沒有輸出的。固,咱們能夠把輸出結果的行數做爲比較對象,看看它是否大於0。

實現代碼:

#!/bin/bash d=`date -d "-5 min" +%Y%m%d%H%M` basedir=/data/web/attachment find $basedir/ -type f -mmin -5 > /tmp/newf.txt n=`wc -l /tmp/newf.txt` if [ $n -gt 0 ]; then /bin/mv /tmp/newf.txt /tmp/$d fi

【腳本29】統計經常使用命令

寫一個shell腳原本看看你使用最多的命令是哪些,列出你最經常使用的命令top10。

思路:咱們要用到一個文件就是.bash_history,而後再去sort、uniq,剩下的就不用我多說了吧。很簡單一個shell。

一條命令便可:
sort /root/.bash_history |uniq -c |sort -nr |head


【腳本30】統計日誌大小

假如咱們須要每小時都去執行你寫的腳本。在腳本中實現這樣的功能,當時間是0點和12點時,須要將目錄/data/log/下的文件所有清空,注意只能清空文件內容而不能刪除文件。而其餘時間只須要統計一下每一個文件的大小,一個文件一行,輸出到一個按日期和時間爲名字的日誌裏。 須要考慮/data/log/目錄下的二級、三級、… 等子目錄裏面的文件。

實現代碼:

#!/bin/bash logdir="/data/log" t=`date +%H` d=`date +%F-%H` [ -d /tmp/log_size ] || mkdir /tmp/log_size for log in `find $logdir -type f` do if [ $t == "0" ] || [ $t == "12" ] then true > $log else du -sh $log >>/tmp/log_size/$d fi done

【腳本31】統計數字並求和

計算文檔a.txt中每一行中出現的數字個數而且要計算一下整個文檔中一共出現了幾個數字。例如a.txt內容以下:

12aa*lkjskdj
alskdflkskdjflkjj

咱們腳本名字爲 ncount.sh, 運行它時:

bash ncount.sh a.txt

輸入結果應該爲:

2
0
sum:2

實現代碼:

#!/bin/bash n=`wc -l a.txt|awk '{print $1}'` sum=0 for i in `seq 1 $n` do line=`sed -n "$i"p a.txt` n_n=`echo -n $line|sed 's/[^0-9]//g'|wc -c` echo line $i number: $n_n sum=$[$sum+$n_n] done echo sum is $sum

【腳本32】檢測文件改動

有兩臺Linux服務器A和B,假如A能夠直接ssh到B,不用輸入密碼。A和B都有一個目錄叫作/data/web/ 這下面有不少文件,固然咱們不知道具體有幾層子目錄,倘若以前A和B上該目錄下的文件都是如出一轍的。但如今不肯定是否一致了。固須要咱們寫一個腳本實現這樣的功能,檢測A機器和B機器/data/web/目錄下文件的異同,咱們以A機器上的文件做爲標準。好比,倘若B機器少了一個a.txt文件,那咱們應該可以檢測出來,或者B機器上的b.txt文件有過改動,咱們也應該可以檢測出來(B機器上多了文件咱們不用考慮)。

提示: 使用核心命令 md5sum a.txt 算出md5值,去和B機器上的比較。

實現代碼:

#!/bin/bash #假設A機器到B機器已經作了無密碼登陸設置 dir=/data/web ##假設B機器的IP爲192.168.0.100 B_ip=192.168.0.100 find $dir -type f |xargs md5sum >/tmp/md5.txt ssh $B_ip "find $dir -type f |xargs md5sum >/tmp/md5_b.txt" scp $B_ip:/tmp/md5_b.txt /tmp for f in `awk '{print $2}' /tmp/md5.txt` do if grep -q "$f" /tmp/md5_b.txt then md5_a=`grep $f /tmp/md5.txt|awk '{print $1}'` md5_b=`grep $f /tmp/md5_b.txt|awk '{print $1}'` if [ $md5_a != $md5_b ] then echo "$f changed." fi else echo "$f deleted. " fi done

【腳本33】統計網卡流量

寫一個腳本,檢測你的網絡流量,並記錄到一個日誌裏。須要按照以下格式,而且一分鐘統計一次(只須要統計外網網卡,假設網卡名字爲eth0):

2017-08-04 01:11
eth0 input: 1000bps
eth0 output : 200000bps
################ 2017-08-04 01:12 eth0 input: 1000bps eth0 output : 200000bps

提示:使用sar -n DEV 1 59 這樣能夠統計一分鐘的平均網卡流量,只須要最後面的平均值。另外,注意換算一下,1byt=8bit

實現代碼:

#!/bin/bash while : do LANG=en DATE=`date +"%Y-%m-%d %H:%M"` LOG_PATH=/tmp/traffic_check/`date +%Y%m` LOG_FILE=$LOG_PATH/traffic_check_`date +%d`.log [ -d $LOG_PATH ] || mkdir -p $LOG_PATH echo " $DATE" >> $LOG_FILE sar -n DEV 1 59|grep Average|grep eth0 \ |awk '{print "\n",$2,"\t","input:",$5*1000*8,"bps", \ "\t","\n",$2,"\t","output:",$6*1000*8,"bps" }' \ >> $LOG_FILE echo "#####################" >> $LOG_FILE done

【腳本34】系統-批量殺進程

今天發現網站訪問超級慢,top看以下:
101個shell腳本

有不少sh進程,再ps查看:
101個shell腳本

這個腳本,運行很慢,由於制定了cron,上一次尚未運行完,又有了新的運行任務。太多確定會致使系統負載升高。當務之急就是先把這些在跑的給kill掉。那麼咱們可使用一條命令,直接殺死全部的sh。

命令以下:

ps aux |grep clearmem.sh |grep -v grep|awk '{print $2}'|xargs kill

【腳本35】判斷是否開啓80端口

寫一個腳本判斷你的Linux服務器裏是否開啓web服務?(監聽80端口)若是開啓了,請判斷出跑的是什麼服務,是httpd呢仍是nginx又或者是其餘的什麼?

實現代碼:

#!/bin/bash port=`netstat -lnp | grep 80` if [ -z "port" ]; then echo "not start service."; exit; fi web_server=`echo $port | awk -F'/' '{print $2}'|awk -F : '{print $1}'` case $web_server in httpd ) echo "apache server." ;; nginx ) echo "nginx server." ;; * ) echo "other server." ;; esac

【腳本36】監控mysql服務

假設,當前MySQL服務的root密碼爲123456,寫腳本檢測MySQL服務是否正常(好比,能夠正常進入mysql執行show processlist),並檢測一下當前的MySQL服務是主仍是從,若是是從,請判斷它的主從服務是否異常。若是是主,則不須要作什麼。

實現代碼:

#!/bin/bash Mysql_c="mysql -uroot -p123456" $Mysql_c -e "show processlist" >/tmp/mysql_pro.log 2>/tmp/mysql_log.err n=`wc -l /tmp/mysql_log.err|awk '{print $1}'` if [ $n -gt 0 ] then echo "mysql service sth wrong." else $Mysql_c -e "show slave status\G" >/tmp/mysql_s.log n1=`wc -l /tmp/mysql_s.log|awk '{print $1}'` if [ $n1 -gt 0 ] then y1=`grep 'Slave_IO_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'` y2=`grep 'Slave_SQL_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'` if [ $y1 == "Yes" ] && [ $y2 == "Yes" ] then echo "slave status good." else echo "slave down." fi fi fi

【腳本37】帶選項的用戶腳本

要求以下:

  1. 只支持三個選項 ‘–del’ ‘–add’ –help輸入其餘選項報錯。
  2. 使用‘–add’須要驗證用戶名是否存在,存在則反饋存在。且不添加。 不存在則建立該用戶,切>添加與該用戶名相同的密碼。而且反饋。
  3. 使用‘–del’ 須要驗證用戶名是否存在,存在則刪除用戶及其家目錄。不存在則反饋該用戶不存>在。
  4. –help 選項反饋出使用方法
  5. 支持以,分隔 一次刪除多個或者添加多個用戶。
  6. 能用echo $? 檢測腳本執行狀況 成功刪除或者添加爲0,報錯信息爲其餘數字。
  7. 能以,分割。一次性添加或者 刪除多個用戶。 例如 adddel.sh –add user1,user2,user3…….
  8. 不容許存在明顯bug。

代碼參考:

#!/bin/bash #written by aming. if [ $# -eq 0 -o $# -gt 2 ] then echo "use $0 --add username or $0 --del username or $0 --help." exit 1 fi case $1 in --add) n=0 for u in `echo $2|sed 's/,/ /g'`; do if awk -F: '{print $1}' /etc/passwd |grep -qw "$u" then echo "The user $u exist." else useradd $u echo -e "$u\n$u"|passwd $u >/dev/null 2>&1 echo "The user $u added successfully." n=$[$n+1] fi done if [ $n -eq 0 ]; then exit 2 fi ;; --del) n=0 for u in `echo $2|sed 's/,/ /g'`; do if awk -F: '{print $1}' /etc/passwd|grep -qw "$u" then userdel -r $u echo "The user $u deleted successfully." n=$[$n+1] else echo "The user $u not exist." fi done if [ $n -eq 0 ]; then exit 3 fi ;; --help) echo -e "--add can add user,and the passwd is the same as username. It can add multiuser such as --add user1,user2,user3..." echo "--del cat delete user.It can delete user such as --del user1,user2,user3..." ;; *) echo "use $0 --add username or $0 --del username or $0 --help." exit 1 ;; esac

【腳本38】被3整除

寫一個腳本: 計算100之內全部能被3整除的正整數的和

代碼參考:

#!/bin/bash sum=0 for i in {1..100};do if [ $[$i%3] -eq 0 ];then sum=$[$i+$sum] fi done echo "sum:$sum"

【腳本39】腳本傳參

使用傳參的方法寫個腳本,實現加減乘除的功能。例如: sh a.sh 1 2,這樣會分別計算加、減、乘、除的結果。

要求:

  1. 腳本需判斷提供的兩個數字必須爲整數
  2. 當作減法或者除法時,須要判斷哪一個數字大
  3. 減法時須要用大的數字減少的數字
  4. 除法時須要用大的數字除以小的數字,而且結果須要保留兩個小數點。

參考代碼:

#!/bin/bash if [ $# -ne 2 ] then echo "The number of parameter is not 2, Please useage: ./$0 1 2" exit 1 fi is_int() { if echo "$1"|grep -q '[^0-9]' then echo "$1 is not integer number." exit 1 fi } max() { if [ $1 -ge $2 ] then echo $1 else echo $2 fi } min() { if [ $1 -lt $2 ] then echo $1 else echo $2 fi } sum() { echo "$1 + $2 = $[$1+$2]" } minus() { big=`max $1 $2` small=`min $1 $2` echo "$big - $small = $[$big-$small]" } mult() { echo "$1 * $2 = $[$1*$2]" } div() { big=`max $1 $2` small=`min $1 $2` d=`echo "scale =2; $big / $small"|bc` echo "$big / $small = $d" } is_int $1 is_int $2 sum $1 $2 minus $1 $2 mult $1 $2 div $1 $2

【腳本40】用戶交互腳本

寫一個腳本,執行後,打印一行提示「Please input a number:」,要求用戶輸入數值,而後打印出該數值,而後再次要求用戶輸入數值。直到用戶輸入」end」中止。

代碼參考:

#!/bin/bash while : do read -p "Please input a number:(end for exit) " n num=` echo $n |sed -r 's/[0-9]//g'|wc -c ` if [ $n == "end" ] then exit elif [ $num -ne 1 ] then echo "what you input is not a number!Try again!" else echo "your input number is: $n" fi done

【腳本41】獲取ip

提示用戶輸入網卡的名字,而後咱們用腳本輸出網卡的ip。 看似簡單,可是須要考慮多個方面,好比咱們輸入的不符合網卡名字的規範,怎麼應對。名字符合規範,可是根本就沒有這個網卡有怎麼應對。

代碼參考:

#!/bin/bash while : do read -p "請輸入網卡名: " e e1=`echo "$e" | sed 's/[-0-9]//g'` e2=`echo "$e" | sed 's/[a-zA-Z]//g'` if [ -z $e ] then echo "你沒有輸入任何東西" continue elif [ -z $e1 ] then echo "不要輸入純數字在centos中網卡名是以eth開頭後面加數字" continue elif [ -z $e2 ] then echo "不要輸入純字母在centos中網卡名是以eth開頭後面加數字" continue else break fi done ip() { ifconfig | grep -A1 "$1 " |tail -1 | awk '{print $2}' | awk -F ":" '{print $2}' } myip=`ip $e` if [ -z $myip ] then echo "抱歉,沒有這個網卡。" else echo "你的網卡IP地址是$myip" fi

【腳本42】列出子目錄

腳本的功能:
腳本能夠帶參數也能夠不帶,參數能夠有多個,每一個參數必須是一個目錄,腳本檢查參數個數,若等於0,則列出當前目錄自己;不然,顯示每一個參數包含的子目錄。

參考代碼:

#!/bin/bash if [ $# == 0 ] then ls -ld `pwd` else for i in `seq 1 $#` do a=$i echo "ls ${!a}" ls -l ${!a} |grep '^d' done fi

標註:

你可能會對${!a}有疑問,這裏是一個特殊用法,在shell中,$1爲第一個參數,$2爲第二個參數,以此類推,那麼這裏的數字要是一個變量如何表示呢?好比n=3,我想取第三個參數,可否寫成 $$n? shell中是不支持的,那怎麼辦? 就用腳本中的這種方法: a=$n, echo ${!a}

【腳本43】下載文件

建立一個函數,能接受兩個參數:

  1. 第一個參數爲URL,便可下載的文件;第二個參數爲目錄,即下載後保存的位置;
  2. 若是用戶給的目錄不存在,則提示用戶是否建立;若是建立就繼續執行,不然,函數返回一個51的錯誤值給調用腳本;
  3. 若是給的目錄存在,則下載文件;下載命令執行結束後測試文件下載成功與否;若是成功,則>返回0給調用腳本,不然,返回52給調用腳本;

提示,在函數中返回錯誤值給調用腳本,使用return

參考代碼:

#!/bin/bash if [ ! -d $2 ] then echo "please make directory" exit 51 fi cd $2 wget $1 n=`echo $?` if [ $n -eq 0 ];then exit 0 else exit 52 fi

【腳本44】猜數字

寫一個猜數字腳本,當用戶輸入的數字和預設數字(隨機生成一個小於100的數字)同樣時,直接退出,不然讓用戶一直輸入,而且提示用戶的數字比預設數字大或者小。

參考代碼:

#!/bin/bash m=`echo $RANDOM` n1=$[$m%100] while : do read -p "Please input a number: " n if [ $n == $n1 ] then break elif [ $n -gt $n1 ] then echo "bigger" continue else echo "smaller" continue fi done echo "You are right."

【腳本45】抽籤腳本

一、寫一個腳本執行後,輸入名字,產生隨機數01-99之間的數字。
二、若是相同的名字重複輸入,抓到的數字仍是第一次抓取的結果,
三、前面已經抓到的數字,下次不能在出現相同數字。
四、第一個輸入名字後,屏幕輸出信息,並將名字和數字記錄到文件裏,程序不能退出
繼續等待別的學生輸入。

參考代碼:

while : do read -p "Please input a name:" name if [ -f /work/test/1.log ];then bb=`cat /work/test/1.log | awk -F: '{print $1}' | grep "$name"` if [ "$bb" != "$name" ];then #名字不重複狀況下 aa=`echo $RANDOM | awk -F "" '{print $2 $3}'` while : do dd=`cat /work/test/1.log | awk -F: '{print $2}' | grep "$aa"` if [ "$aa" == "$dd" ];then #數字已經存在狀況下 echo "數字已存在." aa=`echo $RANDOM | awk -F "" '{print $2 $3}'` else break fi done echo "$name:$aa" | tee -a /work/test/1.log else aa=`cat /work/test/1.log | grep "$name" | awk -F: '{print $2}'` #名字重複 echo $aa echo "重複名字." fi else aa=`echo $RANDOM | awk -F "" '{print $2 $3}'` echo "$name:$aa" | tee -a /work/test/1.log fi done

【腳本46】打印只有一個數字的行

如題,把一個文本文檔中只有一個數字的行給打印出來。

參考代碼:

#!/bin/bash f=/etc/passwd line=`wc -l $f|awk '{print $1}'` for l in `seq 1 $line`; do n=`sed -n "$l"p $f|grep -o '[0-9]'|wc -l`; if [ $n -eq 1 ]; then sed -n "$l"p $f fi done

【腳本47】日誌歸檔

相似於日誌切割,系統有個logrotate程序,能夠完成歸檔。但如今咱們要本身寫一個shell腳本實現歸檔。

舉例: 假如服務的輸出日誌是1.log,我要求天天歸檔一個,1.log次日就變成1.log.1,第三天1.log.2, 第四天 1.log.3 一直到1.log.5

參考答案:

#!/bin/bash function e_df() { [ -f $1 ] && rm -f $1 } for i in `seq 5 -1 2` do i2=$[$i-1] e_df /data/1.log.$i if [ -f /data/1.log.$i2 ] then mv /data/1.log.$i2 /data/1.log.$i fi done e_df /data/1.log.1 mv /data/1.log /data/1.log.1

【腳本48】找出活動ip

寫一個shell腳本,把192.168.0.0/24網段在線的ip列出來。
思路: for循環, 0.1 — 0.254 依次去ping,能通說明在線。

參考代碼:

#!/bin/bash ips="192.168.1." for i in `seq 1 254` do ping -c 2 $ips$i >/dev/null 2>/dev/null if [ $? == 0 ] then echo "echo $ips$i is online" else echo "echo $ips$i is not online" fi done

【腳本49】檢查錯誤

寫一個shell腳本,檢查指定的shell腳本是否有語法錯誤,如有錯誤,首先顯示錯誤信息,而後提示用戶輸入q或者Q退出腳本,輸入其餘內容則直接用vim打開該shell腳本。

提醒: 檢查shell腳本有沒有語法錯誤的命令是 sh -n xxx.sh

參考代碼:

#!/bin/bash sh -n $1 2>/tmp/err if [ $? -eq "0" ] then echo "The script is OK." else cat /tmp/err read -p "Please inpupt Q/q to exit, or others to edit it by vim. " n if [ -z $n ] then vim $1 exit fi if [ $n == "q" -o $n == "Q" ] then exit else vim $1 exit fi fi

【腳本50】格式化輸出

輸入一串隨機數字,而後按千分位輸出。

好比輸入數字串爲「123456789」,輸出爲123,456,789

代碼參考:

#!/bin/bash read -p "輸入一串數字:" num v=`echo $num|sed 's/[0-9]//g'` if [ -n "$v" ] then echo "請輸入純數字." exit fi length=${#num} len=0 sum='' for i in $(seq 1 $length) do len=$[$len+1] if [[ $len == 3 ]] then sum=','${num:$[0-$i]:1}$sum len=0 else sum=${num:$[0-$i]:1}$sum fi done if [[ -n $(echo $sum | grep '^,' ) ]] then echo ${sum:1} else echo $sum fi

上面這個實現比較複雜,下面再來一個sed的:

#!/bin/bash read -p "輸入一串數字:" num v=`echo $num|sed 's/[0-9]//g'` if [ -n "$v" ] then echo "請輸入純數字." exit fi echo $num|sed -r '{:number;s/([0-9]+)([0-9]{3})/\1,\2/;t number}'

【腳本51】

1 編寫一個名爲iffile程序,它執行時判斷/bin目錄下date文件是否存在?

參考代碼:

#!/bin/bash if [ -f /bin/date ] then echo "/bin/date file exist." else echo "/bin/date not exist." fi

2 編寫一個名爲greet的問候程序,它執行時能根據系統當前的時間向用戶輸出問候信息。設從半夜到中午爲早晨,中午到下午六點爲下午,下午六點到半夜爲晚上。

參考代碼:

#!/bin/bash h=`date +%H` if [ $h -ge 0 ] && [ $h -lt 12 ] then echo "Good morning." elif [ $h -ge 12 ] && [ $h -lt 18 ] then echo "Good afternoon." else echo "Good evening." fi

【腳本52】判斷用戶登陸

1 編寫一個名爲ifuser的程序,它執行時帶用戶名做爲命令行參數,判斷該用戶是否已經在系統中登陸,並給出相關信息。

參考代碼:

#!/bin/bash read -p "Please input the username: " user if who | grep -qw $user then echo $user is online. else echo $user not online. fi

2 編寫一個名爲menu的程序,實現簡單的彈出式菜單功能,用戶能根據顯示的菜單項從鍵盤選擇執行對應的命令。

參考代碼:

#!/bin/bash function message() { echo "0. w" echo "1. ls" echo "2.quit" read -p "Please input parameter: " Par } message while [ $Par -ne '2' ] ; do case $Par in 0) w ;; 1) ls ;; 2) exit ;; *) echo "Unkown command" ;; esac message done

【腳本53】更改後綴名

1 編寫一個名爲chname的程序,將當前目錄下全部的.txt文件改名爲.doc文件。

參考代碼:

#!/bin/bash find . -type f -name "*.txt" > /tmp/txt.list for f in `cat /tmp/txt.list` do n=`echo $f|sed -r 's/(.*)\.txt/\1/'` echo "mv $f $n.doc" done

2 編寫一個名爲chuser的程序,執行中每隔5分鐘檢查指定的用戶是否登陸系統,用戶名從命令行輸入;若是指定的用戶已經登陸,則顯示相關信息。

參考代碼:

#!/bin/bash read -p "Please input the username: " user while : do if who | grep -qw $user then echo $user login. else echo $user not login. fi sleep 300 done

【腳本54】判斷pid是否一致

先普及一小段知識,咱們用ps aux能夠查看到進程的PID,而每一個PID都會在/proc內產生。若是查看到的pid而proc內是沒有的,則是進程被人修改了,這就表明你的系統頗有可能已經被***過了。

請你們用上面知識編寫一個shell,按期檢查下本身的系統是否被人***過。

參考代碼:

#!/bin/bash ps aux|awk '/[0-9]/ {print $2}'|while read pid do result=`find /proc/ -maxdepth 1 -type d -name "$pid"` if [ -z $result ]; then echo "$pid abnormal!" fi done

【腳本55】一列變三行

好比1.txt內容:

1
2
3
4
5
6
7

處理後應該是:

1 2 3
4 5 6
7

可以使用sed命令完成:

sed 'N;N;s/\n/ /g' 1.txt

【腳本56】shell的getops

寫一個getinterface.sh 腳本能夠接受選項[i,I],完成下面任務:

  1. 使用一下形式:getinterface.sh [-i interface | -I ip]
  2. 當用戶使用-i選項時,顯示指定網卡的IP地址;當用戶使用-I選項時,顯示其指定ip所屬的網卡。
    • 例:sh getinterface.sh -i eth0
    • sh getinterface.sh -I 192.168.0.1
  3. 當用戶使用除[-i | -I]選項時,顯示[-i interface | -I ip]此信息。
  4. 當用戶指定信息不符合時,顯示錯誤。(好比指定的eth0沒有,而是eth1時)

參考代碼:

#!/bin/bash ip add |awk -F ":" '$1 ~ /^[1-9]/ {print $2}'|sed 's/ //g' > /tmp/eths.txt [ -f /tmp/eth_ip.log ] && rm -f /tmp/eth_ip.log for eth in `cat /tmp/eths.txt` do ip=`ip add |grep -A2 ": $eth" |grep inet |awk '{print $2}' |cut -d '/' -f 1` echo "$eth:$ip" >> /tmp/eth_ip.log done useage() { echo "Please useage: $0 -i 網卡名字 or $0 -I ip地址" } wrong_eth() { if ! awk -F ':' '{print $1}' /tmp/eth_ip.log | grep -qw "^$1$" then echo "請指定正確的網卡名字" exit fi } wrong_ip() { if ! awk -F ':' '{print $2}' /tmp/eth_ip.log | grep -qw "^$1$" then echo "請指定正確的ip地址" exit fi } if [ $# -ne 2 ] then useage exit fi case $1 in -i) wrong_eth $2 grep -w $2 /tmp/eth_ip.log |awk -F ':' '{print $2}' ;; -I) wrong_ip $2 grep -w $2 /tmp/eth_ip.log |awk -F ':' '{print $1}' ;; *) useage exit esac

【腳本57】3位隨機數字

寫一個腳本產生隨機3位的數字,而且能夠根據用戶的輸入參數來判斷輸出幾組。 好比,腳本名字爲 number3.sh。
執行方法:
bash number3.sh
直接產生一組3位數字。
bash number3.sh 10
插上10組3位數字。

思路: 可使用echo $RANDOM獲取一個隨機數字,而後再除以10,取餘獲取0-9隨機數字,三次運算得到一組。

參考代碼:

#!/bin/bash get_a_num() { n=$[$RANDOM%10] echo $n } get_numbers() { for i in 1 2 3; do a[$i]=`get_a_num` done echo ${a[@]} } if [ -n "$1" ]; then m=`echo $1|sed 's/[0-9]//g'` if [ -n "$m" ]; then echo "Useage bash $0 n, n is a number, example: bash $0 5" exit else for i in `seq 1 $1` do get_numbers done fi else get_numbers fi

【腳本58】檢查服務

先判斷是否安裝http和mysql,沒有安裝進行安裝,安裝了檢查是否啓動服務,若沒有啓動則須要啓動服務。

說明:操做系統爲centos6,httpd和mysql所有爲rpm包安裝。

參考代碼:

#!/bin/bash if_install() { n=`rpm -qa|grep -cw "$1"` if [ $n -eq 0 ] then echo "$1 not install." yum install -y $1 else echo "$1 installed." fi } if_install httpd if_install mysql-server chk_ser() { p_n=`ps -C "$1" --no-heading |wc -l` if [ $p_n -eq 0 ] then echo "$1 not start." /etc/init.d/$1 start else echo "$1 started." fi } chk_httpd chk_mysqld

【腳本59】判斷日期是否合法

用shell腳本判斷輸入的日期是否合法。就是判斷日期是都是真實的日期,好比20170110就是合法日期,20171332就不合法

參考代碼:

#!/bin/bash #check date if [ $# -ne 1 ] || [ ${#1} -ne 8 ] then echo "Usage: bash $0 yyyymmdd" exit 1 fi datem=$1 year=${datem:0:4} month=${datem:4:2} day=${datem:6:2} if echo $day|grep -q '^0' then day=`echo $day |sed 's/^0//'` fi if cal $month $year >/dev/null 2>/dev/null then daym=`cal $month $year|egrep -v "$year|Su"|grep -w "$day"` if [ "$daym" != "" ] then echo ok else echo "Error: Please input a wright date." exit 1 fi else echo "Error: Please input a wright date." exit 1 fi

【腳本60】監控網卡

1.每10分鐘檢測一次指定網卡的流量
2.若是流量爲0,則重啓網卡

參考代碼:

#!/bin/bash LANG=en n1=`sar -n DEV 1 60 |grep eth0 |grep -i average|awk '{print $5}'|sed 's/\.//g'` n2=`sar -n DEV 1 60 |grep eth0 |grep -i average|awk '{print $6}'|sed 's/\.//g'` if [ $n1 == "000" ] && [ $n2 == "000" ] then ifdown eth0 ifup eth0 fi

而後寫個cron,10分鐘執行一次


【腳本61】監控web可用性

寫一個shell腳本,經過curl -I 返回的狀態碼來斷定所訪問的網站是否正常。好比,當狀態碼爲200時,纔算正常。

參考代碼:

#/bin/bash url="http://www.apelearn.com/index.php" sta=`curl -I $url 2>/dev/null |head -1 |awk '{print $2}'` if [ $sta != "200" ] then python /usr/local/sbin/mail.py xxx@qq.com "$url down." "$url down" fi

【腳本62】文件打包

需求:將用戶家目錄(考慮到執行腳本的用戶多是普通用戶也多是root)下面小於5KB的文件打包成tar.gz的壓縮包,並以當前日期爲文件名前綴,例現在天打包的文件爲2017-09-15.tar.gz。

參考代碼:

#!/bin/bash t=`date +%F` cd $HOME tar czf $t.tar.gz `find . -type f -size -5k`

【腳本63】端口解封

一個小夥伴提到一個問題,他不當心用iptables規則把sshd端口22給封掉了,結果不能遠程登錄,要想解決這問題,還要去機房,登錄真機去刪除這規則。 問題來了,要寫個監控腳本,監控iptables規則是否封掉了22端口,若是封掉了,給打開。 寫好腳本,放到任務計劃裏,每分鐘執行一次。

參考代碼:

#!/bin/bash # check sshd port drop /sbin/iptables -nvL --line-number|grep "dpt:22"|awk -F ' ' '{print $4}' > /tmp/drop.txt i=`cat /tmp/drop.txt|head -n 1|egrep -iE "DROP|REJECT"|wc -l` if [ $i -gt 0 ] then /sbin/iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT fi

【腳本64】統計分析日誌

已知nginx訪問的日誌文件在/usr/local/nginx/logs/access.log內

請統計下早上10點到12點 來訪ip最多的是哪一個?

日誌樣例:

111.199.186.68 – [15/Sep/2017:09:58:37 +0800]  「//plugin.php?id=security:job」 200 「POST //plugin.php?id=security:job HTTP/1.1″」http://a.lishiming.net/forum.php?mod=viewthread&tid=11338&extra=page%3D1%26filter%3Dauthor%26orderby%3Ddateline」 「Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36」 「0.516」

203.208.60.208 – [15/Sep/2017:09:58:46 +0800] 「/misc.php?mod=patch&action=ipnotice&_r=0.05560809863330207&inajax=1&ajaxtarget=ip_notice」 200 「GET /misc.php?mod=patch&action=ipnotice&_r=0.05560809863330207&inajax=1&ajaxtarget=ip_notice HTTP/1.1″」http://a.lishiming.net/forum.php?mod=forumdisplay&fid=65&filter=author&orderby=dateline」 「Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36」 「0.065」

實現這個需求使用以下命令便可:

grep '15/Sep/2017:1[0-2]:[0-5][0-9]:' /usr/local/nginx/logs/access.log|awk '{print $1}'|sort -n|uniq -c |sort -n|tail -n1

【腳本65】打印數字

寫一個shell腳本。提示你輸入一個暫停的數字,而後從1打印到該數字。而後詢問是否繼續。繼續的話在輸入個在數字 接着打印。不繼續退出。

例:若是輸入的是5,打印1 2 3 4 5 而後繼續 輸入15 而後打印 6 7 …14 15 依此類推。

參考代碼:

#!/bin/bash read -p "請輸入您想要暫停的數字:" number_1 for i in `seq 1 $number_1`; do echo $i done read -p "是否繼續輸入數字?" a if [ $a == "yes" ];then read -p "請繼續輸入您想要暫停的數字:" number_2 number_3=$[$number_1+1] if [ $number_2 -gt $number_1 ];then for h in `seq $number_3 $number_2`; do echo $h done else echo "輸入數字錯誤,請輸入大於的數字!" fi else exit fi

【腳本66】給文檔增長內容

在文本文檔1.txt第5行(假設文件行數大於5)後面增長以下內容:

# This is a test file. # Test insert line into this file.

參考命令:

sed -i "5a # This is a test file.\n# Test insert line into this file." 1.txt

【腳本67】備份etc下面文件

設計一個shell程序,在每個月第一天備份並壓縮/etc目錄的全部內容,存放在/root/bak目錄裏,且文件名爲以下形式」yymmdd_etc.tar.gz」,yy爲年,mm爲月,dd爲日。

參考代碼:

#!/bin/sh if [ ! -d /root/bak ] then mkdir /root/bak fi prefix=`date +%y%m%d` d=`date +%d` if [ $d == "01" ] then cd /etc/ tar czf /root/bak/$prefix_etc.tar.gz ./ fi

【腳本68】計算單詞重複次數

將文件內全部的單詞的重複次數計算出來,只須要列出重複次數最多的10個單詞。

假設文檔名字叫作a.txt,使用以下命令便可:

sed 's/[^a-zA-Z]/ /g' a.txt|xargs -n1 |sort |uniq -c |sort -nr |head

【腳本69】成員分組

需求是,把全部的成員平均得分紅若干個小組。這裏,我會提供一我的員列表,好比成員有50人,須要分紅7個小組,要求隨機性,每次和每次分組的結構應該不一致。

假設成員列表文件爲members.txt

參考代碼:

#!/bin/bash f=members.txt n=`wc -l $f|awk '{print $1}'` get_n() { l=`echo $1|wc -c` n1=$RANDOM n2=$[$n1+$l] g_id=$[$n1%7] if [ $g_id -eq 0 ] then g_id=7 fi echo $g_id } for i in `seq 1 7` do [ -f n_$i.txt ] && rm -f n_$i.txt done for i in `seq 1 $n` do name=`sed -n "$i"p $f` g=`get_n $name` echo $name >> n_$g.txt done nu(){ wc -l $1|awk '{print $1}' } max(){ ma=0 for i in `seq 1 7` do n=`nu n_$i.txt` if [ $n -gt $ma ] then ma=$n fi done echo $ma } min(){ mi=50 for i in `seq 1 7` do n=`nu n_$i.txt` if [ $n -lt $mi ] then mi=$n fi done echo $mi } ini_min=1 while [ $ini_min -le 7 ] do m1=`max` m2=`min` ini_min=m2 for i in `seq 1 7` do n=`nu n_$i.txt` if [ $n -eq $m1 ] then f1=n_$i.txt elif [ $n -eq $m2 ] then f2=n_$i.txt fi done name=`tail -n1 $f1` echo $name >> $f2 sed -i "/$name/d" $f1 ini_min=$[$ini_min+1] done for i in `seq 1 7` do echo "$i 組成員有:" cat n_$i.txt echo done

【腳本70】shell中的小數

有一組式子以下:

a=0.5
b=3
c=a*b

求c的值,參考代碼:

#!/bin/bash a=0.5 b=3 c=`echo "scale=1;$a*$b"|bc` echo $c

【腳本71】a.txt有b.txt沒有

有兩個文件a.txt和b.txt,需求是,把a.txt中有的而且b.txt中沒有的行找出來,並寫入到c.txt,而後計算c.txt文件的行數。

參考代碼:

#!/bin/bash n=`wc -l a.txt|awk '{print $1}'` [ -f c.txt ] && rm -f c.txt for i in `seq 1 $n` do l=`sed -n "$i"p a.txt` if ! grep -q "^$l$" b.txt then echo $l >>c.txt fi done wc -l c.txt 或者用grep實現 grep -vwf b.txt a.txt > c.txt; wc -l c.txt

【腳本72】殺死進程

把當前用戶下全部進程名字中含有」java」的進程關閉。

參考答案:

ps -u $USER |awk '$NF ~ /java/ {print $1}'|xargs kill

【腳本73】備份數據表

用shell實現,以併發進程的形式將mysql數據庫全部的表備份到當前目錄,並把全部的表壓縮到一個壓縮包文件裏。

假設數據庫名字爲mydb,用戶名爲zero,密碼爲passwd。

提示: 在shell中加上&能夠將命令丟到後臺,從而能夠同時執行多條命令達到併發的效果。

參考代碼:

#!/bin/bash pre=`date +%F` for d in `mysql -uaming -ppasswd mydb -e "show tables"|grep -v 'Tables_in_'` do mysqldump -uaming -ppasswd mydb $d > $d.sql & done tar czf $pre.tar.gz *.sql rm -f *.sql

【腳本74】監控節點

一個網站,使用了cdn,全國各地有幾十個節點。須要你寫一個shell腳原本監控各個節點是否正常。

假如:

  1. 監控的url爲www.xxx.com/index.php
  2. 源站ip爲88.88.88.88

參考代碼:

#!/bin/bash url="www.xxx.com/index.php" s_ip="88.88.88.88" curl -x $s_ip:80 $url > /tmp/source.html 2>/dev/null for ip in `cat /tmp/ip.txt` do curl -x $ip:80 $url 2>/dev/null >/tmp/$ip.html [ -f /tmp/$ip.diff ] && rm -f /tmp/$ip.diff touch /tmp/$ip.diff diff /tmp/source.html /tmp/$ip.html > /tmp/$ip.diff 2>/dev/null n=`wc -l /tmp/$ip.diff|awk '{print $1}'` if [ $n -lt 0 ] then echo "node $ip sth wrong." fi done

【腳本75】破解字符串

已知下面的字符串是經過RANDOM隨機數變量md5sum|cut-c 1-8截取後的結果,請破解這些字符串對應的md5sum前的RANDOM對應數字?

21029299
00205d1c
a3da1677
1f6d12dd
890684ba

解題思路:經過每次傳遞一個參數的方式,來實現依次破解,$RANDOM的範圍爲0-32767。

參考代碼:

#!/bin/bash for n in {0..32767} do MD5=`echo $n | md5sum | cut -c 1-8` if [ "$MD5" == "$1" ];then echo "$n $1 " break fi done

【腳本76】判斷cpu廠商

寫一個腳本:

  1. 判斷當前主機的CPU生產商,其信息在/proc/cpuinfo文件中vendor id一行中。
  2. 若是其生產商爲AuthenticAMD,就顯示其爲AMD公司;
  3. 若是其生產商爲GenuineIntel,就顯示其爲Intel公司;
  4. 不然,就說其爲非主流公司。

參考代碼:

#!/bin/bash m=`cat /proc/cpuinfo |grep vendor_id|awk -F":" '{print $2}'|tail -1` if [ $m == "GenuineIntel" ] then echo "cpu is 英特爾" elif [ $m == "AuthenticAMD" ] then echo "cpu is AMD" else echo "cpu is 非主流" fi

【腳本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,實現如下功能:

  1. 當/home/log 目錄存在時 將/home目錄下全部tmp開頭的文件或目錄移/home/log 目錄。
  2. 當/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

【腳本92】截取tomcat日誌

寫一個截取tomcat catalina.out日誌的腳本。

tomcat實例t1-t4:

[root@server ~]# tree -L 1 /opt/TOM/ /opt/TOM/ ├── crontabs ├── t1 ├── t2 ├── t3 └── t4 5 directories, 0 files

catalina.out日誌路徑:

[root@server ~]# find /opt/TOM/ -name catalina.out /opt/TOM/t1/logs/catalina.out /opt/TOM/t3/logs/catalina.out /opt/TOM/t4/logs/catalina.out /opt/TOM/t2/logs/catalina.out

要求:

  1. 這個腳本能夠取tomcat實例t1-t4的日誌
  2. 這個腳本能夠自定義取日誌的起始點,好比取今天早上10點以後到如今的數據
  3. 這個腳本能夠自定義取日誌的起始點和終點,好比取今天早上9點到晚上8點的數據

catalina.out 日誌片斷:

Mar 29, 2016 1:52:24 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler [「http-bio-8080」]
Mar 29, 2016 1:52:24 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler [「ajp-bio-8009」]
Mar 29, 2016 1:52:24 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2102 ms

參考代碼:

#!/bin/bash export LANG=en_US.UTF-8 export PATH=$PATH IPADD=`/sbin/ifconfig | grep "inet addr" | head -1 | awk '{print $2}'| awk -F '.' '{print $NF}'` LOGFILE="/opt/TOM/$1/logs/catalina.out" YEAR=`date +%Y` DATE=`date +%m%d_%H%M` TOMCAT=$1 BEGIN_TIME=$YEAR$2 END_TIME=$YEAR$3 ##judge is a.m.or p.m. TIME_HOUR1=`echo ${BEGIN_TIME:9:2}` cut_log() { N_DATE1=`echo $1 | sed 's/_/ /g'` D_DATE1=`echo $2 | sed 's/_/ /g'` E_DATE1=`echo $3 | sed 's/_/ /g'` [ $4 ] && N_DATE2=`echo $4 | sed 's/_/ /g'` [ $5 ] && D_DATE2=`echo $5 | sed 's/_/ /g'` [ $6 ] && E_DATE2=`echo $6 | sed 's/_/ /g'` BEGIN=`grep -nE "${N_DATE1}|${D_DATE1}|${E_DATE1}" ${LOGFILE} | head -1 | cut -d : -f1` [ "$N_DATE2" ] && END=`grep -nE "${N_DATE2}|${D_DATE2}|${E_DATE2}" ${LOGFILE} | tail -1 | cut -d : -f1` [ ! -z "${TIME_HOUR1}" ] && if [ ${TIME_HOUR1} -gt 12 ] ; then BEGIN1=`grep -nE "${N_DATE1}|${D_DATE1}|${E_DATE1}" ${LOGFILE} |grep " PM " |grep "${E_DATE1}" | head -1 | cut -d : -f1` if [ ! -z "${BEGIN1}" ] ; then [ "${BEGIN1}" -gt "${BEGIN}" ] ; BEGIN=${BEGIN1} fi fi if [ "$BEGIN" ] && [ -z "$END" ] ; then if [ "$N_DATE2" ]; then echo "${END_TIME}時間點沒有訪問日誌,請從新設置時間點." else sed -n "${BEGIN},[ DISCUZ_CODE_0 ]quot;p ${LOGFILE} > /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log fi elif [ "$END" ];then [ "$BEGIN" ] || BEGIN=1 sed -n "${BEGIN},${END}"p ${LOGFILE} > /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log else [ "$END_TIME" != "$YEAR" ] && echo "該時段 ${BEGIN_TIME}~${END_TIME} 沒有日誌." [ "$END_TIME" = "$YEAR" ] && echo "該時段 ${BEGIN_TIME}~now 沒有日誌." fi if [ -s /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log ]; then cd /home/gcweb && tar -zcf ${IPADD}_${TOMCAT}_${DATE}.tar.gz ${IPADD}_${TOMCAT}_${DATE}.log rm -f /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log sz /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.tar.gz echo "Success to get logs." rm -f /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.tar.gz fi } get_time() { case "$1" in 4) N_DATE=`date -d "$2" +"%Y-%m-%d" 2>/dev/null` D_DATE=`date -d "$2" +"%Y/%m/%d" 2>/dev/null` E_DATE=`date -d "$2" +"%h %e,_%Y" 2>/dev/null|sed 's/ /_/g'` echo $N_DATE $D_DATE $E_DATE ;; 7) TIME=`echo $2 | awk -F'_' '{print $1,$2}'` N_DATE=`date -d "$TIME" +"%Y-%m-%d_%H" 2>/dev/null` D_DATE=`date -d "$TIME" +"%Y/%m/%d_%H" 2>/dev/null` E_DATE=`date -d "$TIME" +"%h %e,_%Y %l" 2>/dev/null|sed 's/ /_/g'` echo "$N_DATE" "$D_DATE" "$E_DATE" ;; 9) TIME=`echo $2 | awk -F'_' '{print $1,$2}'` N_DATE=`date -d "$TIME" +"%Y-%m-%d_%H:%M" 2>/dev/null` D_DATE=`date -d "$TIME" +"%Y/%m/%d_%H:%M" 2>/dev/null` E_DATE=`date -d "$TIME" +"%h %e,_%Y %l:%M" 2>/dev/null|sed 's/ /_/g'` echo "$N_DATE" "$D_DATE" "$E_DATE" ;; *) echo 1 ;; esac } check_arguments () { if [ "$1" == 1 ] || [ -z "$1" ] ;then echo "你輸入時間參數的格式沒法識別, usage: 010八、0108_十、0108_1020" exit 3 fi } check_tomcat () { if [ ! -s "${LOGFILE}" ] ;then echo "tomcat_name: ${TOMCAT} is not exist" echo "you can choose:" /bin/ls /home/gcweb/usr/local/ fi if [ $1 -lt 2 ] || [ ! -s "${LOGFILE}" ];then echo "usage: $0 tomcat_name {begin_time|begin_time end_time}" exit 2 fi } case "$#" in 0) echo "usage: $0 tomcat_name {begin_time|begin_time end_time}" exit 1 ;; 1) check_tomcat $# ;; 2) check_tomcat $# len=`echo $2 | awk '{print length($0)}'` A_DATE=$(get_time $len $BEGIN_TIME) eval $( echo $A_DATE |awk '{print "N_DATE="$1,"D_DATE="$2,"E_DATE="$3}') check_arguments "${N_DATE}" cut_log "${N_DATE}" "${D_DATE}" "${E_DATE}" ;; 3) check_tomcat $# len1=`echo $2 | awk '{print length($0)}'` len2=`echo $3 | awk '{print length($0)}'` A_DATE=$(get_time ${len1} $BEGIN_TIME) eval $( echo $A_DATE |awk '{print "N_DATE1="$1,"D_DATE1="$2,"E_DATE1="$3}') check_arguments "${N_DATE1}" A_DATE=$(get_time ${len2} $END_TIME) eval $( echo $A_DATE |awk '{print "N_DATE="$1,"D_DATE="$2,"E_DATE="$3}') check_arguments "${N_DATE}" cut_log ${N_DATE1} ${D_DATE1} ${E_DATE1} "${N_DATE}" "${D_DATE}" "${E_DATE}" ;; *) echo "usage: $0 tomcat_name {begin_time|begin_time end_time};你使用的參數太多哦." ;; esac

【腳本93】數組

寫一個腳本讓用戶輸入多個城市的名字(能夠是中文),要求很多於5個,而後把這些城市存到一個數組裏,最後用for循環把它們打印出來。

參考代碼:

#!/bin/bash read -p "請輸入至少5個城市的名字,用空格分隔:" city n=`echo $city|awk '{print NF}'` if [ $n -lt 5 ] then echo "輸入的城市個數至少爲5" exit fi name=($city) for i in ${name[@]} do echo $i done

【腳本94】批量同步代碼

需求背景是:

一個業務,有3臺服務器(A,B,C)作負載均衡,因爲規模過小目前並未使用專業的自動化運維工具。有新的需求時,開發同事改完代碼會把變動上傳到其中一臺服務器A上。可是其餘2臺服務器也須要作相同變動。

寫一個shell腳本,把A服務器上的變動代碼同步到B和C上。

其中,你須要考慮到不須要同步的目錄(假若有tmp、upload、logs、caches)

參考代碼:

#!/bin/bash echo "該腳本將會把A機器上的/data/wwwroot/www.aaa.com目錄同步到B,C機器上"; read -p "是否要繼續?(y|n) " rs() { rsync -azP \ --exclude logs \ --exclude upload \ --exclude caches \ --exclude tmp \ www.aaa.com/ $1:/data/wwwroot/www.aaa.com/ } if [ $REPLY == 'y' -o $REPLY == 'Y' ] then echo "即將同步……" sleep 2 cd /data/wwwroot/ rs B機器ip rs C機器ip echo "同步完成。" elif [ $REPLY == 'n' -o $REPLY == 'N' ] then exit 1 else echo "請輸入字母y或者n" fi

【腳本95】統計併發量

需求背景:

  • 須要統計網站的併發量,並繪圖。

思路:

  1. 藉助zabbix成圖
  2. 經過統計訪問日誌每秒的日誌條數來斷定併發量
  3. zabbix獲取數據間隔30s

說明: 只須要寫出shell腳本便可,不用關心zabbix配置。

假設日誌路徑爲:

/data/logs/www.aaa.com_access.log

日誌格式以下:

112.107.15.12 - [07/Nov/2017:09:59:01 +0800] www.aaa.com "/api/live.php" 200"-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"

參考代碼:

#!/bin/bash log=/data/logs/www.aaa.com_access.log t=`date -d "-1 second" +%Y:%H:%M:%S` #能夠大概分析一下每分鐘日誌的量級,好比說不超過3000 n=tail -3000 $log |grep -c "$t" echo $n

【腳本96】關閉服務

在centos6系統裏,咱們可使用ntsysv關閉不須要開機啓動的服務,固然也可使用chkconfig工具來實現。

寫一個shell腳本,用chkconfig工具把不經常使用的服務關閉。腳本須要寫成交互式的,須要咱們給它提供關閉的服務名字。

參考代碼:

#!/bin/bash LANG=en c="1" while [ ! $c == "q" ] do echo -e "\033[35mPlease chose a service to close from this list: \033[0m" chkconfig --list |awk '/3:on/ {print $1}' read -p "Which service to close: " s chkconfig $s off service $s stop read -p "If you want's to quit this program, tab "q", or tab "Ctrl c": " c done

【腳本97】重啓tomcat服務

在生產環境中,常常遇到tomcat沒法完全關閉,也就是說用tomcat自帶shutdown.sh腳本沒法將java進程徹底關掉。因此,須要藉助shell腳本,將進程殺死,而後再啓動。

寫一個shell腳本,實現上述功能。完全殺死一個進程的命令是 kill -9 pid.

參考代碼:

#!/bin/bash ###功能: 重啓 tomcat 進程 ###要求:對於tomcat中的某些應用,使用shutdown.sh是沒法徹底停掉全部服務的 實際操做中都須要kill掉tomcat再重啓 ## ### root can not run this script. ## if [ $USER = root ] then echo "root cann't run this script!please run with other user!" exit 1 fi ## ### check the Parameter ## if [[ $# -ne 1 ]] then echo "Usage:$0 tomcatname" exit 1 fi ## ### only one process can run one time ## TMP_FILE_U=/tmp/.tmp.ps.keyword.$USER.956327.txt #echo $TMP_FILE_U KEYWORD1="$0" KEYWORD2="$1" # 使用賦值會多fork出一個進程,因此要先重定向到一個文本,再統計. ps ux |grep "$KEYWORD1"|grep "\<$KEYWORD2\>"|grep -v "grep" > $TMP_FILE_U Pro_count=`cat $TMP_FILE_U |wc -l` if [ $Pro_count -gt 1 ] then echo "An other process already running ,exit now!" exit 1 fi ################################################### # # # begin of the script # # # ################################################### ## ### set the Parameter ## TOM=`echo $1|sed 's#/##g'` TOMCAT_DIRECTORY=~/usr/local/$TOM STARTUP_SCRIPT=$TOMCAT_DIRECTORY/bin/startup.sh TOMCAT_LOG=$TOMCAT_DIRECTORY/logs/catalina.out CONF_FILE=$TOMCAT_DIRECTORY/conf/server.xml TEMPFILE=/tmp/.tmpfile.x.89342.c4r3.tmp ## ### check if the tomcat directory exist ## if [ ! -d "$TOMCAT_DIRECTORY" ] then echo "the tomcat \"$TOM\" not exist.check again!" exit 1 fi ## ### log roteta and delete log one week ago ## rotate_log(){ TIME_FORMART=$(date +%Y%m%d%H%M%S) LOG_DIR=$(dirname $TOMCAT_LOG) mv $TOMCAT_LOG ${TOMCAT_LOG}_${TIME_FORMART} find $LOG_DIR -type f -ctime +7 -exec rm -rf {} \; } ## ### function start the tomcat ## start_tomcat() { #echo start-tomcat-func if [ -x "$STARTUP_SCRIPT" ] then rotate_log $STARTUP_SCRIPT sleep 1 tail -f $TOMCAT_LOG else if [ -e $STARTUP_SCRIPT ] then chmod +x $STARTUP_SCRIPT # echo "permition added!" if [ -x "$STARTUP_SCRIPT" ] then rotate_log $STARTUP_SCRIPT sleep 1 tail -f $TOMCAT_LOG else echo "The script not have excute permision,Couldn't add permision to Script!" exit 1 fi else echo "error,the script \"startup.sh\" not exist!" exit 1 fi fi } ## ### function stop the tomcat ## stop_tomcat() { rm -rf $TEMPFILE ps ux |grep /$TOM/ |grep -v "grep /$TOM/"|grep java > $TEMPFILE Pro_Count=`cat $TEMPFILE|wc -l` PIDS=`cat $TEMPFILE|awk '{print $2}'` rm -rf $TEMPFILE #echo $Pro_Count if [ $Pro_Count -eq 0 ] then echo "The tomcat not running now!" else if [ $Pro_Count -ne 1 ] then echo "The have $Pro_Count process running,killed!" kill -9 `echo $PIDS` WC=`ps aux | grep "/$TOM/" | grep -v "grep /$TOM/" | grep java |wc -l` [ $WC -ne 0 ] && (echo "kill process failed!";exit 1) else echo "Process killed!" kill -9 `echo $PIDS` WC=`ps aux | grep "/$TOM/" | grep -v "grep /$TOM/" | grep java |wc -l` [ $WC -ne 0 ] && (echo "kill process failed!";exit 1) fi fi } ########################### #### #### #### The main script #### #### #### ########################### echo -e "are you sure restart $TOM?(y or n)" read ANS if [ "$ANS"a != ya ] then echo -e "bye! \n" exit 1 fi stop_tomcat echo "start tomcat ..." sleep 2 start_tomcat # end

【腳本98】取消後綴

至少用兩種方法,批量把當前目錄下面全部文件名後綴爲.bak的後綴去掉,好比1.txt.bak去掉後爲1.txt

假設取消的後綴爲.bak

方法一:

#!/bin/bash for i in `ls *.bak` do mv $i `echo $i|sed 's/\.bak//g'` done

方法二:

#!/bin/bash for i in `ls *.bak` do newname=`echo $i|awk -F '.bak' '{print $1}'` mv $i $newname done

【腳本99】域名到期提醒

寫一個shell腳本,查詢指定域名的過時時間,並在到期前一週,天天發一封提醒郵件。

思路: 你們能夠在linux下使用命令「whois 域名」,如」whois xxx.com」,來獲取該域名的一些信息。

提示: whois命令,須要安裝jwhois包

參考代碼:

#!/bin/bash t1=`date +%s` is_install_whois() { which whois >/dev/null 2>/dev/null if [ $? -ne 0 ] then yum install -y jwhois fi } notify() { e_d=`whois $1|grep 'Expiry Date'|awk '{print $4}'|cut -d 'T' -f 1` e_t=`date -d "$e_d" +%s` n=`echo "86400*7"|bc` e_t1=$[$e_t-$n] if [ $t1 -ge $e_t1 ] && [ $t1 -lt $e_t ] then /usr/local/sbin/mail.py aming_test@163.com "Domain $1 will be expire." "Domain $1 expire date is $e_d." fi } is_install_whois notify xxx.com

【腳本100】自動增長公鑰

寫一個shell腳本,當咱們執行時,提示要輸入對方的ip和root密碼,而後能夠自動把本機的公鑰增長到對方機器上,從而實現密鑰認證。

參考代碼:

#!/bin/bash read -p "Input IP: " ip ping $ip -w 2 -c 2 >> /dev/null ## 查看ip是否可用 while [ $? -ne 0 ] do read -p "your ip may not useable, Please Input your IP: " ip ping $ip -w 2 -c 2 >> /dev/null done read -p "Input root\'s password of this host: " password ## 檢查命令子函數 check_ok() { if [ $? != 0 ] then echo "Error!." exit 1 fi } ## yum須要用到的包 myyum() { if ! rpm -qa |grep -q "$1" then yum install -y $1 check_ok else echo $1 already installed fi } for p in openssh-clients openssh expect do myyum $p done ## 在主機A上建立密鑰對 if [ ! -f ~/.ssh/id_rsa ] || [ ! -f ~/.ssh/id_rsa.pub ] then if [ -d ~/.ssh ] then mv ~/.ssh/ ~/.ssh_old fi echo -e "\n" | ssh-keygen -t rsa -P '' check_ok fi ## 傳私鑰給主機B if [ ! -d /usr/local/sbin/rsync_keys ] then mkdir /usr/local/sbin/rsync_keys fi cd /usr/local/sbin/rsync_keys if [ -f rsync.expect ] then d=`date +%F-%T` mv rsync.expect $d.expect fi #建立遠程同步的expect文件 cat > rsync.expect <<EOF #!/usr/bin/expect set host [lindex \$argv 0] #主機B的密碼 set passwd [lindex \$argv 1] spawn rsync -av /root/.ssh/id_rsa.pub root@\$host:/tmp/tmp.txt expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "\$passwd\r" } } expect eof spawn ssh root@\$host expect { "password:" { send "\$passwd\r" } } expect "]*" send "\[ -f /root/.ssh/authorized_keys \] && cat /tmp/tmp.txt >>/root/.ssh/authorized_keys \r" expect "]*" send "\[ -f /root/.ssh/authorized_keys \] || mkdir -p /root/.ssh/ \r" send "\[ -f /root/.ssh/authorized_keys \] || mv /tmp/tmp.txt /root/.ssh/authorized_keys\r" expect "]*" send "chmod 700 /root/.ssh; chmod 600 /root/.ssh/authorized_keys\r" expect "]*" send "exit\r" EOF check_ok /usr/bin/expect /usr/local/sbin/rsync_keys/rsync.expect $ip $password echo "OK,this script is successful. ssh $ip to test it"

【腳本101】自動封/解封ip

需求背景:

discuz論壇,天天有不少註冊機註冊的用戶,而後發垃圾廣告帖子。雖然使用了一些插件但沒有效果。分析訪問日誌,發現有幾個ip訪問量特別大,因此想到能夠寫個shell腳本,經過分析訪問日誌,把訪問量大的ip直接封掉。

可是這個腳本頗有可能誤傷,因此還須要考慮到自動解封這些ip。

思路:

  1. 能夠每分鐘分析1次訪問日誌,設定一個閾值,把訪問量大的ip用iptables封掉80端口
  2. 每20分鐘檢測一次已經被封ip的請求數據包數量,設定閾值,把沒有請求的或者請求量很小的解封

參考代碼:

#! /bin/bash ## To block the ip of bad requesting. ## Writen by aming 2017-11-18. log="/data/logs/www.xxx.com.log" tmpdir="/tmp/badip" #白名單ip,不該該被封 goodip="27.133.28.101" [ -d $tmpdir ] || mkdir -p $tmpdir t=`date -d "-1 min" +%Y:%H:%M` #截取一分鐘之前的日誌 grep "$t:" $log > $tmpdir/last_min.log #把一分鐘內日誌條數大於120的標記爲不正常的請求 awk '{print $1}' $tmpdir/last_min.log |sort -n |uniq -c |sort -n |tail |awk '$1>120 {print $2}'|grep -v "$good_ip"> $tmpdir/bad.ip d3=`date +%M` #每隔20分鐘解封一次ip if [ $d3 -eq "20" ] || [ $d3 -eq "40" ] || [ $d3 -eq "00" ] then /sbin/iptables -nvL INPUT|grep 'DROP' |awk '$1<10 {print $8}'>$tmpdir/good.ip if [ -s $tmpdir/good.ip ] then for ip in `cat $tmpdir/good.ip` do /sbin/iptables -D INPUT -p tcp --dport 80 -s $ip -j DROP d4=`date +%Y%m%d-%H:%M` echo "$d4 $ip unblock" >>$tmpdir/unblock.ip done fi #解封后,再把iptables的計數器清零 /sbin/iptables -Z INPUT fi if [ -s $tmpdir/bad.ip ] then for ip in `cat $tmpdir/bad.ip` do /sbin/iptables -A INPUT -p tcp --dport 80 -s $ip -j DROP d4=`date +%Y%m%d-%H:%M` echo "$d4 $ip block" >>$tmpdir/block.ip done fi

【腳本102】單機部署SpringBoot項目

有一臺測試服務器,常常須要部署SpringBoot項目,手動部署太麻煩,因而寫了個部署腳本

腳本代碼:

#!/bin/bash # git倉庫路徑 GIT_REPOSITORY_HOME=/app/developer/git-repository # jar包發佈路徑 PROD_HOME=/prod/java-back # 應用列表 APPS=(app1 app2 app3) if [ ! -n "$1" ] then echo -e "請輸入要發佈的項目!" exit fi # cd dir for((i=0;i<${#APPS[@]};i++)) do echo $1 ${APPS[i]} if [ $1 = ${APPS[i]} ] then echo -e ===========Enter $1============= cd ${GIT_REPOSITORY_HOME}/$1 break fi done if [ `pwd` != ${GIT_REPOSITORY_HOME}/$1 ] then echo -e "輸入的項目名沒有找到!" exit fi echo "==========git切換分之到master===============" git checkout master echo "==================git fetch======================" git fetch echo "==================git pull======================" git pull echo "===========選擇線上環境編譯並跳過單元測試====================" mvn clean package -Dmaven.test.skip=true -Pprod jar_path=${GIT_REPOSITORY_HOME}/$1/target/*-0.0.1-SNAPSHOT.jar echo ${jar_path} if [ -f ${jar_path} ] then # backup dest echo -e "===========jar backup=============" mv ${PROD_HOME}/$1/*-0.0.1-SNAPSHOT.jar ${PROD_HOME}/$1/$1-0.0.1-SNAPSHOT.jar.back # copy echo "======拷貝編譯出來的jar包拷貝到$PROD_HOME=======" if [ -d ${PROD_HOME}/$1 ] then /bin/cp ${GIT_REPOSITORY_HOME}/$1/target/*-0.0.1-SNAPSHOT.jar ${PROD_HOME}/$1 else mkdir ${PROD_HOME}/$1 /bin/cp ${GIT_REPOSITORY_HOME}/$1/target/*-0.0.1-SNAPSHOT.jar ${PROD_HOME}/$1 fi echo "============中止項目=============" jar_name=`jps |awk -F" " '{ print $2 }'| egrep ^$1.*jar$` pid=`jps |grep ${jar_name} | awk -F" " '{ print $1 }'` echo ${pid} kill -15 ${pid} echo "================sleep 10s=========================" for i in 1 2 3 4 5 6 7 8 9 10 do echo ${i}"s" sleep 1s done echo "============啓動項目=============" nohup java -jar ${PROD_HOME}/$1/*-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 & echo -e "===========Deploy Success=============" else echo -e "===========Deploy Error=============" fi

【轉】自