蓝天

Linux后台开发工具箱

https://files-cdn.cnblogs.com/files/aquester/Linux后台开发工具箱.pdf 

 

目录

 

目录 1

 

1. 前言 3

 

2. 脚本类工具 3

 

2.1. sed命令-字符串文本操作 3

 

2.2. sedawk使用外部变量 4

 

2.3. awk给外部变量赋值 4

 

3. 设备类工具 4

 

3.1. 查看网卡型号 4

 

3.2. dmidecode查看所有硬件信息工具 5

 

3.3. lscpu查看cpu工具 5

 

3.4. lspci查看主板工具 5

 

3.5. lsscsi查看SCSI卡工具 5

 

4. 系统类工具 5

 

4.1. sar系统综合工具 5

 

4.2. vmstat系统级内存监测工具 5

 

4.3. iostat系统级磁盘IO监测工具 5

 

4.4. iotop进程级磁盘IO监测工具 6

 

4.5. tophtop 6

 

4.6. 定时查看CPU 6

 

4.7. 查看系统中断 6

 

4.8. 查看网卡中断 6

 

4.9. 查看中断亲和性 6

 

4.10. lsof 6

 

4.11. fuser 7

 

4.12. free查看内存工具 7

 

4.13. screenbyobutmux分屏工具 7

 

4.14. dtach 7

 

4.15. slabtop查看内核slab缓存工具 8

 

4.16. dmesg检测和控制内核环缓冲工具 8

 

4.17. dstat可取代vmstat/iostat/netstat/ifstat的工具 8

 

4.18. MultiTail类似tail的同时监控多个文档工具 9

 

4.19. Monitorix系统和网络监控工具 9

 

4.20. collectl全能性能监控工具 9

 

4.21. percona工具包 10

 

5. 磁盘工具 10

 

5.1. sysbench 10

 

5.2. sfdisk分区工具 11

 

5.3. fdisk分区工具 11

 

5.4. cfdisk分区工具 11

 

5.5. parted分区工具 11

 

5.6. gparted分区工具 11

 

5.7. SCSI工具 11

 

5.8. RAID工具 11

 

5.9. hdparm磁盘性能测试工具 12

 

5.10. mount挂载磁盘工具 12

 

5.11. mkfs创建文件系统工具 12

 

5.12. df查看磁盘容量工具 12

 

5.13. du统计目录和文件大小工具 12

 

6. 进程类工具 12

 

6.1. pwdx命令-查看工作目录 12

 

6.2. pidof命令-查看进程ID 12

 

6.3. niceionice优先级调整工具 12

 

6.4. pstack查看调用栈工具 12

 

6.5. 查看可执行程序和共享库工具 12

 

7. 性能类工具 13

 

7.1. valgrindqcachegrind内存分析工具 13

 

7.2. perf性能分析工具 13

 

7.3. 压力测试工具:abtsungsiege 13

 

8. 网络类工具 13

 

8.1. netstatss命令 13

 

8.2. ifconfigip命令 13

 

8.3. tcpdump网络抓包工具 14

 

8.4. ifstat网络流量实时查看工具 16

 

8.5. iptraf实时IP局域网监控 16

 

8.6. iftop网络带宽监控 16

 

8.7. nethogs网络带宽监控 16

 

8.8. slurm查看网络流量工具 17

 

8.9. Arpwatch以太网活动监控器 17

 

8.10. Suricata网络安全监控 17

 

8.11. Nagios网络/服务器监控 17

 

8.12. socat多功能的网络工具 17

 

8.13. mtr网络连通性判断工具 17

 

8.14. 查看网卡统计 17

 

8.15. 查看网卡RingBuffer大小 17

 

8.16. sar查看网络流量 17

 

9. /proc文件系统 17

 

9.1. /proc/meminfo 18

 

9.2. /proc/cpuinfo 18

 

9.3. /proc/PID 18

 

9.4. /proc/irq/ 18

 

9.5. /proc/net 18

 

9.6. /proc/sys/fs 18

 

9.7. /proc/sys/net 19

 

9.8. /proc/sys/vm 19

 

10. 其它 19

 

10.1. shell中函数继承问题 19

 

10.2. 查看Linux各发行版本方法 19

 

10.3. 取IP地址命令 20

 

10.4. 清除系统缓存 20

 

10.5. 查看TCP数据 20

 

10.6. 查看UDP数据 20

 

10.7. 查看socket缓冲区默认大小 20

 

10.8. 查看socket缓冲区最大大小 20

 

10.9. 找出CPU占用最高的线程 20

 

10.10. Linux上查找造成IO高负载的进程 20

 

10.11. iptables简单应用 21

 

10.12. 配置DNS客户端方法 23

 

10.13. crontab使用环境变量 24

 

11. 几种修改Linux主机名的方法 25

 

11.1. 临时修改主机名 25

 

11.2. 永久修改主机名 25

 

11.3. 区别 26

 

12. process_monitor.sh进程监控重启工具 26

 

13. 远程批量操作工具 27

 

13.1. 批量执行命令工具:mooon_ssh 28

 

13.2. 批量上传文件工具:mooon_upload 28

 

13.3. 使用示例 28

 

 

 

1. 前言

 

本文是个大杂烩,内容为日常点滴的日积月累,持续更新当中,可关注博客(https://blog.csdn.net/Aquesterhttp://aquester.blog.chinaunix.net),查看最新版本。文中的内容,可帮忙开发提升分析和定位各类问题,比如找出导致IO负载高的进程等,以及一些简单的运维工作等。

 

2. 脚本类工具

 

2.1. sed命令-字符串文本操作

 

如需直接修改文件方式替换,只需sed后带参数“-i”。

 

 

 

1) 单引号替换(特殊字符需要使用反斜线”\”进行转义

 

sed 's/原字符串/替换字符串/'

 

 

 

2) 双引号替换(如要替换的包含了“/”,则可使用“|”做分隔符)

 

sed "s/原字符串包含'/替换字符串包含'/"

 

 

 

3) 问号替换

 

sed 's?原字符串?替换字符串?'

 

 

 

4) 同时多个替换

 

不同替换间使用分号分开。

 

2.2. sedawk使用外部变量

 

x=MM

sed 's/AB/'$x'/g' filename

sed 's/AB/'"$x"'/g' filename

 

sed 's/'"$val"'//' filename

 

awk '{ print "'$x'" }' filename

 

2.3. awk给外部变量赋值

 

假设将值存在文件t中,文件t内容如下,只有一行:

 

a b c

 

 

 

需要将abc分别赋给外部变量xyz,则脚本可写成如下:

 

eval $(awk '{ printf("x=%s\ny=%s\nz=%s",$1,$2,$3); }' ./t)

echo $x

echo $y

echo $z

 

 

 

请注意printf函数中的换行符\n是必须的,起关键作用的是eval命令,它在很多场景有特别的用处。

 

3. 设备类工具

 

3.1. 查看网卡型号

 

lspci | grep -i ethernet

 

3.2. dmidecode查看所有硬件信息工具

 

3.3. lscpu查看cpu工具

 

3.4. lspci查看主板工具

 

使用示例:

 

lspci -vvv

lspci -vvv -t

 

3.5. lsscsi查看SCSI卡工具

 

4. 系统类工具

 

4.1. sar系统综合工具

 

全称“System Activity Reporter”,即系统活动情况报告,最为全面的系统性能分析工具之一,也可用来查看网络流量。

 

4.2. vmstat系统级内存监测工具

 

$ vmstat

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----

 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

 1  0 1397364 3553340 775800 22420964    0    0     0    41    0    0  6 10 84  0  0

 

4.3. iostat系统级磁盘IO监测工具

 

$ iostat

Linux 3.10.1-1-XXX-0041 (UN)      2018年12月12日  _x86_64_        (4 CPU)

 

avg-cpu:  %user   %nice %system %iowait  %steal   %idle

           6.13    0.01   10.00    0.02    0.00   83.84

 

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn

sdb               0.11         0.11         3.66    3818251  131342429

sda               6.06         1.54       158.24   55370852 5672335360

dm-0              0.00         0.03         0.02    1126394     833860

dm-5              0.00         0.00         0.00      45657       5116

dm-6              0.00         0.00         0.00      45657       5116

dm-1              0.00         0.00         0.00      45658       5110

dm-2              0.00         0.00         0.00      45658       5116

dm-3              0.00         0.00         0.00      46478       5216

dm-4              0.00         0.00         0.00      43486       3369

dm-7              0.00         0.00         0.00      43269       3361

 

4.4. iotop进程级磁盘IO监测工具

 

4.5. tophtop

 

htoptop的加强版本。

 

4.6. 定时查看CPU

 

mpstat -P ALL 1

mpstat -I SUM 1

 

 

 

示例(每秒显示一次):

 

mpstat -P ALL 1

 

4.7. 查看系统中断

 

cat /proc/interrupts

 

4.8. 查看网卡中断

 

grep eth1 /proc/interrupts |awk '{print $NF}'

 

4.9. 查看中断亲和性

 

cat /proc/irq/74/smp_affinity # 以中断74为例

 

 

 

4.10. lsof

 

全称“List Open Files”,可用来查看进程打开了哪些文件,也可用来查看一个文件被哪些进程打开了,或者一个端口是哪个进程打开的等。

 

 

 

1) 查看端口被谁占用

 

lsof -i:port,如:lsof -i:80

 

 

 

2) 显示开启文件abc.txt的进程

 

lsof abc.txt

 

 

 

3) 显示abc进程现在打开的文件

 

lsof -c abc

 

 

 

4) 显示目录下被进程开启的文件

 

lsof +d /usr/local/

 

 

 

5) 显示使用fd4的进程

 

lsof -d 4

 

 

 

6) 以UID,列出打开的文件

 

lsof -u username

 

 

 

7) 看进程号为12的进程打开了哪些文件

 

lsof -p 12

 

 

 

8) 反复执行,刷新频率为2

 

lsof -i:10888 -r 2

 

 

 

ls +r 死循环执行,直到没有结果,如已没有程序占用端口号10888

 

4.11. fuser

 

lsof有些类似的功能,可查看文件、文件系统或套接字被哪些进程打开了。

 

4.12. free查看内存工具

 

4.13. screenbyobutmux分屏工具

 

4.14. dtach

 

用来模拟screendetach的功能的小工具:http://dtach.sourceforge.net/

 

4.15. slabtop查看内核slab缓存工具

 

4.16. dmesg检测和控制内核环缓冲工具

 

4.17. dstat可取代vmstat/iostat/netstat/ifstat的工具

 

1) 示例1

 

$ dstat

You did not select any stats, using -cdngy by default.

----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--

usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw

  4   6  89   0   0   0| 746B  118k|   0     0 |   0    18B| 850  5461

  8   9  82   0   0   0|   0    92k| 111k   71k|   0     0 |6888    15k

 17  39  44   0   0   0|   0    96k| 107k   62k|   0     0 |7392    19k

  2   3  94   0   0   0|   0   484k| 124k  171k|   0     0 |6855    13k

 

 

 

2) 示例2

 

# dstat -l -m -r -c  --top-io --top-mem --top-cpu

---load-avg--- ------memory-usage----- --io/total- ----total-cpu-usage---- ----most-expensive---- --most-expensive- -most-expensive-

 1m   5m  15m | used  buff  cach  free| read  writ|usr sys idl wai hiq siq|     i/o process      |  memory process |  cpu process

0.14 0.14 0.14|2710M  407M 6067M  117G|0.01  3.34 |  0   0 100   0   0   0|process_mon 960k  639B|redis-server 412M|report_proxy 0.0

0.13 0.14 0.14|2710M  407M 6067M  117G|   0     0 |  0   0 100   0   0   0|redis-serve  13k 9360B|redis-server 412M|report_proxy 0.1

0.13 0.14 0.14|2710M  407M 6067M  117G|   0     0 |  0   0  99   0   0   0|process_mon2027k 1986B|redis-server 412M|report_proxy 0.0

0.13 0.14 0.14|2710M  407M 6067M  117G|   0     0 |  0   0 100   0   0   0|sap1002      30k  624B|redis-server 412M|report_proxy 0.1

0.13 0.14 0.14|2710M  407M 6067M  117G|   0  9.00 |  0   0  99   0   0   0|process_mon2024k 1986B|redis-server 412M|report_proxy 0.1

0.13 0.14 0.14|2715M  407M 6067M  117G|   0  28.0 |  0   1  99   0   0   0|redis-serve  38k 4339k|redis-server 412M|report_proxy 0.1

0.68 0.25 0.18|2723M  407M 6067M  117G|   0  5.00 |  1   1  98   0   0   0|crond        13M  180k|redis-server 412M|report_proxy 0.1

 

4.18. MultiTail类似tail的同时监控多个文档工具

 

4.19. Monitorix系统和网络监控工具

 

4.20. collectl全能性能监控工具

 

可以交互式地运行或作为一个守护进程或同时二者兼备地运行,可替代pstopiotopvmstat等,可以作为一个服务来监控远程机或者整个服务器集群。可使用yumapt-get安装,官网:http://collectl.sourceforge.net/

 

 

 

1) 示例1

 

collectl

 

#<--------CPU--------><-----------Disks-----------><-----------Network---------->

#cpu sys inter  ctxsw KBRead  Reads  KBWrit Writes netKBi pkt-in  netKBo pkt-out

  37  37   382    188      0      0   27144    254     45     68       3      21

  25  25   366    180     20      4   31280    296      0      1       0       0

  25  25   368    183      0      0   31720    275      2     20       0       1

 

 

 

2) 示例2

 

collectl -sjmf -oT

 

#         <-------Int--------><-----------Memory-----------><------NFS Totals------>

#Time     Cpu0 Cpu1 Cpu2 Cpu3 Free Buff Cach Inac Slab  Map  Reads Writes Meta Comm

08:36:52  1001   66    0    0   2G 201M 609M 363M 219M 106M      0      0    5    0

08:36:53   999 1657    0    0   2G 201M   1G 918M 252M 106M      0  12622    0    2

08:36:54  1001 7488    0    0   1G 201M   1G   1G 286M 106M      0  20147    0    2

 

 

 

3) 示例3

 

collectl -sn --verbose -oT

 

# NETWORK SUMMARY (/sec)

#          KBIn  PktIn SizeIn  MultI   CmpI  ErrIn  KBOut PktOut  SizeO   CmpO ErrOut

08:46:35   3255  41000     81      0      0      0 112015  78837   1454      0      0

08:46:36      0      9     70      0      0      0     29     25   1174      0      0

08:46:37      0      2     70      0      0      0      0      2    134      0      0

 

 

 

4) 示例4

 

collectl -sJ -oTm

 

#              Int    Cpu0   Cpu1   Cpu2   Cpu3   Type            Device(s)

08:52:32.002   225       0      4      0      0   IO-APIC-level   ioc0

08:52:32.002   000    1000      0      0      0   IO-APIC-edge    timer

08:52:32.002   014       0      0     18      0   IO-APIC-edge    ide0

08:52:32.002   090       0      0      0  15461   IO-APIC-level   eth1

 

4.21. percona工具包

 

简称PTPercona Toolkit),可用来监控MySQLMongoDB等。

 

1) 查询程序执行聚合的GDB堆栈跟踪,先进性堆栈跟踪,然后将跟踪信息汇总:

 

pt-pmp -p pid

 

 

 

2) 格式化explain出来的执行计划按照tree方式输出,方便阅读:

 

pt-visual-explain

 

 

 

3) 从log文件中读取插叙语句,并用explain分析他们是如何利用索引,完成分析之后会生成一份关于索引没有被查询使用过的报告:

 

pt-index-usage

 

5. 磁盘工具

 

5.1. sysbench

 

下载地址:https://github.com/akopytov/sysbench/releases

 

一个开源的、模块化的、跨平台的多线程性能测试工具,可以用来进行CPU、内存、磁盘I/O、线程、数据库的性能测试。目前支持的数据库有MySQLOraclePostgreSQL

 

示例:测试fsync是否为实时fsync

 

sysbench --test=fileio --file-fsync-freq=1 --file-num=1 --file-total-size=16384 --file-test-mode=rndwr prepare

sysbench --test=fileio --file-fsync-freq=1 --file-num=1 --file-total-size=16384 --file-test-mode=rndwr run

 

 

 

运行时,如果遇到警告“Did you forget to run the prepare step”,则表示需要先执行“prepare”。

 

 

 

Python脚本测试:

 

#!/usr/bin/python

# time python fsync.py

import os, sys, mmap

 

# Open a file

fd = os.open( "testfile", os.O_RDWR|os.O_CREAT|os.O_DIRECT )

m = mmap.mmap(-1, 512)

for i in range (1,1000):

   os.lseek(fd,os.SEEK_SET,0)

   m[1] = "1"

   os.write(fd, m)

   os.fsync(fd)

# Close opened file

os.close( fd )

 

5.2. sfdisk分区工具

 

示例:列出所有分区

 

# sfdisk -l

 

5.3. fdisk分区工具

 

示例:列出所有分区

 

# fdisk -l

 

5.4. cfdisk分区工具

 

具有互动式操作界面的磁盘分区工具,参数-P表示显示分区表的内容,附加参数“s”会依照磁区的顺序显示相关信息。

 

5.5. parted分区工具

 

一个由GNU开发的功能强大的磁盘分区和分区大小调整工具。

 

5.6. gparted分区工具

 

parted的图形化版本。

 

5.7. SCSI工具

 

1) dmesg |grep SCSI

 

2) lsscsi

 

5.8. RAID工具

 

1) dmesg |grep -i raid

 

2) 查看软RAIDcat /proc/mdstat

 

5.9. hdparm磁盘性能测试工具

 

使用示例:hdparm -t /dev/sda

 

5.10. mount挂载磁盘工具

 

文件/etc/fstab的内容和mount输出是一致的。

 

5.11. mkfs创建文件系统工具

 

挂载一块磁盘之前,需要先创建好文件系统。

 

5.12. df查看磁盘容量工具

 

5.13. du统计目录和文件大小工具

 

6. 进程类工具

 

6.1. pwdx命令-查看工作目录

 

根据进程ID,查看指定进程的当前工作目录(注意不是程序文件所在目录),格式:pwdx pid,如pwdx 1

 

6.2. pidof命令-查看进程ID

 

根据进程名,查看进程的ID,格式:pidof 进程名,如:pidof init

 

6.3. niceionice优先级调整工具

 

nice是进程的CPU优先级查看和调整工具,ionice是进程的IO优先级查看和调整工具。

 

6.4. pstack查看调用栈工具

 

根据进程ID,查看指定进程调用栈的工具,格式:pstack pid

 

6.5. 查看可执行程序和共享库工具

 

1) objdump

 

2) nm 经常用来查看共享库是否包含了某个符号

 

3) ldd 查看依赖关系工具

 

4) strings 列出符号

 

5) strip 删除符号表工具

 

6) readelf

 

7. 性能类工具

 

7.1. valgrindqcachegrind内存分析工具

 

开源的内存分析和性能分析工具。qcachegrind是一个valgrind辅助工具,可视化方式查看valgrind性能分析结果。

 

7.2. perf性能分析工具

 

Linux自带的功能强大的性能分析工具,可结合火焰图。使用方式,如:perf top -p pid。自带了生成SVG格式的图形化工具timechart

 

7.3. 压力测试工具:abtsungsiege

 

8. 网络类工具

 

8.1. netstatss命令

 

ss是一个可以替代netstat的网络连接查看工具(socket statistics)

 

 

 

示例1:查看TCP监听

 

netstat -lpnt

 

 

 

示例1:查看TCP连接

 

netstat -lpna

 

8.2. ifconfigip命令

 

ip是一个可以替代ifconfigroute等的网络管理工具,为iproute2套件中的一员,而ifconfignet-tools中已被废弃使用的一个命令,许多年前就已经没有维护了。

 

 

 

1) 示例1:设置一个IP

 

ip addr add 192.168.31.13/24 dev eth1

 

 

 

2) 示例2:查看设置的IP是否生效

 

ip addr show eth1

 

 

 

3) 示例3:删除IP

 

ip addr del 192.168.31.13/24 dev eth1

 

 

 

4) 示例4:查看路由表

 

ip route show

 

8.3. tcpdump网络抓包工具

 

参数“-s”指定显示多少字节的包内容。

 

 

 

1) 显示包的内容:

 

tcpdump -i eth1 -n -vv -x -e -s 600 # 仅二进制

tcpdump -i eth1 -n -vv -X -e -s 600 # 二进制和文本

 

 

 

2) 抓包保存到文件供Wireshark分析:

 

tcpdump -i eth1 -n -vv -X -e -s 600 -w x.cap

 

 

 

3) 抓取192.168.31.180端口的包:

 

tcpdump -i eth1 host 192.168.31.1 and port 80

 

 

 

4) 抓取目标IP192.168.31.1和目标端口为80端口的包:

 

tcpdump -i eth1 dst host 192.168.31.1 and dst port 80

 

 

 

5) 监听指定网卡

 

tcpdump -i eth1

 

 

 

6) 监听指定UDP端口

 

tcpdump udp port 10888

 

 

 

7) 监听指定TCP端口

 

tcpdump tcp port 80

 

 

 

8) 监听ABAC间的通讯

 

tcpdump host A and \(B or C \)

# tcpdump host 127.0.0.1 and \(127.0.0.1 or 110.240.110.18 \)

 

 

 

9) 监听A的所有通讯,但不包括AB

 

tcpdump ip A and not B

 

 

 

10) 监听A发出的所有包

 

tcpdump -i eth1 src host A

 

 

 

11) 监听所有发送到B的包

 

tcpdump -i eth1 dst host B

 

 

 

12) 监听A收到或发出的所有http

 

tcpdump tcp port 80 and host A

 

 

 

13) 列出tcpdump能够监听的网卡

 

tcpdump -D

 

 

 

14) 监听所有网卡,要求2.2或更高版本内核

 

tcpdump -i any

 

 

 

15) 详细显示捕获的信息

 

tcpdump -v

 

 

 

更详细可以使用“tcpdump -vv”和“tcpdump -vvv”。

 

 

 

16) 以十六进制和ASCII方式打印包,除了连接层头

 

tcpdump -v -X

 

 

 

17) 以十六进制和ASCII方式打印包,包括连接层头

 

tcpdump -v -XX

 

 

 

18) 限制捕获100个包

 

tcpdump -c 100

 

 

 

19) 将记录写入文件

 

tcpdump -w filename.log

 

 

 

20) 使用IP代替域名

 

tcpdump -n

 

 

 

21) 捕获每个包的100字节而不是默认的68字节

 

tcpdump -s 500

 

 

 

如果要捕获所有字节则为:tcpdump -s 0

 

 

 

22) 捕获所有广播或多播包

 

tcpdump -n "broadcast or multicast"

 

 

 

23) 捕获所有icmparp

 

tcpdump -v "icmp or arp"

 

 

 

24) 捕获arp

 

tcpdump -v arp

 

 

 

25) 捕获目标地址是192.168.0.1,端口是80443的包

 

tcpdump -n "dst host 192.168.0.1 and (dst port 80 or dst port 443)"

 

 

 

26) 捕获目标端口号在1-1023间的UDP

 

tcpdump -n udp dst portrange 1-1023

 

 

 

27) 捕获目标端口号为23的包

 

tcpdump dst port 23

 

 

 

28) 捕获目标网络为192.168.1.0/24的包

 

tcpdump -n dst net 192.168.1.0/24

 

 

 

29) 捕获源网络为192.168.1.0/24的包

 

tcpdump -n src net 192.168.1.0/24

 

8.4. ifstat网络流量实时查看工具

 

$ ifstat

#kernel

Interface        RX Pkts/Rate    TX Pkts/Rate    RX Data/Rate    TX Data/Rate

                 RX Errs/Drop    TX Errs/Drop    RX Over/Rate    TX Coll/Rate

lo                  8546 0          8546 0        11845K 0        11845K 0

                       0 0             0 0             0 0             0 0

eth1               93020 0         41717 0         8867K 0         5969K 0

                       0 0             0 0             0 0             0 0

 

8.5. iptraf实时IP局域网监控

 

8.6. iftop网络带宽监控

 

按对端IP查看网络流量。

 

8.7. nethogs网络带宽监控

 

按进程查看网络流量:https://github.com/raboof/nethogs/releases

 

8.8. slurm查看网络流量工具

 

8.9. Arpwatch以太网活动监控器

 

8.10. Suricata网络安全监控

 

8.11. Nagios网络/服务器监控

 

8.12. socat多功能的网络工具

 

全称“Socket CAT”,为netcat的加强版。

 

8.13. mtr网络连通性判断工具

 

集成了tracerouteping

 

8.14. 查看网卡统计

 

ethtool -S eth1

 

8.15. 查看网卡RingBuffer大小

 

ethtool -g eth1

 

8.16. sar查看网络流量

 

sar -n DEV 1 # 流量信息

sar -n EDEV 1 # 错误信息

sar -u 2 5 # 每2秒报告CPU使用率,共显示5行(次)

sar -I 14 -o int14.file 2 10 每2秒报告14号中断,共显示10行(次),结果写入文件int14.file

sar -f /var/log/sa/sa16 显示内存和网络统计,结果写入文件/var/log/sa/sa16

sar -A 显示所有统计

 

9. /proc文件系统

 

有关/proc的内容很庞大,系统监控需要从这里读取大量数据,这里逐步记录一些常用到的。

 

9.1. /proc/meminfo

 

内存大小和使用信息。

 

9.2. /proc/cpuinfo

 

CPU个数和频率等CPU信息。

 

9.3. /proc/PID

 

进程的各种信息,其中PID为进程ID,假设进程ID2019,则路径为“/proc/2019”。一个进程所创建和打开的文件描述符,全在/proc/PID/fd下,以Linuxinit进程为例:

 

# ls /proc/1/fd

0  1  10  11  12  13  14  15  16  17  2  20  21  22  24  25  26  27  28  29  3  30  31  32  33  34  37  38  39  4  5  6  7  8  9

 

 

 

包括进程的命令行参数等均可以这个目录下得到。

 

9.4. /proc/irq/

 

1) /proc/irq/

 

该目录下存放的是以IRQ号命名的目录,如/proc/irq/40/表示中断号为40的相关信息。

 

2) /proc/irq/[irq_num]/smp_affinity

 

该文件存放的是CPU位掩码(十六进制),修改该文件中的值可以改变CPU和某中断的亲和性。

 

3) /proc/irq/[irq_num]/smp_affinity_list

 

该文件存放的是CPU列表(十进制),注意CPU核心个数用表示编号从0开始,如cpu0cpu1等。

 

9.5. /proc/net

 

网络相关的:

 

1) /proc/net/dev

 

可用来统计网卡流量。

 

2) /proc/net/sockstat SOCKET的各类状态

 

9.6. /proc/sys/fs

 

文件系统相关:

 

1) /proc/sys/fs/file-max

 

2) /proc/sys/fs/file-nr

 

3) /proc/sys/fs/inode-nr

 

9.7. /proc/sys/net

 

网络相关:

 

1) /proc/sys/net/core/somaxconn 控制TCP监听队列大小

 

2) /proc/sys/net/ipv4/tcp_fin_timeout 控制FIN_WAIT_2状态的超时时长

 

3) /proc/sys/net/ipv4/tcp_keepalive_intvl

 

9.8. /proc/sys/vm

 

内存相关:

 

1) /proc/sys/vm/drop_caches

 

2) /proc/sys/vm/overcommit_memory

 

10. 其它

 

10.1. shell中函数继承问题

 

我们知道变量是会被子进程继承的,可以直接使用。有些情况下可能需要继承函数,以方便透明使用,方法非常简单,使用“export -f”,注意参数“-f”,它表示函数的意思,不带参数的export只针对变量。

 

function ifprop()

{

    echo ":$1=$2"

}

export -f ifprop

 

 

 

也可以使用“typeset -fx”替代“export -f”。

 

10.2. 查看Linux各发行版本方法

 

基本上各发行版本均在/etc目录下有个后缀为“-release”的文件,该文件即存储了发行版本的版本号信息,如:

 

1) SuSE

 

cat /etc/SuSE-release

 

 

 

2) Slackware

 

cat /etc/slackware-version

 

 

 

3) Redhat

 

cat /etc/redhat-release

 

10.3. 取IP地址命令

 

netstat -ie|awk /broadcast/'{print $2}'

netstat -ie|awk -F '[ :]+' /cast/'{print $4}'

netstat -ie|awk -F '[ :]+' /cast/'{print $3}'

 

10.4. 清除系统缓存

 

echo 3 > /proc/sys/vm/drop_caches

 

 

 

测试请参见:http://blog.chinaunix.net/uid-20682147-id-4209165.html

 

10.5. 查看TCP数据

 

cat /proc/net/tcp

 

10.6. 查看UDP数据

 

cat /proc/net/udp

 

10.7. 查看socket缓冲区默认大小

 

cat /proc/sys/net/core/rmem_default

 

10.8. 查看socket缓冲区最大大小

 

cat /proc/sys/net/core/rmem_max

 

10.9. 找出CPU占用最高的线程

 

ps -mp 20693 -o THREAD,tid,time | sort -rn

 

10.10. Linux上查找造成IO高负载的进程

 

1) 方法1:使用iotop工具

 

这是一个python脚本工具,使用方法如:iotop -o

 

 

 

2) 方法2:使用工具dmesg

 

使用dmesg之前,需要先开启内核的IO监控:

 

echo 1 >/proc/sys/vm/block_dump或sysctl vm.block_dump=1

 

 

 

然后可以使用如下命令查看IO最重的前10个进程:

 

dmesg |awk -F: '{print $1}'|sort|uniq -c|sort -rn|head -n 10

 

 

 

3) 方法3:使用命令“iostat -x 1“确定哪个设备IO负载高

 

# iostat -x 1 3

avg-cpu:  %user   %nice %system %iowait  %steal   %idle

           1.06    0.00    0.99    1.09    0.00   97.85

 

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util

sda          0.49  17.29  1.74  6.75   23.47  200.18    11.73   100.09    26.33     0.10   12.25   5.73   4.87

 

 

 

找“await”值最大的设备(Device),如上的结果即为sda。然后使用mount找到sda挂载点,再使用fuser命令查看哪些进程在访问,如:

 

# fuser -vm /data

 

10.11. iptables简单应用

 

iptables命令操作只对当前登录有效,如果需重启后也有效,可将操作放到/etc/rc.d/boot.local中,如:

 

/sbin/iptables -F

/sbin/iptables -A INPUT -i eth0 -p tcp --sport 80 -j ACCEPT

/sbin/iptables -A INPUT -i eth0 -p tcp -j DROP

/sbin/iptables -A INPUT -i eth0 -p udp -j DROP

 

 

 

iptables是一个链的方式从前往后判断,如果前面的规则成立就不会往后继续,所以要注意顺序,每行对应一条规则。

 

参数“-A”是Append意思,也就是追加;参数“-I”是Insert意思,也就是插入;参数“-F”是Flush意思,表示清除(即删除)掉已有规则,也就是清空。

 

 

 

查看已有的规则,执行命令:

 

iptables -L -n

 

 

 

带行号显示结果(DEL操作需要指定行号):

 

# iptables -L -n --line-number

Chain INPUT (policy ACCEPT)

num  target     prot opt source               destination

1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:443

2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:443

3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:443

4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80

5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:443

6    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8000

7    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:443

8    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:80

9    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0

10   DROP       udp  --  0.0.0.0/0            0.0.0.0/0

 

Chain FORWARD (policy ACCEPT)

num  target     prot opt source               destination

 

Chain OUTPUT (policy ACCEPT)

num  target     prot opt source               destination

 

 

 

从上可以看到,iptables有三种规则链(Chain

 

1) INPUT 用于指定输入规则,比如外部是可以访问本机的80端口

 

2) OUTPUT 用于指定输出规则,比如本机是否可以访问外部的80端口

 

3) FORWARD 用于指定端口转发规则(相当于rinetd功能),比如将8080端口的数据转到到80端口

 

 

 

参数“-I”和参数“-A”需要指定链(Chain)名,其中“-I”的链名后还需要指定第几条(行)规则。

 

可通过“-D”参数删除规则,有两种删除方式,一是匹配模式,二是指定第几条(行)。也可以通过“-R”参数修改已有规则,另外“-L”参数后也可以跟链(Chain)名,表示只列出指定链的所有规则。“-j”参数后跟的是动作,即满足规则时执行的操作,可以为ACCEPTDROPREJECTREDIRECT等。

 

 

 

iptablesINPUT链的第一行插入一条规则(可访问其它机器的80端口):

 

iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT

 

 

 

iptablesINPUT链尾追加一条规则(可访问其它机器的80端口):

 

iptables -A INPUT -p tcp --sport 80 -j ACCEPT

 

 

 

如果要让其它机器可以访问本机的80端口,则为:

 

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

 

 

 

插入前:

 

# iptables -L -n

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         

DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           

DROP       udp  --  0.0.0.0/0            0.0.0.0/0  

 

 

 

插入:

 

# iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT

 

 

 

插入后:

 

# iptables -L -n

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         

ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:80

DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           

DROP       udp  --  0.0.0.0/0            0.0.0.0/0  

 

 

 

追加前:

 

# iptables -L -n

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         

DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           

DROP       udp  --  0.0.0.0/0            0.0.0.0/0 

 

 

 

追加:

 

# iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT

 

 

 

追加后(ACCEPT将不能生效):

 

# iptables -L -n

Chain INPUT (policy ACCEPT)

target     prot opt source               destination         

DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           

DROP       udp  --  0.0.0.0/0            0.0.0.0/0 

ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp spt:80

 

 

 

删除INPUT的第3条(即第3行,执行“iptables -L INPUT --line-numbers”显示行号)规则:

 

iptables -D INPUT 3

 

10.12. 配置DNS客户端方法

 

配置DNS客户端的方法非常简单,需要修改两个文件:

 

1) 修改/etc/resolv.conf

 

在这个文件里增加DNS服务器的IP地址,格式为:nameserver  DNS服务器IP地址

 

如:

 

nameserver 192.168.1.46

 

 

 

可以有多行nameserver,如:

 

nameserver 192.168.1.46

nameserver 219.133.38.2

nameserver 219.133.38.3

 

 

 

2) 修改/etc/nsswitch.conf

 

在这个文件中增加如下内容即可:

 

hosts:          files  dns

networks:       files  dns

 

 

 

现在即可ping域名了,如:ping www.hadoopor.com。当然在ping之前要保证该机器是可以正常连接到DNS服务器的,DNS服务器的默认端口号为53,可以通过telnet命令来测试是否能够连接到DNS服务器,如:telnet 192.168.1.46 53

 

10.13. crontab使用环境变量

 

有两种方式在crontab中定义变量:

 

1) 直接在crontab中定义变量

 

A=123

* * * * * echo $A > /tmp/a.txt

 

 

 

注意在定义变量时不能使用$引用其它变量,如下面的做法错误:

 

A=123

B=$A

 

 

 

2) 在/etc/environment中定义变量

 

此文件定义变量的格式为:

 

NAME=VALUE

 

 

 

crontab,也不能使用$引用其它变量。操作系统在登录时使用的第一个文件是/etc/environment文件,/etc/environment文件包含指定所有进程的基本环境的变量。

 

千万注意,不要有“PATH=$PATH:/usr/local/jdk/bin”这样的用法,这将导致系统无法启动。

 

小技巧:想保持多台机器的crontab一致,但变量值不完全相同,这个时候可以考虑将变量配置在/etc/environment中,这样crontab就可以相同了。

 

如机器1

 

A=123

 

 

 

机器2

 

A=456

 

 

 

两者的crontab配置:

 

* * * * * echo "$A" > /x.txt

 

 

 

一般不建议直接修改/etc/environment,而可采取在目录/etc/profile.d下新增一个.sh文件方式替代。但如果想crontab中生效,则只能修改/etc/environment,经测试/etc/profile.d方式不起作用。

 

另外注意在/etc/environment设置的变量,在shell中并不生效,但对crontab有效。

 

11. 几种修改Linux主机名的方法

 

在安装一些系统时,需要修改hostname,比如安装Hadoop时需要修改主机名,而且主机名不能包含下划线。

 

实际上,主机名分三种(命令hostnamectl或hostnamectl status可查看三种主机名):

 

1) “pretty”主机名,UTF8格式的主机名,这个仅供阅读,长度无限制;

 

2) “static”主机名,日常所称的主机名(traditional hostname)。最多为64个字符,仅可包含“.”、“_”、“-”、“a-z”、“A-Z”和“0-9”这些字符,并且不能以“.”打头和结尾,也不能两个“.”连续;

 

3) “transient”主机名,内核维护的动态主机名,初始化为“static”主机名,默认为localhost。也为hadoop要求的主机名,它的约束规则同“static”主机名。如果存在“static”主机名,且不是“localhost”,那么将忽略“transient”主机名。“transient”主机名可被DHCPmDNS修改。

 

 

 

当三种主机名相同时,“hostnamectl status”只会显示“static”主机名,三种主机名的设置方法:

 

hostnamectl --pretty set-hostname NAME

hostnamectl --static set-hostname NAME

hostnamectl --transient set-hostname NAME

 

 

 

 

hostnamectl修改的主机名,在系统重启之前会一直有效,而hostname只对当次有效。如果不指定参数,则一次设置三种主机名:

 

hostnamectl set-hostname NAME

 

11.1. 临时修改主机名

 

命令hostname不但可以查看主机名,还可以用它来修改主机名,格式为:hostname 新主机名。

 

在修改之前9.4.149.11对应的主机名为hadoop_10202,而9.4.149.6对应的主机名为hadoop_10203。两者的主机名均带有下划线,因此需要修改。为求简单,仅将原下划线去掉:

 

hostname hadoop10202

 

hostname hadoop10203

 

 

 

经过上述修改后,类似于修改环境变量,只临时有效,还需要修改相应的系统配置文件,以永久有效。

 

11.2. 永久修改主机名

 

不同的Linux发行版本,对应的系统配置文件可能不同,SuSE 10.1/etc/HOSTNAME:

 

# cat /etc/HOSTNAME

hadoop_10202

 

 

 

将文件中的“hadoop_10202”,改成“hadoop10202”。有些Linux发行版本对应的可能是/etc/hostname文件,有些如CentOSRedHat同时有/etc/hostname/etc/sysconfig/network两个文件,修改/etc/hostname即可。

 

需注意:/etc/sysconfig/network的格式和/etc/hostname/etc/HOSTNAME不同,为:

 

HOSTNAME=主机名

 

 

 

修改之后,需要重启网卡,以使修改生效,执行命令:/etc/rc.d/boot.localnet start(不同系统命令会有差异,这是SuSE上的方法,其它一些可能为:/etc/init.d/network restart或service network restart等),再次使用hostname查看,会发现主机名变了。

 

上述方法如果不能永久有效,则可使用hostnamectl修改来修改永久有效。如果还是不行,则可重启系统以使永久有效。

 

 

 

可以通过以下多种方法查看主机名:

 

1) hostname命令(也可以用来修改主机名,但当次仅当次会话有效)

 

2) hostnamectl命令(也可以用来修改主机名,系统重启前一直有效)

 

3) cat /proc/sys/kernel/hostname

 

4) cat /etc/hostnamecat /etc/sysconfig/network(永久性的修改,需要重启)

 

5) sysctl kernel.hostname(也可以用来修改主机名,但仅重启之前有效)

 

 

 

批量修改/etc/hostname工具(其它可参照):

 

https://github.com/eyjian/libmooon/blob/master/shell/set_hostname.sh

 

11.3. 区别

 

方法

效果

hostname

当次登录临时有效,新登录或重新登录后无效

hostnamectl

系统重启之前一直有效,重启后无效

/etc/hostname

只有在系统重启后才有效

 

12. process_monitor.sh进程监控重启工具

 

使用process_monitor.sh监控进程,当进程挂掉后,能够在两三秒内将进程重拉起,并且支持同一程序以不同参数启动多个实例,和不同用户以相同参数启动多个实例。

 

下载:https://github.com/eyjian/libmooon/blob/master/shell/process_monitor.sh

 

一般建议将process_monitor.sh放在/usr/local/bin目录下,并设置好可执行权限,放在crontab中运行。

 

 

 

1) 示例1:监控redis进程

 

* * * * * /usr/local/bin/process_monitor.sh "/data/redis/bin/redis-server 6379" "/data/redis/bin/redis-server /data/redis/conf/redis-6379.conf"

* * * * * /usr/local/bin/process_monitor.sh "/data/redis/bin/redis-server 6380" "/data/redis/bin/redis-server /data/redis/conf/redis-6380.conf"

 

 

 

2) 示例2:监控zookeeper进程

 

* * * * * /usr/local/bin/process_monitor.sh "/usr/local/jdk/bin/java -Dzookeeper" "/data/zookeeper/bin/zkServer.sh start"

 

 

 

process_monitor.sh启动后,会在/tmp目录下创建以“/process_monitor-”打头的日志文件,假设root用户运行process_monitor.sh,则日志全路径为:/tmp/process_monitor-root.log

 

13. 远程批量操作工具

 

远程批量工具包含:

 

1) 批量命令工具mooon_ssh

 

2) 批量上传文件工具mooon_upload

 

3) 批量下载文件工具mooon_download

 

 

 

可执行二进制包下载地址:

 

https://github.com/eyjian/libmooon/releases

 

 

 

源代码包下载地址:

 

https://github.com/eyjian/libmooon/archive/master.zip

 

 

 

批量工具除由三个工具组成外,还分两个版本:

 

1) C++版本

 

2) GO版本

 

 

 

当前C++版本比较成熟,GO版本相当简略,但C++版本依赖C++运行时库,不同环境需要特定编译,而GO版本可不依赖CC++运行时库,所以不需编译即可应用到广泛的Linux环境。

 

 

 

使用简单,直接执行命令,即会提示用法,如C++版本:

 

$ mooon_ssh

parameter[-c]'s value not set

 

usage:

-h[]: Connect to the remote machines on the given hosts separated by comma, can be replaced by environment variable 'H', example: -h='192.168.1.10,192.168.1.11'

-P[36000/10,65535]: Specifies the port to connect to on the remote machines, can be replaced by environment variable 'PORT'

-u[]: Specifies the user to log in as on the remote machines, can be replaced by environment variable 'U'

-p[]: The password to use when connecting to the remote machines, can be replaced by environment variable 'P'

-t[60/1,65535]: The number of seconds before connection timeout

-c[]: The command is executed on the remote machines, example: -c='grep ERROR /tmp/*.log'

-v[1/0,2]: Verbosity, how much troubleshooting info to print

 

13.1. 批量执行命令工具:mooon_ssh

 

参数名

默认值

说明

-u

用户名参数,可用环境变量U替代

-p

密码参数,可用环境变量P替代

-h

IP列表参数,可用环境变量H替代

-P

22,可修改源码,编译为常用端口号

SSH端口参数,可用环境变量PORT替代

-c

在远程机器上执行的命令,建议单引号方式指定值,除非要执行的命令本身已经包含了单引号有冲突。使用双引号时,要注意转义,否则会被本地shell解释

-v

1

工具输出的详细度

-thr

1

线程数,当线程数大于2时,并发执行;如果值为0,表示线程数和IP数相同

 

13.2. 批量上传文件工具:mooon_upload

 

参数名

默认值

说明

-u

用户名参数,可用环境变量U替代

-p

密码参数,可用环境变量P替代

-h

IP列表参数,可用环境变量H替代

-P

22,可修改源码,编译为常用端口号

SSH端口参数,可用环境变量PORT替代

-s

以逗号分隔的,需要上传的本地文件列表,可以带相对或绝对目录

-d

文件上传到远程机器的目录,只能为单个目录

-thr

1

线程数,当线程数大于2时,并发执行;如果值为0,表示线程数和IP数相同

 

13.3. 使用示例

 

1) 使用示例1:上传/etc/hosts

 

mooon_upload -s=/etc/hosts -d=/etc

 

 

 

2) 使用示例2:检查/etc/profile文件是否一致

 

mooon_ssh -c='md5sum /etc/hosts'

 

 

 

3) 使用示例3:批量查看crontab

 

mooon_ssh -c='crontab -l'

 

 

 

4) 使用示例4:批量清空crontab

 

mooon_ssh -c='rm -f /tmp/crontab.empty;touch /tmp/crontab.empty'

mooon_ssh -c='crontab /tmp/crontab.emtpy'

 

 

 

5) 使用示例5:批量更新crontab

 

mooon_ssh -c='crontab /tmp/crontab.online'

 

 

 

6) 使用示例6:取远端机器IP

 

因为awk用单引号,所以参数“-c”的值不能使用单引号,所以内容需要转义,相对其它来说要复杂点:

 

mooon_ssh -c="netstat -ie | awk -F[\\ :]+ 'BEGIN{ok=0;}{if (match(\$0, \"eth1\")) ok=1; if ((1==ok) && match(\$0,\"inet\")) { ok=0; if (7==NF) printf(\"%s\\n\",\$3); else printf(\"%s\\n\",\$4);} }'"

 

 

 

不同的环境,IP在“netstat -ie”输出中的位置稍有不同,所以awk中加了“7==NF”判断,但仍不一定适用于所有的环境。需要转义的字符包含:双引号、美元符和斜杠。

 

 

 

7) 使用示例7:批量查看kafka进程(环境变量方式)

 

$ export H=192.168.31.9,192.168.31.10,192.168.31.11,192.168.31.12,192.168.31.13

$ export U=kafka

$ export P='123456'

 

$ mooon_ssh -c='/usr/local/jdk/bin/jps -m'

[192.168.31.15]

50928 Kafka /data/kafka/config/server.properties

125735 Jps -m

[192.168.31.15] SUCCESS

 

[192.168.31.16]

147842 Jps -m

174902 Kafka /data/kafka/config/server.properties

[192.168.31.16] SUCCESS

 

[192.168.31.17]

51409 Kafka /data/kafka/config/server.properties

178771 Jps -m

[192.168.31.17] SUCCESS

 

[192.168.31.18]

73568 Jps -m

62314 Kafka /data/kafka/config/server.properties

[192.168.31.18] SUCCESS

 

[192.168.31.19]

123908 Jps -m

182845 Kafka /data/kafka/config/server.properties

[192.168.31.19] SUCCESS

 

 

================================

[192.168.31.15 SUCCESS] 0 seconds

[192.168.31.16 SUCCESS] 0 seconds

[192.168.31.17 SUCCESS] 0 seconds

[192.168.31.18 SUCCESS] 0 seconds

[192.168.31.19 SUCCESS] 0 seconds

SUCCESS: 5, FAILURE: 0

 

 

 

8) 使用示例8:批量停止kafka进程(参数方式)

 

$ mooon_ssh -c='/data/kafka/bin/kafka-server-stop.sh' -u=kafka -p='123456' -h=192.168.31.15,192.168.31.16,192.168.31.17,192.168.31.18,192.168.31.19

[192.168.31.15]

No kafka server to stop

command return 1

 

[192.168.31.16]

No kafka server to stop

command return 1

 

[192.168.31.17]

No kafka server to stop

command return 1

 

[192.168.31.18]

No kafka server to stop

command return 1

 

[192.168.31.19]

No kafka server to stop

command return 1

 

================================

[192.168.31.15 FAILURE] 0 seconds

[192.168.31.16 FAILURE] 0 seconds

[192.168.31.17 FAILURE] 0 seconds

[192.168.31.18 FAILURE] 0 seconds

[192.168.31.19 FAILURE] 0 seconds

SUCCESS: 0, FAILURE: 5

 

posted on 2018-12-13 10:35  #蓝天  阅读(1032)  评论(0编辑  收藏  举报

导航