strace和lsof的学习

一、strace

该命令为了跟踪进程的系统调用情况。如果进程有问题,可以根据该命令去排查,看看哪里出现了问题。

一个例子:

我在command定义一个执行函数:

 public function handle()
    {
       $re = CFDailyFinanceProcessor::getAllNeedDealGids();
       var_dump($re);
    }

该函数直接从Redis中读取数据。

strace -c -tt php artisan test:run

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 15.38    0.002556           3       857           mmap
 12.67    0.002105           1      2534         3 fstat
 11.95    0.001985           3       787         3 openat
 11.48    0.001908           3       717           munmap
  9.59    0.001593           8       192           mprotect
  8.59    0.001427           2       880        11 stat
  7.33    0.001217           2       797           close
  6.54    0.001087           1      1047         6 lstat
  4.04    0.000672           5       138           read
  3.01    0.000500           2       224        65 access
  2.74    0.000456           6        80           rt_sigaction
  2.09    0.000348           2       142           getdents
  1.00    0.000166           7        24           brk
  0.93    0.000155           2        80         6 lseek
  0.81    0.000134           3        41        37 ioctl
  0.76    0.000126           5        23           futex
  0.11    0.000019          19         1         1 connect
  0.11    0.000019           6         3           getrandom
  0.10    0.000016           5         3           poll
  0.10    0.000016           8         2           readlink
  0.09    0.000015           5         3           getcwd
  0.08    0.000014           7         2           sendto
  0.08    0.000013           4         3           write
  0.07    0.000012           4         3           socket
  0.07    0.000011           4         3           prlimit64
  0.06    0.000010           2         6           fcntl
  0.05    0.000008           3         3           getpid
  0.04    0.000006           3         2           recvfrom
  0.04    0.000006           6         1           sysinfo
  0.02    0.000004           1         3           uname
  0.02    0.000003           2         2           rt_sigprocmask
  0.02    0.000003           3         1           getsockopt
  0.01    0.000002           1         3           dup
  0.01    0.000002           2         1           wait4
  0.00    0.000000           0         2           pipe
  0.00    0.000000           0         1           clone
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.016614                  8615       132 total

直接不加参数:

strace -o /tmp/out.log php artisan test:run

lstat("/home/work/admin/config/resp_codes.php", {st_mode=S_IFREG|0664, st_size=656, ...}) = 0
stat("/home/work/admin/config/resp_codes.php", {st_mode=S_IFREG|0664, st_size=656, ...}) = 0
lstat("/home/work/admin/config/resp_codes.php", {st_mode=S_IFREG|0664, st_size=656, ...}) = 0
lstat("/home/work/admin/config/filesystems.php", {st_mode=S_IFREG|0664, st_size=2543, ...}) = 0
stat("/home/work/admin/config/filesystems.php", {st_mode=S_IFREG|0664, st_size=2543, ...}) = 0
lstat("/home/work/admin/config/filesystems.php", {st_mode=S_IFREG|0664, st_size=2543, ...}) = 0
lstat("/home/work/admin/config/permission.php", {st_mode=S_IFREG|0664, st_size=844, ...}) = 0
stat("/home/work/admin/config/permission.php", {st_mode=S_IFREG|0664, st_size=844, ...}) = 0
lstat("/home/work/admin/config/permission.php", {st_mode=S_IFREG|0664, st_size=844, ...}) = 0
lstat("/home/work/admin/config/app.php", {st_mode=S_IFREG|0664, st_size=9357, ...}) = 0
stat("/home/work/admin/config/app.php", {st_mode=S_IFREG|0664, st_size=9357, ...}) = 0
lstat("/home/work/admin/config/app.php", {st_mode=S_IFREG|0664, st_size=9357, ...}) = 0
lstat("/home/work/admin/config/session.php", {st_mode=S_IFREG|0664, st_size=6872, ...}) = 0
stat("/home/work/admin/config/session.php", {st_mode=S_IFREG|0664, st_size=6872, ...}) = 0
lstat("/home/work/admin/config/session.php", {st_mode=S_IFREG|0664, st_size=6872, ...}) = 0
lstat("/home/work/admin/config/database.php", {st_mode=S_IFREG|0664, st_size=9335, ...}) = 0
stat("/home/work/admin/config/database.php", {st_mode=S_IFREG|0664, st_size=9335, ...}) = 0
lstat("/home/work/admin/config/database.php", {st_mode=S_IFREG|0664, st_size=9335, ...}) = 0
lstat("/home/work/admin/config/cache.php", {st_mode=S_IFREG|0664, st_size=2682, ...}) = 0
stat("/home/work/admin/config/cache.php", {st_mode=S_IFREG|0664, st_size=2682, ...}) = 0
lstat("/home/work/admin/config/cache.php", {st_mode=S_IFREG|0664, st_size=2682, ...}) = 0
lstat("/home/work/admin/config/admin.php", {st_mode=S_IFREG|0664, st_size=4968, ...}) = 0
stat("/home/work/admin/config/admin.php", {st_mode=S_IFREG|0664, st_size=4968, ...}) = 0
lstat("/home/work/admin/config/admin.php", {st_mode=S_IFREG|0664, st_size=4968, ...}) = 0
lstat("/home/work/admin/config/auth.php", {st_mode=S_IFREG|0664, st_size=3351, ...}) = 0
stat("/home/work/admin/config/auth.php", {st_mode=S_IFREG|0664, st_size=3351, ...}) = 0
lstat("/home/work/admin/config/auth.php", {st_mode=S_IFREG|0664, st_size=3351, ...}) = 0
lstat("/home/work/admin/config/services.php", {st_mode=S_IFREG|0664, st_size=980, ...}) = 0
stat("/home/work/admin/config/services.php", {st_mode=S_IFREG|0664, st_size=980, ...}) = 0
lstat("/home/work/admin/config/services.php", {st_mode=S_IFREG|0664, st_size=980, ...}) = 0
lstat("/home/work/admin/config/queue.php", {st_mode=S_IFREG|0664, st_size=2617, ...}) = 0
stat("/home/work/admin/config/queue.php", {st_mode=S_IFREG|0664, st_size=2617, ...}) = 0
lstat("/home/work/admin/config/queue.php", {st_mode=S_IFREG|0664, st_size=2617, ...}) = 0
lstat("/home/work/admin/config/business.php", {st_mode=S_IFREG|0664, st_size=58, ...}) = 0
stat("/home/work/admin/config/business.php", {st_mode=S_IFREG|0664, st_size=58, ...}) = 0
lstat("/home/work/admin/config/business.php", {st_mode=S_IFREG|0664, st_size=58, ...}) = 0
lstat("/home/work/admin/config/broadcasting.php", {st_mode=S_IFREG|0664, st_size=1604, ...}) = 0
stat("/home/work/admin/config/broadcasting.php", {st_mode=S_IFREG|0664, st_size=1604, ...}) = 0
lstat("/home/work/admin/config/broadcasting.php", {st_mode=S_IFREG|0664, st_size=1604, ...}) = 0
lstat("/home/work/admin/config/view.php", {st_mode=S_IFREG|0664, st_size=1004, ...}) = 0
stat("/home/work/admin/config/view.php", {st_mode=S_IFREG|0664, st_size=1004, ...}) = 0
lstat("/home/work/admin/config/view.php", {st_mode=S_IFREG|0664, st_size=1004, ...}) = 0
lstat("/home/work/admin/config/order_type.php", {st_mode=S_IFREG|0664, st_size=4256, ...}) = 0
stat("/home/work/admin/config/order_type.php", {st_mode=S_IFREG|0664, st_size=4256, ...}) = 0
lstat("/home/work/admin/config/order_type.php", {st_mode=S_IFREG|0664, st_size=4256, ...}) = 0
lstat("/home/work/admin/config/image.php", {st_mode=S_IFREG|0664, st_size=508, ...}) = 0
stat("/home/work/admin/config/image.php", {st_mode=S_IFREG|0664, st_size=508, ...}) = 0
lstat("/home/work/admin/config/image.php", {st_mode=S_IFREG|0664, st_size=508, ...}) = 0
lstat("/home/work/admin/config/mer.php", {st_mode=S_IFREG|0664, st_size=4089, ...}) = 0
stat("/home/work/admin/config/mer.php", {st_mode=S_IFREG|0664, st_size=4089, ...}) = 0
lstat("/home/work/admin/config/mer.php", {st_mode=S_IFREG|0664, st_size=4089, ...}) = 0
lstat("/home/work/admin/config/mail.php", {st_mode=S_IFREG|0664, st_size=4212, ...}) = 0
stat("/home/work/admin/config/mail.php", {st_mode=S_IFREG|0664, st_size=4212, ...}) = 0
lstat("/home/work/admin/config/mail.php", {st_mode=S_IFREG|0664, st_size=4212, ...}) = 0

其实这只是部分文件,其实后面还有很多,也就是一个console命令,需要执行很多stat的调用。可以看上面都是laravel的配置文件。

最后才到了Redis部分,从建立socket开始


socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP) = 5
close(5)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 5
fcntl(5, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
connect(5, {sa_family=AF_INET, sin_port=htons(6379), sin_addr=inet_addr("10.38.163.219")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=5, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 5000) = 1 ([{fd=5, revents=POLLOUT}])
getsockopt(5, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
fcntl(5, F_SETFL, O_RDWR)               = 0

lstat("/home/work/admin/vendor/composer/../predis/predis/src/Response/ResponseInterface.php", {st_mode=S_IFREG|0664, st_size=417, ...}) = 0
openat(AT_FDCWD, "/home/work/admin/vendor/predis/predis/src/Response/ResponseInterface.php", O_RDONLY) = 6
fstat(6, {st_mode=S_IFREG|0664, st_size=417, ...}) = 0
fstat(6, {st_mode=S_IFREG|0664, st_size=417, ...}) = 0
fstat(6, {st_mode=S_IFREG|0664, st_size=417, ...}) = 0
fstat(6, {st_mode=S_IFREG|0664, st_size=417, ...}) = 0
mmap(NULL, 417, PROT_READ, MAP_SHARED, 6, 0) = 0x7f43993c3000
munmap(0x7f43993c3000, 417)             = 0
close(6)                                = 0
sendto(5, "*2\r\n$8\r\nSMEMBERS\r\n$22\r\nmerchant/"..., 47, 0, NULL, 0) = 47
poll([{fd=5, events=POLLIN|POLLERR|POLLHUP}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
recvfrom(5, "*1\r\n$6\r\n103512\r\n", 8192, 0, NULL, NULL) = 16
write(1, "array(1) {\n", 11array(1) {
)            = 11
write(1, "  [0]=>\n", 8  [0]=>
)                = 8
write(1, "  ", 2  )                       = 2
write(1, "string(6) \"", 11string(6) ")            = 11
write(1, "103512", 6103512)                   = 6
write(1, "\"\n", 2"
)                     = 2
write(1, "}\n", 2}
)                      = 2
lstat("/home/work/admin/vendor/composer/../laravel/framework/src/Illuminate/Console/Events/CommandFinished.php", {st_mode=S_IFREG|0664, st_size=1196, ...}) = 0
openat(AT_FDCWD, "/home/work/admin/vendor/laravel/framework/src/Illuminate/Console/Events/CommandFinished.php", O_RDONLY) = 6
fstat(6, {st_mode=S_IFREG|0664, st_size=1196, ...}) = 0
fstat(6, {st_mode=S_IFREG|0664, st_size=1196, ...}) = 0
fstat(6, {st_mode=S_IFREG|0664, st_size=1196, ...}) = 0
fstat(6, {st_mode=S_IFREG|0664, st_size=1196, ...}) = 0
mmap(NULL, 1196, PROT_READ, MAP_SHARED, 6, 0) = 0x7f43993c3000

除了可以在应用中使用,还可以直接指定进程  -p  pid进程号。

1、strace较好的教程: strace使用教程

2、strace使用的几个场景: strace使用场景

二、lsof

通过man查看一下,其作用就是list all open files

lsof命令可以看到某个进程pid调用的所有资源,如果存在大量的can’t identify protocol,说明有socket泄漏,未正常关闭。

当然如果出现泄漏,那么也可以查看含有最多句柄的进程。

lsof -n|awk '{print $2}'| sort | uniq -c | sort -nr | head -n 20

当然,有时我们想清理磁盘空间,但是du却看不见。就可以看看有些大文件是不是处于deleted状态。

lsof |grep deleted

Linux中一切皆文件,block,reg,dir,ipv4等等都可以,因此我们也可以查看当前系统所建立的连接。

lsof -i

查看tcp: lsof -i tcp

例子:

java     4098 haibo  110u  IPv6 6412279      0t0  TCP *:9092 (LISTEN)
java     4228 haibo  247u  IPv6 6410736      0t0  TCP *:9300 (LISTEN)
java     4228 haibo  296u  IPv6 6410745      0t0  TCP *:9500 (LISTEN)
java     4228 haibo  297u  IPv6 6409105      0t0  TCP localhost:9500->localhost:57306 (ESTABLISHED)
java     4228 haibo  298u  IPv6 6409107      0t0  TCP localhost:9500->localhost:57314 (ESTABLISHED)
java     4228 haibo  299u  IPv6 6413823      0t0  TCP localhost:9500->localhost:57316 (ESTABLISHED)
java     4228 haibo  300u  IPv6 6413824      0t0  TCP localhost:9500->localhost:57324 (ESTABLISHED)
java     4228 haibo  301u  IPv6 6412755      0t0  TCP localhost:9500->localhost:57326 (ESTABLISHED)
java     4228 haibo  302u  IPv6 6412756      0t0  TCP localhost:9500->localhost:57328 (ESTABLISHED)
java     4228 haibo  303u  IPv6 6410798      0t0  TCP localhost:9500->localhost:57330 (ESTABLISHED)
java     4228 haibo  312u  IPv6 6418686      0t0  TCP localhost:9500->localhost:57340 (ESTABLISHED)
java     4228 haibo  313u  IPv6 6414618      0t0  TCP localhost:9500->localhost:57342 (ESTABLISHED)
java     4228 haibo  314u  IPv6 6412767      0t0  TCP localhost:9500->localhost:57344 (ESTABLISHED)
java     4228 haibo  315u  IPv6 6403971      0t0  TCP localhost:9500->localhost:57346 (ESTABLISHED)
java     4228 haibo  316u  IPv6 6403972      0t0  TCP localhost:9500->localhost:57348 (ESTABLISHED)
java     4228 haibo  317u  IPv6 6413906      0t0  TCP localhost:9500->localhost:57350 (ESTABLISHED)
java     4228 haibo  318u  IPv6 6409121      0t0  TCP localhost:9500->localhost:57352 (ESTABLISHED)
java     4228 haibo  319u  IPv6 6409122      0t0  TCP localhost:9500->localhost:57354 (ESTABLISHED)
java     4228 haibo  320u  IPv6 6418327      0t0  TCP localhost:9500->localhost:57356 (ESTABLISHED)
java     4228 haibo  321u  IPv6 6409123      0t0  TCP localhost:9500->localhost:57358 (ESTABLISHED)
java     4228 haibo  322u  IPv6 6412769      0t0  TCP localhost:9500->localhost:57360 (ESTABLISHED)
java     4228 haibo  327u  IPv6 6413917      0t0  TCP localhost:9500->localhost:57374 (ESTABLISHED)
node     4229 haibo   18u  IPv4 6418471      0t0  TCP *:5601 (LISTEN)

一般情况下,strace和lsof可以配合着使用。

lsof好的教程: linux工具进阶 lsof使用

--------EOF---------
微信分享/微信扫码阅读