Linux Shell腳本經(jīng)典案例(二)

11.統(tǒng)計 /proc 目類下 Linux 進程相關(guān)數(shù)量信息,輸出總進程數(shù),running 進程數(shù)贿衍,stoped 進程數(shù),sleeing 進程數(shù)在扰,zombie 進程數(shù)胚股。
【輸出所有 zombie 的進程到 zombie.txt 殺死所有 zombie 進程】

#!/bin/bash
ALL_PROCESS=$(ls /proc/ | egrep '[0-9]+')
running_count=0
stoped_count=0
sleeping_count=0
zombie_count=0
for pid in ${ALL_PROCESS[*]}
do
    test -f /proc/$pid/status && state=$(egrep "State" /proc/$pid/status | awk '{print $2}')
    case "$state" in
R)
running_count=$((running_count+1))
;;
T)
stoped_count=$((stoped_count+1))
;;
S)
sleeping_count=$((sleeping_count+1))
;;
Z)
zombie_count=$((zombie_count+1))
echo "$pid" >>zombie.txt
kill -9 "$pid"
;;
esac
done
echo -e "total:
$((running_count+stoped_count+sleeping_count+zombie_count))\nrunning:
$running_count\nstoped: $stoped_count\nsleeping: $sleeping_count\nzombie:
$zombie_count"

12.12.把當前目錄(包含子目錄)下所有后綴為 ".sh" 的文件后綴變更為 ".shell",之后刪除每個文件的第二行士八。

#!/bin/bash
ALL_SH_FILE=$(find .-type f -name "*.sh")
for file in ${ALL_SH_FILE[*]}
do
filename=$(echo $file | awk -F'.sh' '{print $1}')
new_filename="${filename}.shell"
mv "$file" "$new_filename"
sed -i '2d' "$new_filename"
done

13.判斷目錄 /tmp/jstack 是否存在容燕,不存在則新建一個目
錄,若存在則刪除目錄下所有內(nèi)容婚度。
【每隔 1 小時打印 inceptor server 的 jstack 信息蘸秘,并以 jstack_${當前時間} 命名文件,每當目錄下超過10 個文件后陕见,刪除最舊的文件】

#!/bin/bash
DIRPATH='/tmp/jstack'
CURRENT_TIME=$(date +'%F'-'%H:%M:%S')
if [ ! -d "$DIRPATH" ];then
      mkdir "$DIRPATH"
else
      rm -rf "$DIRPATH"/*
fi
      cd "$DIRPATH"
while true
do
    sleep 3600
    # 這里需要將inceptor改后自己的java進程名稱
    pid=$(ps -ef | grep 'inceptor' | grep -v grep | awk '{print $2}')
    jstack $pid >> "jstack_${CURRENT_TIME}"
    dir_count=$(ls | wc -l)
    if [ "$dir_count"-gt 10 ];then
        rm -f $(ls -tr | head -1)
    fi
done

14.從 test.log 中截取當天的所有 gc 信息日志秘血,并統(tǒng)計 gc
時間的平均值和時長最長的時間。

#!/bin/bash
awk '{print $2}' hive-server2.log | tr -d ':' | awk '{sum+=$1} END {print "avg:
", sum/NR}' >>capture_hive_log.log
awk '{print $2}' hive-server2.log | tr -d ':' | awk '{max = 0} {if ($1+0 > max+0)
max=$1} END {print "Max: ", max}'>>capture_hive_log.log

15.查找 80 端口請求數(shù)最高的前 20 個 IP 地址评甜,判斷中間最小的請求數(shù)是否大于 500灰粮,如大于 500,則輸出系統(tǒng)活動情況報告到 alert.txt忍坷,如果沒有粘舟,則在 600s 后重試熔脂,直到有輸出為止。

#!/bin/bash
state="true"
while $state
do
    SMALL_REQUESTS=$(netstat -ant | awk -F'[ :]+' '/:22/{count[$4]++} END {for(ip in count) print count[ip]}' | sort -n | head -20 | head -1)
    if [ "$SMALL_REQUESTS" -gt 500 ];then
          sar -A > alert.txt
          state="false"
      else
          sleep 6
          continue
fi

16.將當前目錄下大于 10K 的文件轉(zhuǎn)移到 /tmp 目錄柑肴,再按
照文件大小順序霞揉,從大到小輸出文件名

#!/bin/bash
# 目標目錄
DIRPATH='/tmp'
# 查看目錄
FILEPATH='.'
find "$FILEPATH"  -size +10k -type f | xargs -i mv {} "$DIRPATH"
ls -lS "$DIRPATH" | awk '{if(NR>1) print $NF}'

17.企業(yè)微信告警
【此腳本通過企業(yè)微信應用,進行微信告警晰骑,可用于 Zabbix 監(jiān)控适秩。

# -*- coding: utf-8 -*-
import requests
import json
class DLF:
    def__init__(self, corpid, corpsecret):
        self.url ="https://qyapi.weixin.qq.com/cgi-bin"
        self.corpid = corpid
        self.corpsecret = corpsecret
        self._token = self._get_token()
def_get_token(self):
        '''
        獲取企業(yè)微信API接口的access_token
        :return:
        '''
        token_url = self.url + "/gettoken?corpid=%s&corpsecret=%s" %(self.corpid,
self.corpsecret)
try:
        res = requests.get(token_url).json()
        token = res['access_token']
        return token
except Exception as e:
        return str(e)
    def_get_media_id(self, file_obj):
        get_media_url = self.url + "/media/upload?access_token={}&type=file"
.format(self._token)
     data = {"media": file_obj}
    try:
        res = requests.post(url=get_media_url, files=data)
        media_id = res.json()['media_id']
        return media_id
    except Exception as e:
        return str(e)
  def send_text(self, agentid, content, touser=None, toparty=None):
        send_msg_url = self.url + "/message/send?access_token=%s" %
(self._token)
send_data = {
    "touser": touser,
    "toparty": toparty,
    "msgtype": "text",
    "agentid": agentid,
"text": {
        "content": content
    }
}
try:
      res = requests.post(send_msg_url, data=json.dumps(send_data))
    except Exception as e:
      return str(e)
def send_image(self, agentid, file_obj, touser=None, toparty=None):
    media_id = self._get_media_id(file_obj)
    send_msg_url = self.url + "/message/send?access_token=%s" %
(self._token)
    send_data = {
        "touser": touser,
        "toparty": toparty,
        "msgtype": "image",
        "agentid": agentid,
        "image": {
              "media_id": media_id
          }
      }
try:
      res = requests.post(send_msg_url, data=json.dumps(send_data))
except Exception as e:
    return str(e)

18.FTP 客戶端
通過 ftplib 模塊操作 ftp 服務器,進行上傳下載等操作硕舆。

# -*- coding: utf-8 -*-
from ftplib import FTP
from os import path
import copy
class FTPClient:
      def__init__(self, host, user, passwd, port=21):
          self.host = host
          self.user = user
          self.passwd = passwd
          self.port = port
          self.res = {'status': True, 'msg': None}
          self._ftp = None
          self._login()
def_login(self):
'''
登錄FTP服務器
:return: 連接或登錄出現(xiàn)異常時返回錯誤信息
'''
try:
        self._ftp = FTP()
        self._ftp.connect(self.host, self.port, timeout=30)
        self._ftp.login(self.user, self.passwd)
except Exception as e:
        return e
def upload(self, localpath, remotepath=None):
'''
上傳ftp文件
:param localpath: local file path
:param remotepath: remote file path
:return:
'''
if not localpath: return 'Please select a local file. '
# 讀取本地文件
# fp = open(localpath, 'rb')
# 如果未傳遞遠程文件路徑秽荞,則上傳到當前目錄,文件名稱同本地文件
if not remotepath:
      remotepath = path.basename(localpath)
# 上傳文件
      self._ftp.storbinary('STOR ' + remotepath, localpath)
# fp.close()
def download(self, remotepath, localpath=None):
'''
localpath
:param localpath: local file path
:param remotepath: remote file path
:return:
'''
if not remotepath: return 'Please select a remote file. '
# 如果未傳遞本地文件路徑抚官,則下載到當前目錄扬跋,文件名稱同遠程文件
if not localpath:
        localpath = path.basename(remotepath)
# 如果localpath是目錄的話就和remotepath的basename拼接
if path.isdir(localpath):
        localpath = path.join(localpath, path.basename(remotepath))
# 寫入本地文件
fp = open(localpath, 'wb')
# 下載文件
self._ftp.retrbinary('RETR ' + remotepath, fp.write)
fp.close()
def nlst(self, dir='/'):
'''
查看目錄下的內(nèi)容
:return: 以列表形式返回目錄下的所有內(nèi)容
'''
files_list = self._ftp.nlst(dir)
return files_list
def rmd(self, dir=None):
'''
刪除目錄
:param dir: 目錄名稱
:return: 執(zhí)行結(jié)果
'''
if not dir: return 'Please input dirname'
res = copy.deepcopy(self.res)
try:
      del_d = self._ftp.rmd(dir)
       res['msg'] = del_d
except Exception as e:
      res['status'] = False
       res['msg'] = str(e)
      return res
def mkd(self, dir=None):
'''
創(chuàng)建目錄
:param dir: 目錄名稱
:return: 執(zhí)行結(jié)果
'''
if not dir: return 'Please input dirname'
res = copy.deepcopy(self.res)
try:
        mkd_d = self._ftp.mkd(dir)
        res['msg'] = mkd_d
    except Exception as e:
        res['status'] = False
        res['msg'] = str(e)
return res
def del_file(self, filename=None):
'''
刪除文件
:param filename: 文件名稱
:return: 執(zhí)行結(jié)果
'''
if not filename: return 'Please input filename'
res = copy.deepcopy(self.res)
try:
      del_f = self._ftp.delete(filename)
      res['msg'] = del_f
except Exception as e:
      res['status'] = False
      res['msg'] = str(e)
return res
def get_
file_size(self, filenames=[]):
'''
獲取文件大小,單位是字節(jié)
判斷文件類型
:param filename: 文件名稱
:return: 執(zhí)行結(jié)果
'''
if not filenames: return {'msg': 'This is an empty directory'}
res_l = []
for file in filenames:
    res_d = {}
    # 如果是目錄或者文件不存在就會報錯
try:
    size = self._ftp.size(file)
    type ='f'
except:
    # 如果是路徑的話size顯示 -, file末尾加/ (/dir/)
  size ='-'
   type ='d'
    file = file + '/'
res_d['filename'] = file
res_d['size'] = size
res_d['type'] = type
res_l.append(res_d)
return res_l
def rename(self, old_name=None, new_name=None):
:param new
_
name: 新的文件或者目錄名稱
:return: 執(zhí)行結(jié)果
'''
if not old_name or not new_name: return 'Please input old_name and new_name'
res = copy.deepcopy(self.res)
try:
rename_f = self._ftp.rename(old_name, new_name)
res['msg'] = rename_f
except Exception as e:
res['status'] = False
res['msg'] = str(e)
return res
def close(self):
'''
退出ftp連接
:return:
'''
try:
# 向服務器發(fā)送quit命令
self.
_
ftp.quit()
except Exception:
return 'No response from server'
finally:
# 客戶端單方面關(guān)閉連接
self._ftp.close()
'''

19.SSH 客戶端
此腳本僅用于通過 key 連接,如需要密碼連接凌节,簡單修改下即可钦听。

-- coding: utf-8 --

import paramiko
class SSHClient:
def__init__(self, host, port, user, pkey):
self.ssh_host = host
self.ssh_port = port
self.ssh_user = user
self.private_key = paramiko.RSAKey.from_private_key_file(pkey)
self.ssh = None
self._connect()
def_connect(self):
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.ssh.connect(hostname=self.ssh_host, port=self.ssh_port,
username=self.ssh_user, pkey=self.private_key, timeout=10)
except:
return 'ssh connect fail'
def execute_command(self, command):
stdin, stdout, stderr = self.ssh.exec_command(command)
out = stdout.read()
err = stderr.read()
return out, err
def close(self):
self.ssh.close()

20.Saltstack 客戶端

通過 api 對 Saltstack 服務端進行操作,執(zhí)行命令倍奢。

!/usr/bin/env python

-- coding:utf-8 --

import requests
import json
import copy
class SaltApi:
"""
定義salt api接口的類
初始化獲得token
"""
def__init__(self):
self.url ="http://172.85.10.21:8000/"
self.username = "saltapi"
self.password = "saltapi"
self.headers = {"Content-type": "application/json"}
self.params = {'client': 'local', 'fun': None, 'tgt': None, 'arg': None}
self.login_url = self.url + "login"
self.login_params = {'username': self.username, 'password': self.password,
'eauth': 'pam'}
self.token = self.get_data(self.login_url, self.login_params)['token']
self.headers['X-Auth-Token'] = self.token
def get_data(self, url, params):
'''
請求url獲取數(shù)據(jù)
:param url: 請求的url地址
:param params: 傳遞給url的參數(shù)
:return: 請求的結(jié)果
'''
send_data = json.dumps(params)
request = requests.post(url, data=send_data, headers=self.headers)
response = request.json()
result = dict(response)
return result['return'][0]
def get_auth_keys(self):
'''
獲取所有已經(jīng)認證的key
:return:
'''
data = copy.deepcopy(self.params)
data['client'] = 'wheel'
data['fun'] ='key.list_all'
result = self.get_data(self.url, data)
try:
return result['data']['return']['minions']
except Exception as e:
return str(e)
def get_grains(self, tgt, arg='id'):
"""
獲取系統(tǒng)基礎信息
:tgt: 目標主機
:return:
"""
data = copy.deepcopy(self.params)
if tgt:
data['tgt'] = tgt
else:
data['tgt'] = '*'
data['fun'] ='grains.item'
data['arg'] = arg
result = self.get_data(self.url, data)
return result

def execute_command(self, tgt, fun='cmd.run', arg=None, tgt_type='list',salt_async=False):
"""
執(zhí)行saltstack 模塊命令朴上,類似于salt '' cmd.run 'command'
:param tgt: 目標主機
:param fun: 模塊方法 可為空
:param arg: 傳遞參數(shù) 可為空
:return: 執(zhí)行結(jié)果
"""
data = copy.deepcopy(self.params)
if not tgt: return {'status': False, 'msg': 'target host not exist'}
if not arg:
data.pop('arg')
else:
data['arg'] = arg
if tgt != '
':
data['tgt_type'] = tgt_type
if salt_async: data['client'] = 'local_async'
data['fun'] = fun
data['tgt'] = tgt
result = self.get_data(self.url, data)
return result

def jobs(self, fun='detail', jid=None):
"""
任務
:param fun: active, detail
:param jod: Job ID
:return: 任務執(zhí)行結(jié)果
"""
data = {'client': 'runner'}
data['fun'] = fun
if fun == detail':
if not jid: return {'success': False, 'msg': 'job id is none'}
data['fun'] = 'jobs.lookup_jid' data['jid'] = jid
else:
return {'success': False, 'msg': 'fun is active or detail'}
result = self.get_data(self.url, data)

return result

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卒煞,隨后出現(xiàn)的幾起案子余指,更是在濱河造成了極大的恐慌,老刑警劉巖跷坝,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酵镜,死亡現(xiàn)場離奇詭異,居然都是意外死亡柴钻,警方通過查閱死者的電腦和手機淮韭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贴届,“玉大人靠粪,你說我怎么就攤上這事『硫荆” “怎么了占键?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長元潘。 經(jīng)常有香客問我畔乙,道長,這世上最難降的妖魔是什么翩概? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任牲距,我火速辦了婚禮返咱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牍鞠。我一直安慰自己咖摹,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布难述。 她就那樣靜靜地躺著萤晴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胁后。 梳的紋絲不亂的頭發(fā)上硫眯,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音择同,去河邊找鬼。 笑死净宵,一個胖子當著我的面吹牛敲才,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播择葡,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼紧武,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敏储?” 一聲冷哼從身側(cè)響起阻星,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎已添,沒想到半個月后妥箕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡更舞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年畦幢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缆蝉。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡宇葱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出刊头,到底是詐尸還是另有隱情黍瞧,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布原杂,位于F島的核電站印颤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏穿肄。R本人自食惡果不足惜膀哲,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一往产、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧某宪,春花似錦仿村、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衣迷,卻和暖如春畏鼓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壶谒。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工云矫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人汗菜。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓让禀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親陨界。 傳聞我的和親對象是個殘疾皇子巡揍,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容