用途說明time命令經常使用於測量一個命令的運行時間,注意不是用來顯示和修改系統時間的(這是date命令乾的事情)。可是今天我經過查看time命令的手冊頁,發現它能作的不只僅是測量運行時間,還能夠測量內存、I/O等的使用狀況,手冊頁上的說法是time a simple command or give resource usage,其中time一詞我認爲它應該是測量或測定的意思,並不單指時間。一個程序在運行時使用的系統資源一般包括CPU、Memory和I/O等,其中CPU資源的統計包括實際使用時間(real time)、用戶態使用時間(the process spent in user mode)、內核態使用時間(the process spent in kernel mode)。可是簡單的使用time命令並不能獲得內存和I/O的統計數據,請看後文慢慢道來。經常使用參數time命令最經常使用的使用方式就是在其後面直接跟上命令和參數:time <command> [<arguments...>]在命令執行完成以後就會打印出CPU的使用狀況:real 0m5.064s <== 實際使用時間(real time)user 0m0.020s <== 用戶態使用時間(the process spent in user mode)sys 0m0.040s <== 內核態使用時間(the process spent in kernel mode)time命令跟上-p參數能夠只打印時間數值(秒數),不打印單位。使用示例示例一 統計運行時間[root@web186 root]# time find . -name "mysql.sh"./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.shreal 0m14.837suser 0m0.030ssys 0m0.120s[root@web186 root]#注:real遠大於user加上sys,由於find須要遍歷各個目錄,須要大量的I/O操做,而磁盤I/O一般是最慢的環節,所以大部分時間find進程都在等待磁盤I/O完成。[root@web186 root]# time find . -name "mysql.sh"./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.shreal 0m0.230suser 0m0.040ssys 0m0.030s注:再次運行的時候,發現real time變得很小了,應該是操做系統將剛纔操做過的一些文件緩存了的緣故,於是大大減小了磁盤I/O。[root@web186 root]# time -p find . -name "mysql.sh"./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.shreal 0.15user 0.04sys 0.03注:使用-p參數時,直接打印所需時間的數值,單位爲秒,而不是更友好的格式,包括分鐘、秒鐘的顯示方式。[root@web186 root]#示例二 Linux系統中time命令其實不止一個看過手冊頁的朋友,會發現有個-f參數能夠來指定統計信息的輸出格式,咱們也來試一下。[root@web186 root]# time -f "real %f\nuser %f\nsys %f\n" find . -name "mysql.sh" -bash: -f: command not foundreal 0m0.024suser 0m0.000ssys 0m0.000s怪哉,不靈啊。使用type -a來看一下。使用這個shell內建命令常常會有意想不到的發現。[root@web186 root]# type -a timetime is a shell keywordtime is /usr/bin/time注:經過這條命令咱們能夠發現咱們經常使用的time實際上是一個Shell關鍵字,還有一個外部命令/usr/bin/time,它有何不一樣呢?[root@web186 root]# /usr/bin/timeUsage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose] [--portability] [--format=format] [--output=file] [--version] [--help] command [arg...]注:外部命令/usr/bin/time功能更強大,下面來嘗試一下。[root@web186 root]# /usr/bin/time find . -name "mysql.sh"./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.sh0.03user 0.04system 0:00.12elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k0inputs+0outputs (154major+63minor)pagefaults 0swaps注:注意後面兩行,打印了不少信息,但看不太清楚。它有一個參數-v,能夠打印得更清楚些。[root@web186 root]# /usr/bin/time -v find . -name "mysql.sh"./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.sh Command being timed: "find . -name mysql.sh" User time (seconds): 0.03 System time (seconds): 0.05 Percent of CPU this job got: 47% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.17 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 0 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 153 Minor (reclaiming a frame) page faults: 64 Voluntary context switches: 0 Involuntary context switches: 0 Swaps: 0 File system inputs: 0 File system outputs: 0 Socket messages sent: 0 Socket messages received: 0 Signals delivered: 0 Page size (bytes): 4096 Exit status: 0[root@web186 root]#嘗試完這個以後,我看了一下Google搜索的結果,發現有位大蝦早已發現了這個祕密,見相關資料【1】。示例三 解決time命令輸出信息的重定向問題time命令的輸出信息是打印在標準錯誤輸出上的, 咱們經過一個簡單的嘗試來驗證一下。[root@web186 root]# time find . -name "mysql.sh" >1.txtreal 0m0.081suser 0m0.060ssys 0m0.020s[root@web186 root]# time find . -name "mysql.sh" 2>2.txt./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.shreal 0m0.068suser 0m0.040ssys 0m0.030s經過上面的嘗試,發現沒法將time的輸出信息重定向到文件裏面,爲何?由於time是shell的關鍵字,shell作了特殊處理,它會把time命令後面的命令行做爲一個總體來進行處理,在重定向時,其實是針對後面的命令來的,time命令自己的輸出並不會被重定向的。那如今怎麼辦呢?網上提供了兩種解決方法【2,3】,咱們一一嘗試一下。第一種解決方法,就是將time命令和將要執行的命令行放到一個shell代碼塊中,也就是一對大括號中,要注意空格和分號的使用。[root@web186 root]# {time find . -name "mysql.sh"} 2>2.txt好像成功了。慢,看一下對不對。[root@web186 root]# cat 2.txt-bash: {time: command not found原來bash把 {time 做爲一個總體來處理了,先後都加上空格試試。[root@web186 root]# { time find . -name "mysql.sh" } 2>2.txt> Ctrl+C此次Bash認爲命令都沒有輸入完成,少了分號。由於Bash認爲後面的 } 是find命令的參數。[root@web186 root]# { time find . -name "mysql.sh"; } 2>2.txt./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.sh[root@web186 root]# cat 2.txtreal 0m0.068suser 0m0.030ssys 0m0.040s第一種方式的嘗試成功了,總結起來就是 { time command-line; } 2>file 注意分隔符的使用。另一種方式就是使用子Shell的方式,以下所示:[root@web186 root]# (time find . -name "mysql.sh") 2>2.txt./work186/sms/bin/mysql.sh./work186/sms/src/scripts/mysql.sh./work186/sms/src/scripts1/mysql.sh./work186/sms1/bin/mysql.sh./work186/sms1/src/scripts/mysql.sh./temp/sms/bin/mysql.sh./temp/sms/src/scripts/mysql.sh[root@web186 root]# cat 2.txtreal 0m0.083suser 0m0.040ssys 0m0.020s[root@web186 root]#第二種方式的嘗試也成功了,總結起來就是 (time command-line) 2>file 這裏time緊貼着小括號(也能夠的,命令行結束也沒必要帶分號。固然最好仍是用第一種方式,畢竟啓動一個子shell是要多佔些資源的。問題思考1. 爲何執行find命令的屢次時間統計差異很大,一次實際時間須要12秒,另外幾回卻不足1秒?相關資料【1】孵夢森林 Linux中的兩個time【2】Nine Rivers 重定向 Bash 「time」 命令的輸出【3】seizeF的專欄 重定向Bash命令——timehttp://codingstandards.javaeye.com/blog/798788