linux线上命令实战演练

背景

最近公司运维部门同学联合我们业务部门举行了一场线上实际服务器问题排查演练,其旨在提高我们每个开发人员针对linux中常用的一些命令的使用熟练程度,运维同学出的题都是非常具有代表性,从这次实际的演练中,我们每个人学习到了很多关于多个linux命令综合灵活运用的知识,以下是我们这次的实践演练,分享给大家,一起学习!

实践1

有一台linux服务器192.168.1.1的sshd的监听端口是22,如何统计192.168.1.1的sshd服务各种状态(TIME_WAIT/CLOSE_WAIT/ESTABLISHED)的连接数,以便快速定位问题

实践目的:了解机器连接数情况,便于排查问题

参考实践

有两种实践方式

  1. 第一种
    netstat -n | grep 192.168.1.1:22|awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
    
  2. 第二种
    netstat –lnpta|grep ssh|egrep “TIME_WAIT| CLOSE_WAIT| ESTABLISHED”
    

补充知识点

netstat常见参数
-a (all)显示所有选项,默认不显示LISTEN相关
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态
-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。
AWK
NF:支持记录域个数
NR:已经读取的记录数

实践2

192.168.1.1中/opt/log/dubbo-access-provider.2017-06-26.log.bz2 日志中,有192.168.1.2 关键字的数据有多少条
主要目的:当前线上日志文件统一要求以bz2 压缩之后保留在本机,当需要查看历史日志时,解压需要耗费大量时间,如何在不解压的情况下直接查看内容

参考实践

有以下三种实践方式

bzcat /opt/log/dubbo-access-provider.2017-06-26.log.bz2 |grep 192.168.1.2|wc –l

bzgrep 10.37.9.11 /opt/log/dubbo-access-provider.2017-06-26.log.bz2 |wc –l

less /opt/log/dubbo-access-provider.2017-06-26.log.bz2|grep '192.168.1.2' |wc –l

实践3

打包192.168.1.1服务器的 /opt/web/order-feature 目录,排除掉目录中的logs 和 work两个目录,打包后的文件名格式:自己的邮箱前缀.tar.gz(例如:zhangsan.tar.gz)。打包好的文件存放在/opt/backup目录下

主要目的:实际应用场景较为频繁,在项目代码需要打包迁移时,常常需要排除掉日志目录(如log目录)。

参考实践

tar -zcvf /opt/backup/yangjinan.tar.gz  \
            –exclude /opt/web/order-feature/work  \ 
            –exclude /opt/web/order-feature/logs   \
            /opt/web/order-feature

补充知识点

使用tar命令
主选项:
c 创建新的档案文件。如果用户想备份一个目录或是一些文件,就要选择这个选项。相当于打包。
x 从档案文件中释放文件。相当于拆包。
t 列出档案文件的内容,查看已经备份了哪些文件。
特别注意,在参数的下达中, c/x/t 仅能存在一个!不可同时存在!因为不可能同时压缩与解压缩。
辅助选项:
-z :是否同时具有 gzip 的属性?亦即是否需要用 gzip 压缩或解压? 一般格式为xx.tar.gz或xx. tgz
-j :是否同时具有 bzip2 的属性?亦即是否需要用 bzip2 压缩或解压?一般格式为xx.tar.bz2
-v :压缩的过程中显示文件!这个常用
-f :使用档名,请留意,在 f 之后要立即接档名喔!不要再加其他参数!
-p :使用原文件的原来属性(属性不会依据使用者而变)
–exclude FILE:在压缩的过程中,不要将 FILE 打包!

实践4

查询192.168.1.1服务器运行服务的总线程数

主要目的:当机器线程数超报警阀值时,能快速查出相关进程及线程信息

参考实践

  • 第一种方式
    ps -eLf |wc –l
  • 第二种方式
    pstree -p | wc –l

补充知识点

名称:ps
使用权限:所有使用者
使用方式:ps [options] [–help]
说明:显示瞬间行程 (process) 的动态
参数:ps的参数非常多, 在此仅列出几个常用的参数并大略介绍含义
-A 列出所有的进程
-w 显示加宽可以显示较多的资讯
-au 显示较详细的资讯
-aux 显示所有包含其他使用者的行程

############################################################

常用参数:

-A 显示所有进程(等价于-e)(utility)
-a 显示一个终端的所有进程,除了会话引线
-N 忽略选择。
-d 显示所有进程,但省略所有的会话引线(utility)
-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)
-p pid 进程使用cpu的时间
-u uid or username 选择有效的用户id或者是用户名
-g gid or groupname 显示组的所有进程。
U username 显示该用户下的所有进程,且显示各个命令的详细路径。如:ps U zhang;(utility)
-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.
-l 长格式(有F,wchan,C 等字段)
-j 作业格式
-o 用户自定义格式。
v 以虚拟存储器格式显示
s 以信号格式显示
-m 显示所有的线程
-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)
e 命令之后显示环境(如:ps -d e; ps -a e)(utility)
h 不显示第一行

############################################################

ps命令常用用法(方便查看系统进程)

1)ps a 显示现行终端机下的所有程序,包括其他用户的程序。
2)ps -A 显示所有进程。
3)ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
4)ps -e 此参数的效果和指定“A”参数相同。
5)ps e 列出程序时,显示每个程序所使用的环境变量。
6)ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
7)ps -H 显示树状结构,表示程序间的相互关系。
8)ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
9)ps s 采用程序信号的格式显示程序状况。
10)ps S 列出程序时,包括已中断的子程序资料。
11)ps -t<终端机编号>  指定终端机编号,并列出属于该终端机的程序的状况。
12)ps u  以用户为主的格式来显示程序状况。
13)ps x  显示所有程序,不以终端机来区分。
最常用的方法是ps -aux,然后再利用一个管道符号名称:ps

实践5

找出192.168.1.1最大的文件名中包含log的文件,假设因为该文件导致了磁盘空间报警,并且该文件是某个正在运行的tomcat服务异常产生的日志,需要处理该文件(该文件可进行任意操作包括删除),以释放空间。请给出相关思路

主要目的:磁盘空间问题为常见问题,需要定位哪些目录或者文件导致,并及时清理

参考实践

  1. df -h + du -sh |sort -rh 命令结合,定位出具体的占用空间最大的文件;或:
    find /opt/ -type f -name “
    log“|xargs ls -lSh|more
    du -a / | sort -rn | grep log | more
    find / -name ‘
    log*’ -size +1000M -exec du -h {} \;

  2. 假设找到的文件为a.log,echo “”>a.log 将该文件清空,空间即可释放
    很多同学直接rm -f a.log, 来处理。这样文件虽然删除,但是因tomcat服务仍在运行,会导致空间不能释放,此时需要重启tomcat才能将空间释放。

实践6

提取192.168.1.1服务器上/opt/log/localhost_access.log-20170609(nginx访问日志),访问前10的IP地址及访问次数

主要目的:主要目的:cat,awk,uniq,sort,head命令结合使用,日常日志分析中用到的比较多

参考实践

  1. 第一种
cat /opt/log/localhost_access.log-20170609|awk '{print $2}' | sort | uniq -c | sort -rn | head -n 10
  1. 第二种
cat localhost_access.log-20170609 | awk '{a[$2]++}END{for(i in a) print i,a[i]}'| sort -k2nr |head -10

实践7

显示192.168.1.1 /etc/nginx.conf 文件中不以#号开头的行

主要目的:了解grep /sed 的用法

参考实践

  1. 第一种方式
    sed -n ‘/^[#]/!p’ /etc/nginx.conf
  2. 第二种方式
    sed -e ‘/^#/d’ /etc/nginx.conf
  3. 第三种方式
    grep -v “^#” /etc/nginx.conf

实践8

192.168.1.1磁盘IO异常如何排查,类似写入慢或当前使用率较高,请查出导致磁盘IO异常高的非java进程ID

主要目的:查找占用磁盘IO服务名称及磁盘自身故障

参考实践

  1. iotop -o 查看当前正在写磁盘操作的所有服务进程id 、写入IO值、服务路径,可以通过相关参数找到对应的服务名称。
  2. 如果此时各项写入指标都很低,基本没有大的写入操作,则需要排查磁盘自身。可以查看系统dmesg 或 cat /var/log/message 看看是否有相关的磁盘异常报错,同时可以在写入慢的磁盘上touch 一个空文件看看,是否磁盘故障导致无法写入。

实践9

某服务器CPU使用率达到99%,排查是哪个程序的哪个线程导致的高CPU

参考实践

实践思路:

  1. 先找到耗CPU高的进程;
  2. 找到耗CPU高的线程;
  3. 找到耗CPU高的线程对应的业务代码;

具体操作

  1. 执行“top -c”命令,显示进程运行信息列表,键入大写P,按CPU使用率降序排列

  2. 如从步骤1中获取到进程PID为10765的进程,使用CPU资源最高30.9%;至此,已找到耗CPU最高的进程,进程PID为10765,后续命令中需要使用到

  3. 找出消耗CPU最高的线程,一个进程内有很多线程,执行“top -Hp 10765”,显示进程ID为10765的线程列表,键入大写P后,按CPU使用率降序排列

  4. 假设步骤3中,找到PID为10804的线程,CPU使用率最高;将线程ID(10804)按16进制展示,执行指令printf "%x\n" 10804(因java线程Id是以16进制显示),至此,找到了CPU使用率最高的线程ID为10804,并获取到10804的16进制标识:2a34

  5. 通过jstack检索到进程(进程ID=10765)中,最耗CPU的线程(线程ID=2a34)的线程栈信息; 执行指令jstack 10765 | grep "2a34" -C5 --color

  6. 通过上面步骤假设找到了耗CPU高的线程对应的线程名称“AsyncLogger-1”,而这个线程名称是我们业务代码中给线程取的名称,现在就可以快速定位到业务代码了。

tips:给线程取一个与业务处理相关的名称,对快速定位问题尤为重要

实践10

某java应用大量消耗内存,导致OutOfMemoryError

参考实践

实践思路:

  1. 什么对象消耗内存最大;
  2. 是否创建了太多的线程;
  3. 新生的、老年代现在内存使用情况,确认是不是整体内存分配太小了;
  4. 实时查看新生的、老年代内存使用情况,GC情况
  5. 代码层检查,是否有大对象创建?需要调用close()或dispose()来回收的资源是否回收了?

具体操作:

  • 执行“jmap -histo:live 10765 | more”命令,以表格的方式显示存活对象的信息(已按对象所占bytes大小进行降序排列):
    其中,10765为进程ID,更多用法,通过“man jmap”寻求帮助。

    tips:如果发现某类对象占用内存很大(几个G的大小),很可能是有问题的。基本都是因为:该类对象创建太多,且一直未释放。比如:使用完IO资源后,未调用close()接口关闭、释放资源;又比如:消费者消费速度慢(或停止消费了),而生产者不断往队列中投递任务,导致队列中任务累积过多,任务对象占用内存太多而产生OutOfMemoryError

  • 执行“pstree -p 10765 | wc -l”,查看进程内的线程数,其中,10765为进程ID。

    tips:每个线程需要分配线程栈内存,创建线程太多,可能导致OutOfMemoryError

  • 执行“jmap -heap 10765”,查看堆(新生代、老年代)内存分配大小及使用情况
  • 执行“jstat -gc 10765 1000”,查看各个区内存使用情况及GC情况,其中,10765为进程ID,1000为数据刷新间隔的毫秒数

    tips:具体字段含义,通过“man jstat”寻求帮助。主要查看:EC:Eden区容量,EU:Eden区已使用量,OC:Old区容量,OU:Old区已使用量;
    YGC:YongGC次数,YGCT:YongGC耗时,FGC:FullGC次数,FGCT:FullGC耗时;

文章目录
  1. 1. 背景
  2. 2. 实践1
    1. 2.1. 参考实践
    2. 2.2. 补充知识点
  3. 3. 实践2
    1. 3.1. 参考实践
  4. 4. 实践3
    1. 4.1. 参考实践
    2. 4.2. 补充知识点
  5. 5. 实践4
    1. 5.1. 参考实践
    2. 5.2. 补充知识点
  6. 6. 实践5
    1. 6.1. 参考实践
  7. 7. 实践6
    1. 7.1. 参考实践
  8. 8. 实践7
    1. 8.1. 参考实践
  9. 9. 实践8
    1. 9.1. 参考实践
  10. 10. 实践9
    1. 10.1. 参考实践
  11. 11. 实践10
    1. 11.1. 参考实践