您的位置:首页 > 运维架构 > Shell

shell调试手段三则

2013-02-25 22:29 183 查看

shell调试手段三则

1. time

用途说明

time命令常用于测量一个命令的运行时间,注意不是用来显示和修改系统时间的(这是date命令干的事情)。

常用参数

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

real    0m14.837s
user    0m0.030s
sys     0m0.120s
[root@web186 root]#
注: **real远大于user加上sys,因为find需要遍历各个目录,需要大量的I/O操作,

而磁盘I/O通常是最慢的环节,因此大部分时间find进程都在等待磁盘I/O完成。**

其实系统中有两个time

[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功能更强大。

解决time命令输出信息的重定向问题

time命令的输出信息是打印在标准错误输出上的, 我们通过一个简单的尝试来验证一下。::

[root@web186 root]# time find . -name "mysql.sh" >1.txt

real    0m0.081s
user    0m0.060s
sys     0m0.020s


*通过上面的尝试,发现无法将time的输出信息重定向到文件里面,为什么?

因为time是shell的关键字,shell做了特殊处理,它会把time命令后面的命令行作为一个

整体来进行处理,在重定向时,实际上是针对后面的命令来的,

time命令本身的输出并不会被重定向的。那现在怎么办呢?*

第一种解决方法,就是将time命令和将要执行的命令行放到一个shell代码块中,

也就是一对大括号中,要注意空格和分号的使用。::

[root@web186 root]# { time find . -name "mysql.sh"; } 2>2.txt
./work186/sms/bin/mysql.sh
./work186/sms/src/scripts/mysql.sh
[root@web186 root]# cat 2.txt

real    0m0.068s
user    0m0.030s
sys     0m0.040s
另外一种方式就是使用子Shell的方式,如下所示::

[root@web186 root]# (time find . -name "mysql.sh") 2>2.txt
./work186/sms/bin/mysql.sh
./work186/sms/src/scripts/mysql.sh
[root@web186 root]# cat 2.txt

real    0m0.083s
user    0m0.040s
sys     0m0.020s
[root@web186 root]#


2. lsof

lsof是遵从Unix哲学的典范,它只做一件事情,并且做的相当完美——它可以列出某个进

程打开的所有文件信息。打开的文件可能是普通的文件,目录,NFS文件,块文件,

字符文件,共享库,常规管道,明明管道,符号链接,Socket流,网络Socket,

UNIX域Socket,以及其它更多。因为Unix系统中几乎所有东西都是文件,你可以想象lsof该有多有用。

找出谁在使用某个文件

# lsof /path/to/file


只需要执行文件的路径,lsof就会列出所有使用这个文件的进程,你也可以列出多个文件,lsof会列出所有使用这些文件的进程。

递归查找某个目录中所有打开的文件

# lsof +D /usr/lib
加上+D参数,lsof会对指定目录进行递归查找,注意这个参数要比grep版本慢::

# lsof | grep '/usr/lib'
之所以慢是因为+D首先查找所有的文件,然后一次性输出。

列出某个用户打开的所有文件

# lsof -u rms,root
这条命令会列出所有rms和root用户打开的文件。

查找某个程序打开的所有文件

# lsof -c apache


-c选项限定只列出以apache开头的进程打开的文件:

列出所有由某个PID对应的进程打开的文件

# lsof -p 450,980,333


-p选项让你可以使用进程id来过滤输出。

列出所有网络连接

# lsof -i


lsof的-i选项可以列出所有打开了网络套接字(TCP和UDP)的进程。

列出所有TCP网络连接

# lsof -i tcp


也可以为-i选项加上参数,比如tcp,tcp选项会强制lsof只列出打开TCP sockets的进程。

找到使用某个端口的进程

# lsof -i :25


:25和-i选项组合可以让lsof列出占用TCP或UDP的25端口的进程。

你也可以使用/etc/services中制定的端口名称来代替端口号,比如

# lsof -i :smtp


找到使用某个udp端口号的进程::

# lsof -i udp:53

3. strace

[root@localhost ~]# ps -ef|grep rb; netstat -anp | grep rb
root      1613     1  0 13:36 ?        00:00:00 ./rbtunnel lijuanping@itcchina.com 1028
root      4809  4720  0 14:21 pts/3    00:00:00 grep rb
root     13236     1  0 Dec10 ?        00:00:00 ./rbserver
...
tcp        0      0 0.0.0.0:13651               0.0.0.0:*                   LISTEN      13236/./rbserver
tcp       20      0 124.232.156.156:15056       114.255.102.198:57256       CLOSE_WAIT  1613/./rbtunnel
tcp   136458      0 124.232.156.156:15057       221.219.116.77:1182         ESTABLISHED 1613/./rbtunnel
tcp     1117  26064 124.232.156.156:15056       114.255.102.198:57667       ESTABLISHED 1613/./rbtunnel


发现进程1613的数据转发有问题,使用strace来看一下。

[root@localhost ~]# strace -p 1613
Process 1613 attached - interrupt to quit
gettimeofday({1355293347, 691650}, NULL) = 0
write(3, "I 0 14:20:25.792080 action.tcp_r"..., 97) = 97
select(10, [4 6 8 9], NULL, NULL, {30, 0}) = 3 (in [4 8 9], left {30, 0})
recv(9, "\36\3\317\324\n_\305\344\1\236|\317\31\\\361\r`\310U5*\266\2155\320R\3158\347\342\307\310"..., 4095, 0) = 4095
gettimeofday({1355293347, 713394}, NULL) = 0
send(8, "\36\3\317\324\n_\305\344\1\236|\317\31\\\361\r`\310U5*\266\2155\320R\3158\347\342\307\310"..., 4095, 0
Ctrl+C
<unfinished ...>
Process 1613 detached
[root@localhost ~]# )


参考资料:

Linux命令之time - 测定一个命令的资源使用情况

Unix调试的瑞士军刀:lsof

使用strace找出程序在哪个地方吊死
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: