一、linux的time命令-我们可以了解地更多
time命令看名字好像是和date一样查看时间的,但实际不是,linux自建的time命令是用于统计给定命令所花费的总时间。
[dev@user ~]$ ll
total 3016468
-rw-rw-r-- 1 onlinedev onlinedev 2990155079 Aug 23 2018 0809.log
[dev@user ~]$ time wc -l 0809.log
6945388 0809.log
real 0m0.865s
user 0m0.350s
sys 0m0.514s
#加上-p参数只显示时间秒数值(单位:秒)
[dev@user ~]$ time -p wc -l 0809.log
6945388 0809.log
real 0.77
user 0.31
sys 0.46
#上面的real time=后两者之后,下面的real time>后两者之和
[dev@user ~]$ time -p wc -l 0809.log
6945388 0809.log
real 0.83
user 0.31
sys 0.51
在程序中执行中经常要通过断点时间来统计用时,而time命令可以在命令行下方便地实现时间统计并且数据更细致。输出的信息分别显示了该命令所花费的real时间、user时间和sys时间。
实际使用时间(real time):指挂钟时间,也就是命令开始执行到结束的时间。这个短时间包括其他进程所占用的时间片,和进程被阻塞时所花费的时间。
用户态使用时间(the process spent in user mode):指进程花费在用户模式中的CPU时间,这是唯一真正用于执行进程所花费的时间,其他进程和花费阻塞状态中的时间没有计算在内。
内核态使用时间(the process spent in kernel mode):指花费在内核模式中的CPU时间,代表在内核中执系统调用所花费的时间,这也是真正由进程使用的CPU时间。
time统计的对象真正利用计算机进行计算的时间 即 CPU工作时间 = User+Sys (不包括IO).
为了隔离保护,使得系统更稳定。linux运行状态分为Kernel Mode 和 User Mode:
核心态(Kernel Mode):在内核态,代码拥有完全的,不受任何限制的访问底层硬件的能力。可以执行任意的CPU指令,访问任意的内存地址。内核态通常情况下,都是为那些最底层的,由操作系统提供的,可信可靠的代码来运行的。内核态的代码崩溃将是灾难性的,它会影响到整个系统。用户态(User Mode):在用户态,代码不具备直接访问硬件或者访问内存的能力,而必须借助操作系统提供的可靠的,底层的APIs来访问硬件或者内存。由于这种隔离带来的保护作用,用户态的代码崩溃(Crash),系统是可以恢复的。我们大多数的代码都是运行在用户态的。
从上面的数据以及感觉来看,好像real_time 一定会大于 user_time + sys_time,事实会不会真是这样?在单cpu的情况下,基本都是对的。但在多核cpu情况下,如果能把多核cpu都利用起来,这个关系就不一定成立了。上面使用的是shell内建的time命令,直接运行time命令时是调用的系统内建命令,内建time的功能很有限,比如不能重定向输出到日志中,如果需要使用time的更多功能,可以使用time命令的可执行二进制文件,下面使用type -a time查看并看一下time二进制文件的选项功能。
-o选项 将执行时间写入到文件中
-a选项 默认是覆盖在文件中,加上此期待则在文件中追加
-p选项 以秒为单位显示时间数据
-v选项 详细显示各项时间统计数据
-V选项 显示版本GNU time 1.7
-f选项 格式化时间输出,实际也就是在-v选项的结果中选择自己要显示的时间,-f选项后的参数:
参数 描述
%E real时间,显示格式为[小时:]分钟:秒
%U user时间。
%S sys时间。
%C 进行计时的命令名称和命令行参数。
%D 进程非共享数据区域,以KB为单位。
%x 命令退出状态。
%k 进程接收到的信号数量。
%w 进程被交换出主存的次数。
%Z 系统的页面大小,这是一个系统常量,不用系统中常量值也不同。
%P 进程所获取的CPU时间百分百,这个值等于user+system时间除以总共的运行时间。
%K 进程的平均总内存使用量(data+stack+text),单位是KB。
%w 进程主动进行上下文切换的次数,例如等待I/O操作完成。
%c 进程被迫进行上下文切换的次数(由于时间片到期)。
#使用type -a time查看
[dev@user ~]$ type -a time
time is a shell keyword
time is /usr/bin/time
[dev@user ~]$ /usr/bin/time --help
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
[--portability] [--format=format] [--output=file] [--version]
[--help] command [arg...]
#/usr/bin/time直接计算了CPU的利用率及更多信息
[dev@user ~]$ /usr/bin/time wc -l 0809.log
6945388 0809.log
0.30user 0.51system 0:00.82elapsed 99%CPU (0avgtext+0avgdata 632maxresident)k
0inputs+0outputs (0major+189minor)pagefaults 0swaps
#使用-o选项可以将显示结果单独记录在文件中
[dev@user ~]$ /usr/bin/time -o dotime.log wc -l 0809.log
6945388 0809.log
[dev@user ~]$ cat dotime.log
0.33user 0.45system 0:00.79elapsed 99%CPU (0avgtext+0avgdata 628maxresident)k
0inputs+0outputs (0major+191minor)pagefaults 0swaps
[dev@user ~]$ /usr/bin/time -v wc -l 0809.log
6945388 0809.log
Command being timed: "wc -l 0809.log"
User time (seconds): 0.32
System time (seconds): 0.44
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.77
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): 632
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 191
Voluntary context switches: 1
Involuntary context switches: 2
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
#使用-f选项只显示某个时间
[dev@user ~]$ /usr/bin/time -f "time: %U" wc -l 0809.log
6945388 0809.log
time: 0.36
直接使用time命令如果想将结果写到日志文件中去行不通,如下所示。需要将time命令放在代码块{}中如下,这个对使用time的意义不大,但也许在其它的命令中使用中有借鉴意义。
[dev@user ~]$ time wc -l 0809.log >> a.log
real 0m0.780s
user 0m0.304s
sys 0m0.475s
[dev@user ~]$ cat a.log
6945388 0809.log
[dev@user ~]$ { time wc -l 0809.log; } >> b.log
real 0m0.769s
user 0m0.310s
sys 0m0.459s
[dev@user ~]$ cat b.log
6945388 0809.log
[dev@user ~]$ { time wc -l 0809.log; } 2>> c.log
6945388 0809.log
[dev@user ~]$ cat c.log
real 0m0.829s
user 0m0.348s
sys 0m0.480s
[dev@user ~]$ { time wc -l 0809.log; } > c.log 2>&1
[dev@user ~]$ cat c.log
6945388 0809.log
real 0m0.809s
user 0m0.317s
sys 0m0.491s
二、linux中的退出命令exit与logout命令的区别
今天偶尔想到了exit与logout两个命令,在使用的时候突然发现好像这两者没有什么区别,网上一般的提法都是说logout表示注销用户;而exit 表示退出控制台,虽然在描述的时候好像是有区别,但当在命令行里执行这两个命令时,发现都是退出了控制台,并没有感受到什么差异。还看到网上有这么一个描述:退出系统我们可以选择exit或者logout,那么这两者之间有区别么?大部分系统来说这两者之间是没有区别的,但是他们两者还是有一点点的区别的:logout退出时会执行~/.bash_logout(如果有的话),而exit只会作退出工作而不执行~/.bash_logout。除此之外别无其他区别。但是亲自测试,不管是执行exit还是执行logout都会去调用.bash_logout的内容。如下:
[dev@user ~]$ cat .bash_logout
# ~/.bash_logout
echo "goodbye onlinedev."
[dev@user ~]$ exit
logout
goodbye onlinedev.
Connection to 182.118.10.6 closed.
Session closed, press ENTER to start, l to last session or q to exit.
[dev@user ~]$ logout
goodbye onlinedev.
Connection to 182.118.10.6 closed.
Session closed, press ENTER to start, l to last session or q to exit.
那两到底有什么区别呢?我个人尝试总结一下:
1,从上面的执行过程可以看到,每次执行exit后面都跟着执行了一次logout,可以认为在命令行下执行的exit就是先进行了一些任务结束,最后执行logout,基本和logout没有什么差别。
2,logout只能在命令行中执行,而exit可以在shell脚本中执行。而且在shell脚本中执行exit并不会退出控制台,只是终止当前脚本执行,如下代码:
[root@123 ~]# cat test.sh
#!/bin/bash
logout
#执行的时候提示没有这个shell,需要使用exit
[root@123 ~]# ./test.sh
./test.sh: line 2: logout: not login shell: use `exit'
[root@123 ~]# cat test.sh
#!/bin/bash
exit
#执行结束,在终端上看是没有什么直接返回。
[root@123 ~]# ./test.sh
[root@123 ~]#
3,exit在shell脚本中执行时还可以带参数,使shell以指定的状态值退出。若不设置状态值参数,则shell以预设值退出。状态值0代表执行成功,其他值代表执行失败。此参数可在shell执行后通过$?获取
[root@123 ~]# ./test.sh
[root@123 ~]# echo $?
0
[root@123 ~]# cat test.sh
#!/bin/bash
exit 99
[root@123 ~]# ./test.sh
[root@123 ~]# echo $?
99
综上:logout是专门用于命令行中退出当前登录的Shell命令,exit也具有logout的功能,但exit同时还能用于退出执行的shell脚本,并通过设置参数返回给调用shell的程序本身,这个可以方便协同跨程序间的调用。