前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

日常频繁使用的Linux命令,按排查场景整理

首页2018-02-25 09:32:41Back-End
Linux运维排查命令行

服务突然 502,你 ssh 上去,第一条命令敲什么?

这个问题我问过好几个刚接手服务器的同学,答案五花八门。有人直接 tail 日志,有人上来就 top,也有人愣在那不知道从哪开始。命令本身大家都认识,卡住的是顺序,不知道该先确认什么再确认什么。

单纯背命令清单意义不大,网上一搜一大把,背完第二天就忘。真正有用的是把命令和排查场景绑在一起:进程还在不在、端口通不通、磁盘满没满、日志里写了什么、网络能不能出去。这篇按这个思路把日常用得最多的 Linux 命令重新归拢一遍,每组都说清楚为什么先查这个。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • 服务出问题时的排查顺序,先看哪一层
  • 查进程:ps、pstree、top、pkill 各自的位置
  • 查端口和防火墙:端口没监听和端口被拦是两回事
  • 查磁盘和内存:df、du、free 以及 inode 满了的诡异现象
  • 查日志:管道组合怎么把几百兆的日志缩到几行
  • 查网络:源、DNS、连通性
  • 文件管理的基本功:软链接、重定向、压缩解压
  • 找文件的四个命令,为什么 find 排最后
  • vi 在服务器上的应急操作
  • 看机器配置和系统版本

# 一、先想清楚排查顺序

线上服务出问题,我的顺序基本是固定的这五步。

进程还在吗。服务被 OOM Killer 干掉、被人手动杀了、启动就崩了,这三种情况都表现为「访问不通」,但原因天差地别。先确认进程存在与否,能砍掉一大半的可能性。

进程在,那端口有没有监听。进程活着不等于服务可用,配置写错端口、绑定到了 127.0.0.1 而不是 0.0.0.0,进程都好好的但外面就是连不上。

端口在监听,那是不是被防火墙拦了。这一步和上一步的现象很像,都是「连不上」,但一个是本机没监听,一个是包根本没进来。

前面都正常,看资源。磁盘满了、内存被吃光了、CPU 跑满了,服务会表现出各种奇怪的间歇性故障。

最后才是看日志。不是说日志不重要,而是前面四步能快速缩小范围,带着假设去看日志比漫无目的地翻要快得多。

顺着这个顺序,下面一组一组说。

# 二、查进程

# 2.1 ps

ps 列出系统中运行的进程,包括进程号、命令、CPU 使用量、内存使用量。日常最常用的就两种写法。

# 找特定的进程
ps -ef | grep nginx

# 显示所有进程的完整信息,带 CPU 和内存占用
ps -aux
@前端进阶之旅: 代码已经复制到剪贴板

ps -ef 是 System V 风格,输出里有 PPID(父进程 ID),排查「谁把它拉起来的」时候有用。ps -aux 是 BSD 风格,多了 %CPU 和 %MEM 两列。两套参数混用一般也能跑,但看到的列不一样,知道有这么回事就行。

ps -ef | grep nginx 有个人人都会遇到的现象,输出里总会多出一行 grep nginx 自己。因为 grep 也是个进程,ps 抓快照的那一刻它正好在跑。经典的绕法是把首字母用中括号括起来。

ps -ef | grep [n]ginx
@前端进阶之旅: 代码已经复制到剪贴板

[n]ginx 作为正则匹配 nginx,但 grep 自己的命令行里写的是 [n]ginx 这个带括号的字符串,匹配不上自己。或者干脆用 pgrep,它就是为这个场景生的。

pgrep -a nginx
@前端进阶之旅: 代码已经复制到剪贴板

# 2.2 pstree

Linux 里每一个进程都是由父进程创建的。pstree 用树状图展示进程之间的父子关系。

用得最多的场景是看 master/worker 结构的服务。Nginx 的 master 带几个 worker、PM2 的守护进程下面挂了几个 Node 实例,一眼就看清楚了。ps 是平铺的列表,同样的信息得自己在 PPID 里对着找。

pstree -p | grep node
@前端进阶之旅: 代码已经复制到剪贴板

# 2.3 top

top 监视系统中不同进程使用的资源,显示的数据包括 PID、进程属主、优先级、%CPU、%MEM 等,可以用这些指示出资源使用量。

进去之后有几个交互键值得记住。P 按 CPU 排序,M 按内存排序,1 展开显示每个 CPU 核心的负载,q 退出。

看 top 的第一行还有个关键信息,load average 那三个数分别是 1 分钟、5 分钟、15 分钟的平均负载。判断标准是拿它和 CPU 核心数比,核心数是 4 而 load 长期在 8 以上,说明确实排队了。这里有个常见误判,load 高不一定是 CPU 忙,大量进程卡在磁盘 IO 上(状态 D)也会把 load 顶起来,这时候盯着 %CPU 看是找不到原因的。

# 2.4 pkill

pkill 根据进程名杀死进程,不用先查 PID 再 kill。

pkill nginx
@前端进阶之旅: 代码已经复制到剪贴板

但这个命令要小心,它是按名字模糊匹配的,名字写得太短可能会误杀。动手之前先用 pgrep -a 看一眼到底会命中哪些进程,这个习惯能避免很多事故。

另外 pkill 默认发的是 SIGTERM(15),进程可以捕获它做优雅退出。真的杀不掉才用 -9 发 SIGKILL,那个信号不能被捕获,进程没有机会清理临时文件和释放连接。习惯性上来就 -9 不是好事。

# 三、查端口和防火墙

进程活着但连不上,接下来看端口。

# 看所有监听中的 TCP 端口,带进程名
ss -tlnp

# 老一点的机器上可能只有 netstat
netstat -tlnp

# 看某个端口被谁占了
lsof -i:8080
@前端进阶之旅: 代码已经复制到剪贴板

重点看监听地址那一列。0.0.0.0:3000 表示所有网卡都能连,127.0.0.1:3000 表示只有本机能连。Node 服务用 app.listen(3000) 在某些环境下会绑到回环地址,本机 curl 一切正常,外面死活连不上,就是这个原因。

确认端口在监听但外部还是连不上,那就轮到防火墙了。

linux 查看防火墙状态及开启关闭命令,老的 CentOS 6 系用 service 方式。

# 查看防火墙状态
[root@centos6 ~]# service iptables status

# 开启防火墙
[root@centos6 ~]# service iptables start

# 关闭防火墙
[root@centos6 ~]# service iptables stop
@前端进阶之旅: 代码已经复制到剪贴板

也可以直接调 init 脚本。

[root@centos6 ~]# cd /etc/init.d/

# 查看状态
[root@centos6 init.d]# /etc/init.d/iptables status

# 暂时关闭防火墙 
[root@centos6 init.d]# /etc/init.d/iptables stop

# 重启
[root@centos6 init.d]# /etc/init.d/iptables restart
@前端进阶之旅: 代码已经复制到剪贴板

想确认 80 端口是不是被放行了,直接查规则。

iptables -vnL | grep ":80 "
@前端进阶之旅: 代码已经复制到剪贴板

返回有内容说明开通,没返回内容则说明被阻止。

这块要补一句时效性的说明。上面这套是 CentOS 6 时代的做法,CentOS 7 之后 init 脚本换成了 systemd,防火墙前端也换成了 firewalld,对应的命令变成这样。

systemctl status firewalld
firewall-cmd --list-all
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
@前端进阶之旅: 代码已经复制到剪贴板

更新一点的发行版(Debian/Ubuntu 系)常用的是 ufw。原文那套命令在老机器上依然有效,遇到新系统换个前端工具就行,底层还是 netfilter 那一套。

还有个特别容易忽略的地方,云服务器除了系统防火墙,云厂商控制台上还有一层安全组。系统里 iptables 全开了外面还是不通,八成是安全组没放行。这个我踩过,在机器上折腾了半天规则,最后发现问题在网页控制台上。

# 四、查磁盘和内存

# 4.1 磁盘空间

# 查看各分区的使用情况
df -h

# 查看某个目录占了多少空间
du -h file

# 查看当前目录下各个文件/目录的大小
du -sh *
@前端进阶之旅: 代码已经复制到剪贴板

df 是从文件系统层面看,du 是从目录层面统计。日常排查是 df -h 先看哪个分区满了,再 du -sh * 逐层往下找是谁占的。

-h 是 human-readable,把字节数换算成 K/M/G。du -sh * 里的 -s 是 summarize,只输出每个参数的汇总,不加的话会把所有子目录一层层都列出来,几千行刷屏。

这里有个坑要注意。df 显示还有空间,但写文件就是报 No space left on device,这种情况看一眼 inode。

df -i
@前端进阶之旅: 代码已经复制到剪贴板

inode 是文件系统用来记录文件元信息的结构,数量在格式化时就定死了。海量小文件(session 文件、日志切片、缓存碎片)会把 inode 耗光,这时候空间还剩很多但一个新文件都建不了。第一次遇到这个现象是真的会懵。

另一个坑是删了文件空间没释放。有进程还开着那个文件句柄的话,磁盘空间不会回收,lsof | grep deleted 能把这些找出来,重启对应进程才会真正释放。前端项目里最常见的场景是日志文件被 rm 了但 Node 进程还在往里写。

# 4.2 内存

free -m
@前端进阶之旅: 代码已经复制到剪贴板

-m 以 MB 显示,-g 是 GB。

看 free 输出有个经典误解,很多人看到 free 那一列只剩几十兆就慌了。其实 Linux 会把暂时用不到的内存拿去做文件缓存(buff/cache),需要的时候随时能回收。真正该看的是 available 那一列,它才代表还能给新进程用多少。

# 五、查日志

日志文件动辄几百兆,直接 cat 是灾难,终端刷屏几分钟还找不到重点。日志排查的核心是用管道把范围一层层缩小。

管道命令 | 的作用是把前一个命令的输出交给后一个命令处理,最简单的例子是分页看。

ls -l /etc | more
@前端进阶之旅: 代码已经复制到剪贴板

真正干活的组合大概是这几种。

# 实时跟踪最新日志,部署后观察最常用
tail -f /var/log/nginx/error.log

# 只看最后 200 行,再从里面找关键字
tail -n 200 app.log | grep "ERROR"

# 找关键字并带出上下文各 5 行
grep -C 5 "Timeout" app.log

# 统计某个错误出现了多少次
grep -c "500" access.log

# 找出访问量最大的前 10 个 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
@前端进阶之旅: 代码已经复制到剪贴板

最后那条值得拆开说说,它是一个非常典型的管道流水线。awk '{print $1}' 取每行第一列(Nginx 默认日志格式里就是客户端 IP),sort 排序把相同的 IP 排到一起,uniq -c 统计每个 IP 出现的次数,sort -rn 按数字倒序排,head -10 取前十。

为什么 uniq 前面必须先 sort?因为 uniq 只能去掉相邻的重复行,不排序的话分散在各处的相同 IP 它认不出来。这个我一开始也搞错过,写完发现统计结果全是 1。

日志文件太大的时候还有个实用技巧,less 比 vi 安全得多。vi 会把整个文件读进内存,一个 2G 的日志能直接把机器拖死;less 是按需加载的,进去之后 /关键字 搜索、G 跳到末尾、q 退出。

fe
  • 一、先想清楚排查顺序
  • 二、查进程
    • 2.1 ps
    • 2.2 pstree
    • 2.3 top
    • 2.4 pkill
  • 三、查端口和防火墙
  • 四、查磁盘和内存
    • 4.1 磁盘空间
    • 4.2 内存
  • 五、查日志
  • 六、查网络
  • 七、文件管理的基本功
    • 7.1 创建和删除
    • 7.2 软链接
    • 7.3 重定向
    • 7.4 压缩解压速查
  • 八、找文件的四个命令
    • 8.1 which
    • 8.2 whereis
    • 8.3 locate
    • 8.4 find
  • 九、vi 的应急操作
  • 十、上传下载文件
  • 十一、看机器配置和系统版本
  • 总结
  • 参考

← Nginx学习篇,从编译安装到配置文件结构入门JavaScript字符串、对象、数组常用方法速查 →