日常利器,shell腳本統計數據


前言

最近就干了兩件有意思的事,昨天分享了一個,今天我們來分享另一個——shell腳本統計數據。

相比於pythonshell是另一種特別常用,特別實用,也特別基礎的腳本語言,基本上所有的linux系統都支持shell,更准確地說,shell讓系統運行更方便,是shelllinux更強大,所以學習一些基本的shell語法,可以簡化linux的運維工作,提升我們的工作效率。

其實,win平台也是有它的shell的,也就是bat或者cmd腳本,通過這些腳本,我們同樣也可以做很多事,等下我們也分享一些win平台的常用腳本,讓各位小伙伴見識下腳本語言的魅力。

好了,廢話少說,下面我們開始編寫數據統計腳本。

shell腳本統計數據

在開始之前,我們先看下shell的相關內容。shell通俗來講就是我們通常說的CMDcommond,也叫命令行),通過shell我們可以直接與操作系統內核進行溝通。

至於為什么叫shell,也很好理解,shell的中文名稱是殼,而kernel是操作系統的核心,核心是需要和外側進行隔離的,通過什么來隔離呢,就是通過殼(shell),而且shell還要充當核心與外界溝通的信使。

當然shell本身也有好多種:

  • /bin/sh:已經被/bin/bash所取代
  • /bin/bashLinux預設的shell
  • /bin/tcsh:整合C shell,提供更多的功能
  • /bin/csh:已經被/bin/tcsh所取代
  • /bin/zsh:自動補全功能很強大,檢查拼寫功能很強大,因為oh-my-zsh名聲大噪,而且可定制性比bash更高

如果是日常使用的話,推薦實用zsh,但是如果是寫腳本的話,建議用bash,畢竟它是linux的預裝shell

簡單介紹

下面是最簡單的shell腳本:

#!/bin/bash
echo "hello shell"

結合我們上面shell的相關知識,我們可以推測出第一行是標記shell類別的,也就是用哪種shell來解釋腳本;從第二行開始就是腳本的內容了。

運行這個腳本之后會在telminal控制台打印輸出hello shell字符串:

shell腳本基本要點
  • linux系統的shell腳本文件后綴是.sh,也就是shell的簡寫。

  • shell腳本的注釋方式是# 注釋內容linux平台絕大多數的配置文件都是采用這種方式進行注釋的:

    #!/bin/bash
    # 我是腳本注釋
    eacho "hello shell"
    
  • shell腳本有兩種運行方式

    第一種是:

# 腳本名稱hello.sh
sh hello.sh
# 或者
bash hello.sh

​ 第二種方式是:

./hello.sh

雖然這兩種方式都可以運行,但是第二種方式需要給腳本增加運行權限,具體命令如下:

chmod u+x hello.sh

u表示所屬用戶,+x表示增加運行權限,所以執行上面的這行命令,這個腳本就有了運行權限,然后再通過./hello.sh運行即可。

關於sh腳本的基礎知識我們就先分享這么多,想系統學習的小伙伴可以去看下《鳥叔的Linux私房菜》,里面關於shell script講的還是比較系統的,而且很全面,這本書也算是linux的中文聖經了。

編寫統計腳本

下面這段腳本執行的操作很簡單,首先是查詢了db庫配置庫,並將結果寫入到connect_info文件中,拿到查詢結果之后,循環遍歷,然后再次組裝sql查詢我們要統計的數據,並將數據寫入count_data,之后我們就可以通過awksorthead等命令對結果進行解析、排序,最終拿到我們想要的結果。

 #!/bin/bash
 # mysql數據庫配置信息
 # 數據庫端口
 port=3306
 # 數據庫用戶名
 user="root"
 # 數據庫密碼
 pawd="root"
 # 數據庫地址
 host="192.168.1.105"
 # 庫名
 db_name="exam_system"
 # 查詢數據庫連接信息
 select_sql="select id, db_server, db_source_name from db_config"
 # 統計sql
 count_sql="select count(*) from question_option_info where question_id in (select id from question_info where type = 5 ) and CHAR_LENGTH(title) >= 50"
 # 命令行連接mysql,並執行sql,這里我將查詢結果輸出到connect_info文件中
 mysql -h "${host}" -P "${post}" -u"${user}" -p"${pawd}" -D${db_name} -N -s -e "${select_sql}" >connect_info
 
 # 循環遍歷
 while read line
 do
   # 獲取連接信息中的數據
   config_id=`echo "$line"|cut -f1`
   db_server=`echo "$line"|cut -f2`
   db_name=`echo "$line"|cut -f3`
   #mysql -h "${db_server}" -P "${port}" -u"${user}" -p"${pawd}" -D${db_name} -N -s -e "${count_sql}">>count_data
   result=`mysql -h "${host}" -P "${port}" -u"${user}" -p"${pawd}" -D${db_name} -N -s -e "${count_sql}"`
   echo "${config_id} ${result}" >> count_data 
 done < connect_info

這里我們簡單解釋下這段腳本,4~16行我們分別定義了7個變量,sh腳本定義變量的方式和python有點像,都不需要指定數據類型;

mysql命令參數

18行我們執行了一個mysql的命令,這行命令的作用是連接mysql並執行sql語句,-e表示執行並退出,后面直接跟sql語句,會直接打印sql,執行完成后會打印sql結果:

我以前真不知道還有這種操作方式,不是這次統計數據,應該不會去了解。

-s表示以制表符分割顯示結果,不加這個參數的話,結果會包括|,也就是我們通常看到的結果:

不加-s查詢結果如下:

加了-s顯示結果如下:

-N參數的作用是隱藏字段名稱,也就是title(加上這個參數可以保證我們查詢結果只有數據):

sh腳本要點

sh腳本中,將運行結果輸出到文件中有兩種方式,一種是>,另一種是>>,兩者的區別是,前者會覆寫文件中的內容,而后者是在文件中追加(如果文件中已經存在內容,則會在原有內容后面追加新的內容),這種操縱在sh中很普遍,比如:

# 將 ls 結果輸出到文件中
ls /home/syske > file_list
# 將當前時間輸出到文件中,每次追加
date >> date_list

<>剛好相反,是將文件的內容讀取出來,比如:

 # 讀取 date_list
 cat < date_list

另外除了直接將命令結果輸出,我們還可以用變量接收運行結果:

result=`mysql -h "${host}" -P "${port}" -u"${user}" -p"${pawd}" -D${db_name} -N -s -e "${count_sql}"`

比如上面這行sh代碼就是用result接收mysql的運行結果,需要注意的是命令必須通過( ` )進行包裝,否則命令無法運行。這種方式有個好處,就是可以對結果進行處理,比如拼接變量:

 echo "${config_id} ${result}"

運行結果處理

拿到運行結果之后,我們可以通過awksort等命令進行處理,以拿到最終數據。比如我們的查詢結果如下:

Sun Nov  7 16:59:54 CST 2021
Sun Nov  7 16:59:57 CST 2021
Sun Nov  7 16:59:58 CST 2021

如果是通過awk處理,則可以直接幫我們將數據分割成:sunNov716:59:54CST2021這樣的格式,而且很簡單:

 awk '{print $1, $2, $3, $4, $5, $6}' date_list

這里的$1表示分割的第一部分,也就是Sun,其他以此類推;$0表示原始數據

排序的話,可以用sort命令進行操作:

awk '{print $1, $2, $3, $4, $5, $6}' date_list | sort -rk 4

排序結果如下:

其中-r表示降序排序,默認是正序排序,-k表示按指定序列排序,4表示按第四列排序,也就是按時間排序。更多其他排序可以參考sort文檔。

最后再補充點akw的常用操作命令:

  • 求和
cat data|awk '{sum+=$1} END {print "Sum = ", sum}'
  • 求平均
cat data|awk '{sum+=$1} END {print "Average = ", sum/NR}'
  • 求最大值
cat data|awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}'
  • 求最小值(min的初始值設置一個超大數即可)
awk 'BEGIN {min = 1999999} {if ($1<min) min=$1 fi} END {print "Min=", min}'

擴展知識

這里再分享win環境下的幾個常用命令:

  • 關機操作:
# 休眠操作
shutdown /h
# 重啟
shutdown /r
# 定時關閉(兩小時后關機,單位秒)
shutdown /s /t 3600
  • 顯示指定文件夾下的所有內容,包括文件和子文件夾:
dir /b/s ./
  • 顯示指定文件夾樹形結構:
tree ./

另外,我們前面說了,win平台也支持>>>,這樣我們就可以把上面命令的結果輸出到文件中:

dir /b/s ./ > file_list.log
tree ./ >> struts.log
  • 批量修改文件后綴(文件名)

    # 修改文件擴展名
    ren *.gif *.jpg
    # 或者(ren和rename等同)
    rename *.gif *.jpg
    # 修改文件名
    ren *.gif *-syske.gif
    
  • 批量刪除文件

# 我經常通過這樣的方式刪除重復文件
del *(1).jpg

結語

shell腳本統計數據的內容我們就分享這么多,核心知識點包括shell的基本語法、linux的常用命令等,總體的內容難點並不大,如果實際工作中遇到了類似的需求,各位小伙伴可以參考。

最后,還想多說兩句。在我的理解中,我覺得一切工具都可以變成生產力工具,最關鍵的還是要學會活學活用,養成一個善於動腦的小可愛,這樣才能避免低效重復工作,有時候同樣的工具,關鍵在於你如何用,你是否能夠發現它的價值點,現實中的栗子有很多,比如回形針的一百種用法。

當然,實際工作中也會遇到很多類似的問題,比如你現在需要修改一批線上數據(400多條),數據的條件和更新內容各不相同,你能想到那些處理方式?通過編輯器批量修改?還是手工一條一條修改?還是借助其他工具,pythonexcel?上周五我就完成了這樣的工作,最終通過excel生成update sql,通過文本編輯器批量插入和替換拼接緩存key,最后完成相關數據修改。我說這個例子是希望各位小伙伴在學習和實踐的時候,要學會發散思維,不要被當前的語言、環境、方法所局限,要學會解決問題,學會知識的橫向應用,橫向思考。好了,今天廢話有點多,各位小伙伴,晚安吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM