![](http://upload-images.jianshu.io/upload_images/945893-95f643a6763dad69.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)
linux_observability_tools
介绍
在Linux 下进行进程的排错,有很多方法。比如,修改源代码,print出一些关键的信息,如果代码是Python 的话,可以使用traceback 来打印堆栈,以及使用sentry 等等。但是这些方法都不够直接。如果你想要直接看到一个卡住(hanging processes)的进程正在干什么,什么操作卡住了。这个时候,你就应该使用ps、strace、lsof 这三样工具。简单来说,ps 可以查看当前Linux 正在运行的进程的状态,找出进程对应的PID 号,进程的CPU 和内存占用,运行时间等。stace 可以追踪进程的系统调用。lsof 可以给出进程所有打开的文件,而Linux 下一切皆文件,比如硬件设备、网络连接等。
ps - report a snapshot of the current processes.
strace - trace system calls and signals
Lsof - lists on its standard output file information about files opened by processes
ps
- ps 命令常用的指令
ps auxf
- ps 显示的信息的含义
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 816 0.0 0.2 460500 2260 ? Ssl May14 3:01 ./aegis_update -f agx_update.cfg
root 842 0.0 0.0 4404 736 ? S May14 0:00 /bin/sh /alidata/server/mysql/bin/mysqld_safe --da
mysql 1118 0.0 3.9 404884 39988 ? Sl May14 7:35 \_ /alidata/server/mysql/bin/mysqld --basedir=/al
root 1140 0.0 0.0 30944 980 ? Ss May14 0:00 nginx: master process /alidata/server/nginx/sbin/n
www 1143 0.0 2.7 58080 28312 ? S May14 0:00 \_ nginx: worker process
root 1153 0.0 0.0 14508 972 tty1 Ss+ May14 0:00 /sbin/getty -8 38400 tty1
ntp 1179 0.0 0.2 33756 2076 ? Ss May14 0:56 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 104:108
root 7220 0.0 0.2 635176 2304 ? Ssl 16:48 0:00 /usr/local/aegis/aegis_client/aegis_00_19/aegis_cl
USER 该进程输入哪个user
PID 进程的pid 号
%CPU 占用CPU 资源比例
%MEM 占用物理内存比例
VSZ 占用虚拟内存量(单位Kbytes)
RSS 实际占用内存量(单位Kbytes)
TTY 该进程在哪个终端上运行,如果与终端无关,则显示? 如果连入的终端,显示tty,网络连入显示pts/0
STAT 进程状态
START 进程启动的时间
TIME 进程占用CPU 的时间
COMMAND 进程的运行指令
- STAT 进程状态 转自:ps命令详解
R 运行
S 睡眠,等待某个条件的形成或者信号
I Idle空闲
Z 僵死,(a defunct process)但进程描述符存在, 直到父进程调用wait4()系统调用后释放。
D 不可中断,收到信号不唤醒和不可运行, 进程必须等待直到有中断发生。
T 终止,进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行。
P 等待交换页
W 无驻留页
X 死掉的进程
< 高优先级进程,高优先序的进程
N 低优先级进程,低优先序的进程
L 内存锁页,有记忆体分页分配并缩在记忆体内
s 进程的领导者(在它之下有子进程)
l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads)
+ 位于后台的进程组
strace
常见的Linux 系统调用有转自:strace 线程跟踪详解:
fork 创建一个新进程
clone 按指定条件创建子进程
execve 运行可执行文件
exit 中止进程
nanosleep 使进程睡眠指定的时间
pause 挂起进程,等待信号
wait 等待子进程终止
waitpid 等待指定子进程终止
socket 建立socket
bind 绑定socket到端口
connect 连接远程主机
accept 响应socket连接请求
send 通过socket发送信息
recv 通过socket接收信息
mmap 映射虚拟内存页
munmap 去除内存页映射
mremap 重新映射虚拟内存地址
msync 将映射内存中的数据写回磁盘
listen 监听socket端口
select 对多路同步I/O进行轮询
shutdown 关闭socket上的连接
readv 从文件读入数据到缓冲数组中
writev 将缓冲数组里的数据写入文件
pread 对文件随机读
pwrite 对文件随机写
lseek 移动文件指针
dup 复制已打开的文件描述字
flock 文件加/解锁
poll I/O多路转换
truncate 截断文件
相应地,可以让strace 来跟踪指定调用,而非全部。
-e trace=file 跟踪和文件访问相关的调用(参数中有文件名)
-e trace=process 和进程管理相关的调用,比如fork/exec/exit_group
-e trace=network 和网络通信相关的调用,比如socket/sendto/connect
-e trace=signal 信号发送和处理相关,比如kill/sigaction
-e trace=desc 和文件描述符相关,比如write/read/select/epoll等
-e trace=ipc 进程间通信相关,比如shmget等
- strace 常用指令
strace -p <pid> 跟踪进程的系统调用
strace -f -p <pid> 跟踪进程及其子进程的系统调用
strace -ttt -p <pid> 跟踪的同时显示时间信息 strace -c -p <pid> 显示进程的profilling 信息
lsof
- lsof 常用指令
lsof <filename> 显示打开某个文件的进程
lsof +D <DIR> 显示所有打开该目录的进程,注意,如果不想显示其子目录的进程,可以使用+d。
lsof -u <username> 显示某个用户启动进程所打开的文件
lsof -u^<username> 显示除了某个用户外的其他所以用户的启动进程打开的文件
lsof -i [4|6][@hostname|ip][:service|port] 显示打开某ip或者端口的进程 (可以和netstat 配合使用), 4和6 用来区分ip 协议 lsof -i 列出所有的网络连接(注意,网络连接也是文件) lsof -i TCP:1-1024 列出所有使用TCP 协议,端口范围是1-1024 的网络连接
- lsof 输出列代表的含义
FD – Represents the file descriptor. Some of the values of FDs are
cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device
NUMBER – Represent the actual file descriptor. The character after the number i.e ‘1u’, represents the mode in which the file is opened. r for read, w for write, u for read and write. TYPE – of files and it’s identification. DIR – Directory REG – Regular file CHR – Character special file. FIFO – First In First Out
实例
下面给出两个工作中遇到的实际问题,其中隐私部分马赛克处理,但不影响阅读。
下载文件失败
ps auxf
,看到有三个进程运行了8个多小时,有卡住的嫌疑。
![](http://upload-images.jianshu.io/upload_images/945893-2e7ff7919a21664d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)
ps_aufx
strace -p 19693
跟踪该进程。看到进程正在等待从某个文件指针等待读取数据,文件描述符为9。也就是说,该进程在这里等了8个多小时。。。
![](http://upload-images.jianshu.io/upload_images/945893-558a7f2d1efddcf5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/984)
strace
ls of 19693
可以看到,程序和某http 服务器建立起连接,进程就卡到了这个地方,而且文件描述符也是9。
![](http://upload-images.jianshu.io/upload_images/945893-b49561d62db8fe79.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)
lsof
- 接下来再进行进一步的排错。
github 代理失效
- aliyun 上有时候使用github 比较慢,用一台香港aliyun 搭建了shadowsocks
server,机器A 启动了shadowsocks client,为剩下几台同一局域网的机器做代理。github 代理这样配置。./ssh/config
,IP 和端口 是shadowsockes client 的。用nc 来做github ssh 包的转发,通过shadowsocks 链路,从香港服务器中转到github。
Host github.com
User git
IdentityFile ~/.ssh/id_rsa
ProxyCommand nc -x 1.2.3.4:1234 %h %p
- 前几天机器A 做了迁移,IP 变化了,一开始忘记了这件事情,再某台机器上操作git 的时候,报错。
![](http://upload-images.jianshu.io/upload_images/945893-750dd557c393f00b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)
gitpull
- 然后新开另一个终端,或者再tmux 下的另一个pannel,用
ps auxf
找到和git pull
相关的进程pid。
![](http://upload-images.jianshu.io/upload_images/945893-e1a8c2657521fc90.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)
git_ps
lsof -p 17919
,从最下面一行可以看出,发送了握手信息,并没有收到。
![](http://upload-images.jianshu.io/upload_images/945893-1f47ee04e6c77b0e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000)
git_lsof
- 进一步检查IP,发现已经换了。
参考
- Using strace and lsof to Track Down Process Hangs
首先跟踪了一个简单的Hello world 代码的C 函数,后面用实例说明Linux 中进程hang 的几个可能情况(进程进入死循环状态,跑满CPU;进程在等待某种还没有available 的资源,比如向某台机器发起TCP 请求,但是没有收到回应,或者通信已经建立,但是没有收到期望的数据。再或者进程想要加一个mutex 互斥锁,但是已经加锁,进程就在等待其free),并且给出一个实例,连接mysql 服务器失败,通过strace 与lsof 的追踪,发现机器发出SYN 的时候,没有收到应答,那么接下来应该进一步排查防火墙。 - 5 simple ways to troubleshoot using Strace
- Strace (and lsof)
- strace 线程跟踪详解
- linux lsof详解
作者:shawnwang_tech
链接:https://www.jianshu.com/p/b57a88e00765
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。