注意: 命令後面必定要有分號;mysql
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的統計數據,請看後文慢慢道來。web
time命令最經常使用的使用方式就是在其後面直接跟上命令和參數:sql
time <command> [<arguments...>]shell
在命令執行完成以後就會打印出CPU的使用狀況:緩存
real 0m5.064s <== 實際使用時間(real time)
user 0m0.020s <== 用戶態使用時間(the process spent in user mode)
sys 0m0.040s <== 內核態使用時間(the process spent in kernel mode)bash
time命令跟上-p參數能夠只打印時間數值(秒數),不打印單位。app
[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.sh
real 0m14.837s
user 0m0.030s
sys 0m0.120s
[root@web186 root]#ide
注:real遠大於user加上sys,由於find須要遍歷各個目錄,須要大量的I/O操做,而磁盤I/O一般是最慢的環節,所以大部分時間find進程都在等待磁盤I/O完成。ui
[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.sh
real 0m0.230s
user 0m0.040s
sys 0m0.030sthis
注:再次運行的時候,發現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.sh
real 0.15
user 0.04
sys 0.03
注:使用-p參數時,直接打印所需時間的數值,單位爲秒,而不是更友好的格式,包括分鐘、秒鐘的顯示方式。
[root@web186 root]#
看過手冊頁的朋友,會發現有個-f參數能夠來指定統計信息的輸出格式,咱們也來試一下。
[root@web186 root]# time -f "real %f\nuser %f\nsys %f\n" find . -name "mysql.sh"
-bash: -f: command not found
real 0m0.024s
user 0m0.000s
sys 0m0.000s
怪哉,不靈啊。使用type -a來看一下。使用這個shell內建命令常常會有意想不到的發現。
[root@web186 root]# type -a time
time is a shell keyword
time is /usr/bin/time
注:經過這條命令咱們能夠發現咱們經常使用的time實際上是一個Shell關鍵字,還有一個外部命令/usr/bin/time,它有何不一樣呢?
[root@web186 root]# /usr/bin/time
Usage: /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.sh
0.03user 0.04system 0:00.12elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+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命令的輸出信息是打印在標準錯誤輸出上的, 咱們經過一個簡單的嘗試來驗證一下。
[root@web186 root]# time find . -name "mysql.sh" >1.txt
real 0m0.081s
user 0m0.060s
sys 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.sh
real 0m0.068s
user 0m0.040s
sys 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.txt
real 0m0.068s
user 0m0.030s
sys 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.txt
real 0m0.083s
user 0m0.040s
sys 0m0.020s
[root@web186 root]#
第二種方式的嘗試也成功了,總結起來就是 (time command-line) 2>file 這裏time緊貼着小括號(也能夠的,命令行結束也沒必要帶分號。固然最好仍是用第一種方式,畢竟啓動一個子shell是要多佔些資源的。
1. 爲何執行find命令的屢次時間統計差異很大,一次實際時間須要12秒,另外幾回卻不足1秒?