lsof(list open files) 查看当前系统文件、Linux下任何事物都以文件的形式存在、通过文件不仅可以访问常规数据库、还可以访问网络连接(tcp、udp等)和硬件
lsof 打开文件可以是:
- 普通文件
- 目录
- 网络文件系统的文件
- 字符或设备文件
- 共享库
- 管道、命名管道
- 符号连接
- 网络文件 (eg. NFS file、网络socket、unix 域名socket等)
- 其它类型的文件
命令参数
-a 列出打开文件存在的进程
-c<进程名>
lsof(list open files) 查看当前系统文件、Linux下任何事物都以文件的形式存在、通过文件不仅可以访问常规数据库、还可以访问网络连接(tcp、udp等)和硬件
lsof 打开文件可以是:
命令参数
-a 列出打开文件存在的进程
-c<进程名>
选项
-i any
监听所有的网卡接口、用来查看是否有网络流量-i eth0
只监听eth0网卡流量-D
显示可用的接口列表-n
不解析主机名、直接使用ip-nn
显示端口-q
显示简化输出-t
显示可读的时间戳-X
以hex
和ASCII
两种形式显示包内容-v
-vv
-vvv
显示更加多的包信息-XX
与 -X
类似、增加以太网header的显示-c
只读取x
个包, 然后停止-s
指定每个包捕获的长度、单位是 byte
, 可以使用 -s0
捕获整个包-S
输出绝对的序列号-e
获取以太网 header
-w
将捕获的数据包信息写入文件-r
加载之前保存的文件表达式
在tcpdump
中可以使用表达式过滤指定类型的流量:
host
net
port
src
dst
tcp
udp
ah
等示例
捕获所有流量
tcpdump -i any
指定网卡接口、查看指定网卡发生了什么
tcpdump -i eth0
原生输出、不解析主机、端口、显示绝对序列号、可读的时间戳
tcpdump -ttttnnvvS
查看指定ip的流量
tcpdump host {ip}
使用
源
和目的
过滤
tcpdump src {source ip}
tcpdump dst {dest ip}
过滤某个子网的数据包
tcpdump net 1.2.3.0/24
过滤指定端口相关的流量
tcpdump port {port}
tcpdump src port {port} -> 只显示发出
过滤指定协议的流量
tcpdump tcp
只显示ipv6流量
tcpdump ip6
基于包大小过滤流量
tcpdump less 32
tcpdump grater 64
tcpdump <=128
使用端口范围过滤
tcpdump portrange 21-23
保存到指定文件
tcpdump port 80 -w file
加载之前保存的文件
tcpdump -r file
高级使用
AND
: and
or &&
OR
: or
or ||
except
: not
or !
过滤指定源和目的端口
tcpdump -n src 1.1.1.2 and dst port 8080
过滤指定网络方向
tcpdump -n src net 1.1.1.2/16 and dst net 1.1.1.3/16
过滤到指定ip的非icmp报文
tcpdump dst 1.1.1.2 and src net and not icmp
构建规则过于复杂的时候、可以使用单引号将规则放到一起
tcpdump ‘src 1.1.1.1 and (dst port 80 or 22)’
隔离指定的TCP标识tcp[13]
表示在tcp header中的偏移位置13开始、后边代表的是匹配的字节数
显示所有的urgent包(URG)
tcpdump ‘tcp[13] & 32!=0’
显示所有的ACK包
tcpdump ‘tcp[13] & 16!=0’
显示所有的push包
tcpdump ‘tcp[13] & 8!=0’
显示所有的reset包
tcpdump ‘[tcp13] & 4!=0’
显示所有的SYN包
tcpdump ‘[tcp13] & 2!=0’
显示所有的FIN包
tcpdump ‘[tcp13] & 1!=0’
显示所有的SYN/ACK包
tcpdump ‘tcp[13]=18’
识别重要流量
过滤同时设置SYN和RST标识的包(这在正常情况下不应该发生)
tcpdump ‘tcp[13] = 6’
过滤明文的HTTP GET请求
tcpdump ‘tcp[32:4] = 0x47455420’
通过横幅文本过滤任意端口的SSH连接
tcpdump ‘tcp[(tcp[12]>>2):4] = 0x5353482D’
过滤TTL小于10的包(通常情况下是存在问题或者在使用traceroute)
tcpdump ‘ip[8] < 10’
过滤恶意的包
tcpdump ‘ip[6] & 128 != 0’
理解报文内容
1 | 08:41:13.729687 IP 192.168.64.28.22 > 192.168.64.1.41916: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 117964079 ecr 816509256], length 372 |
08:41:13.729687
本地时间戳ip
协议是ipv4、若是ipv6会显示为 ip6192.168.64.28.22
源ip和端口192.168.64.1.41916
目的ip和端口Flags [P.]
报文标记段seq 196:568
代表该数据包包含该数据流的第 196 到 568 字节ack 1
该数据包是数据发送方,ack 值为 1。在数据接收方,该字段代表数据流上的下一个预期字节数据,例如,该数据流中下一个数据包的 ack 值应该是 568win 309
表示接收缓冲区中可用的字节数,后跟 TCP 选项如 MSS(最大段大小)或者窗口比例值length 372
代表数据包有效载荷字节长度
flag描述
S SYN Connection Start
F FIN Connection Finish
P PUSH Data Push
. ACK Acknowledment
1 | 当系统变慢时、我们想到的很可能是 uptime 或者 top |
so. mark10:13:59
是当前时间up 303 days, 22:27
是系统允许时间
1 user
是正在登录用户数
load average: 4.61, 4.37, 3.73 这三列呢 ?
依次是 过去1min
、5min
、15min
的平均负载
1 | 知道了uptime是如何看的、那么平均负载多少算是合适 ?它又是代表什么含义呢 ? |
1 | 1. 若1min、5min、15min的值基本相同或者相差不大、说明系统负载很平稳 |
1 | 1. 命令 |
cat /proc/cpuinfo | grep 'physical id' | sort| uniq| wc -l
查看物理CPU的个数cat /proc/cpuinfo| grep "cpu cores"| uniq
查看每个物理CPU中cores的个数cat /proc/cpuinfo| grep "processor"| wc -l
查看逻辑CPU的个数
1 | uptime: |
平均负载
: 是单位时间内、系统处于可运行状态和不可中断状态的平均进程数, 即: 平均活跃进程数、和CPU的使用率无直接关系
可运行状态的进程
: 正在使用CPU或者等待CPU的进程、ps的R(Runnning / Runable) 状态
不可中断状态
: 正处于内核关键流程中的进程、且这些流程是不可打断的、eg. 等待硬件设备的IO响应、ps的D状态(Uninterruptible Sleep,即: Disk Sleep)
eg. 当一个进程向磁盘写数据时, 为了保证数据一致性、在得到磁盘回复前、是不能被打断的、若被打断, 容易出现磁盘数据和进程数据不一致
其实: 不可中断状态其实是系统堆进程和硬件设备的一种保护机制
平均负载为2怎么解读 ?
1 | 1. 在只有2个CPU的系统上、意味着CPU刚好可以全部占用 |
CPU核数查看
1 | cat /proc/cpuinfo | grep 'model name' | wc -l |
经验值: cpu 的负载到达70%的时候、就需要关注了
平均负载与CPU使用率
1 | 1. 平均负载: 单位时间内处于可运行状态和不可中断状态的进程数 |
案例分析
一、CPU密集型进程
1 | 终端一: |
二、IO密集型进程
查看方式同上
分3步完成、实现从启动盘加载操作系统、完成 main 函数加载所需要的准备工作
Q: RAM ?
A: Random Access Memory. 随机存取存储器、eg. 内存条
特点是 在加电状态下、可随意读写、断电消失
Q: 加电瞬间、RAM中无任何程序、谁来完成 操作系统从软盘的加载 ?
A: BIOS
Q: 为什么必须把操作系统从软盘加载到RAM ?
A: CPU的逻辑电路被设计为只能从内存中运行、无法直接从软盘运行
Q: 为什么CPU的逻辑电路被设计为只能从内存运行 ?
A: … 暂未清楚
Q: BIOS本身是如何启动的 ?
A: 固定地址: 0xFFFF0、
CPU逻辑上被设计为、在加电的瞬间、强行将 CS设为 0xF000, IP 设为 0xFFF0
这样、CS:IP 就指向 0xFFFF0(BIOS程序的入口地址、BIOS程序就开始运行)
开始加载操作系统….
对Linux 0.11而言、是分3步、
1: 有BIOS中断 0x19 将第一扇区bootsect的内容加载到内存
2: 在bootsect的引导下、将后边的4个扇区和240个扇区的内容依次加载到内存中
Q: 操作系统如何加载 ?
A: BIOS代码执行完毕、硬件完成开机自检、会和BIOS联手、让CPU收到 int 0x19中断、CPU在中断向量表中找到中断程序的位置(0x0E6F2)
即: 启动记载服务程序的入口地址、
so. in 0x19中断程序的作用就是把软盘第一扇区的代码512b加载到内存指定位置(BIOS设计、与操作系统无关) - 内存(0x07C00)处
第一扇区的代码作用就是将软盘中的操作系统程序陆续加载到内存、所以称为引导程序(bootsect)
第一扇区的载入、标记着操作系统代码要开始发挥作用
实模式下最大的寻址为1MB
//代码路径:boot/bootsect.s
…
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
SETUPLEN= 4 ! nr of setup-sectors
BOOTSEG = 0x07c0 ! original address of boot-sector
INITSEG = 0x9000 ! we move boot here-out of the way
SETUPSEG= 0x9020 ! setup starts here
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV:0x000 - same type of floppy as boot.
! 0x301 - first partition on first drive etc
ROOT_DEV= 0x306
…
![实模式下的内存使用规划.jpg](https://upload-images.jianshu.io/upload_images/14027542-2fd3e1e6ef913630.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
SETUPLEN
-> SETUPSEG 0x9020
(被加载到的位置)BOOTSEG(0x07c0)
(BIOS加载的位置) -> INITSEG 0x9000
(被移动到的新的位置)SYSSEG 0x1000
内核被加载的位置ENDSEG
内核末尾位置ROOT_DEV 0x306
根文件设备号
注意:
CPU的段寄存器(CS)指向 0x07C0
-> 原来 BOOTSEG 所在的位置
- 实模式: 兼容80286之后80x86的兼容CPU的模式、特性是一个20位的存储器地址空间(2^20 1MB的存储器空间可被寻址)
可以直接软件访问BIOS及周边硬件、无硬件支持的分页机制和实时多任务概念
80286 开始、所有的CPU开机都是 实模式 、之前的CPU只有一种模式、类似 实模式
- CPU: 计算机所有的计算操作都由它完成、可以理解为 一个有输入和输出功能的集成电路
- CPU寻址: 使用CS、IP两个寄存器
CS: Code Segment Register 即代码段寄存器、指向CPU当前执行代码在内存中的位置(代码段的起始位置)、
实模式为绝对地址、16位、保护模式为线性地址 需要结合GDT才能找到段基址
IP/EIP: Intruction Pointer. 指令寄存器、存在于CPU中、记录将要执行的代码在代码段中的偏移地址
实模式为绝对地址、指令指针为16位、即IP、保护模式为32位、即EIP、
CS:IP 寻址规则: 段基址*16 + 偏移地址
- 中断向量表建立
BIOS在最开始的位置(0x00000)用1k内存(0x00000 - 0x003FF)构建中断向量表、接下来256k(0x00400~0x004FF)构建BIOS数据区
大概57k后的位置(0x0E05B)加载了大概8k左右的与中断向量表相关的中断服务程序
- 中断向量表
记录所有中断向量对应中断程序的位置、实模式中断机制实现的重要部分
- 中断服务程序
通过中断向量表的索引对中断程序进行响应、是一些具有特殊功能的代码
- 磁盘磁头
利用特殊材料的电阻值会随磁场变化的原来来读写盘片数据、将硬盘盘片上的磁信号转化为电信号向外传输
$sum
: 计算总和
1 | db.mycol.aggregate([{$group : {_id:"$f1", num_tutorial:{$sum:"$f2"}}}]) |
$avg
: 计算平均值
1 | db.test.aggregate([{$group:{_id:"$field", avg:{$avg:$f}}}]) |
$min
: 获取集合中所有文档对应的最小值
1 | db.test.aggregate([{$group:{_id:"$field",min:{$min:"$f2"}}}]) |
$max
: 获取集合中所有文档对应的最大值
1 | 参考min |
$push
: 在结果文档中插入值到一个数组
1 | db.t.aggregate([{$group:{_id:"$by_user",url:{$push:"$url"}}}]) |
$first
: 根据资源文档的排序获取第一个文档数据
1 | db.t.aggregate([{$group:{_id:"$by_user",first_url:{$first:"$url"}}}]) |
$last
: 根据资源文档的排序获取最后一个文档数据
1 | 参考first |
$project
修改输出文档的结构$match
用于过滤数据、$limit
限制返回条数$skip
跳过指定条数的文档$unwind
将某个数组类型字段拆分成多条$group
将集合中的文档分组、可用于统计结果$sort
将文档排序后输出
eg.
1 | db.t.aggregate({$project:{_id:0,title:1,tags:1}}) |
1 | map :映射函数 (生成键值对序列,作为 reduce 函数参数)。 |
1 | database 数据库 |
1 | 1. show dbs 查看所有数据的列表 |
1 | mongo 192.168.1.100:27017/test |
1 | db.version() |
1 | 复制集状态查看 rs.status() |
1 | db.stats() 默认返回字节 |
1 | db.dbname.find().count() |
1 | db.getName 返回当前所在的db名称 |
1 | rs.slaveOk() |
1 | https://www.cnblogs.com/kevingrace/p/8178549.html |
1 | 在查询语句后添加 explain 即可 |
1 | queryPlanner (查询计划): 查询优化选择的计划细节和被拒绝的计划 |