8.10-11每日一讲
8月10日技术每日一讲
某进程卡死,用 kill -9 也无法杀死,可能的原因是什么?如何解决?
核心原因在于 kill -9 只杀用户态,杀不掉内核态。
可能的原因
-
不可中断睡眠(D 状态)
进程卡在D状态(uninterruptible sleep),阻塞在内核的 IO 等待上(比如 NFS 卡死、磁盘故障、FUSE 挂起)。kill -9的信号处理要等进程回到用户态才行,而 D 状态进程不响应信号。 -
僵死进程(Z 状态)
kill -9根本没用。僵尸进程已经死了,只是没被父进程wait()回收,信号发给它无意义。 -
内核线程(K 状态)
内核线程不接受 kill 信号。 -
长时间不释放的自旋锁 / 死锁的内核路径
极端情况,进程卡在内核的临界区里出不来。
排查:
# 看进程状态(D/Z 一目了然)
ps -eo pid,stat,wchan:30,cmd | grep <pid>
# D 状态看它阻塞在内核哪个函数
cat /proc/<pid>/stack
cat /proc/<pid>/wchan
cat /proc/<pid>/status | grep -i state
解决:
| 情况 | 处理 |
|---|---|
| D 状态 | 找到阻塞的 IO 挂载点,恢复网络/磁盘,或 umount -l 强制卸载,进程自动释放 |
| Z 状态 | 杀父进程(kill -9 <父pid>),让 init 回收 |
| 内核死锁 | 只能重启机器,或优先隔离节点(如果跑在 K8s) |
D 状态先查 IO,Z 状态杀父进程。
服务器无法上网(ping: unknown host www.baidu.com),请描述排查网络故障的完整步骤。
第一步:分清故障类型
ping -c 3 8.8.8.8 # 测试公网 IP
ping -c 3 www.baidu.com # 测试域名
- IP 通、域名不通 → DNS 问题
- IP 都不通 → 网络层问题,往下查
第二步:查网卡与路由
ip addr # 看网卡 IP
ip route # 看默认网关
ping -c 3 <网关IP> # 测本地链路
- 网关不通 → 物理链路、网线、交换机
- 网关通、外网不通 → 上游路由或出口防火墙
第三步:查 DNS
cat /etc/resolv.conf # 看 nameserver
nslookup www.baidu.com 8.8.8.8 # 绕开系统 DNS 直接测
- 注意 systemd-resolved 会重写 resolv.conf
第四步:查路由与防火墙
traceroute -n -m 20 8.8.8.8 # 看断在哪一跳
iptables -L -n # 查防火墙规则
firewall-cmd --list-all # firewalld 场景
第五步:查系统服务
systemctl status NetworkManager
systemctl status systemd-resolved
第六步:查上游
env | grep -i proxy # 看是否有代理配置
- 确认是否被做 IP 封禁、域名白名单
总结:
- 域名不通、IP 通 → DNS
- 网关都不通 → 物理链路
- 网关通、外网 IP 不通 → 上游路由/出口防火墙
- 路由通连接不上 → 防火墙/代理/应用层
核心就是先 ping 8.8.8.8 区分 DNS 还是网络,再顺着找,通常 5 分钟内能圈定范围。
如何排查 Too many open files 错误?涉及哪些内核参数?
先定位:
dmesg -T | tail看是不是有进程疯狂开 fd。lsof +p <pid> | wc -l数某个进程占用数。cat /proc/<pid>/fd | wc -l更快,看进程级。- 全局统计:
lsof | awk '{print $1}' | sort | uniq -c | sort -rn | head找出最活跃的进程。 - 系统级当前占用:
cat /proc/sys/fs/file-nr(三列:已分配、未使用、最大)。
分清是哪种限制被卡
- EMFILE(进程级)→ 单进程 fd 数超了
ulimit -n。 - ENFILE(系统级)→ 系统全局 fd 超了
fs.file-max。 - 两者报错都常显示 "too many open files",要区分。
涉及的内核参数
| 参数 | 作用 | 建议 |
|---|---|---|
fs.file-max |
系统全局最大 fd | 按内存调,约 100K 起步 |
fs.nr_open |
单进程可设的最大 fd(硬上限) | 需大于 file-max 的期望值 |
fs.file-nr |
当前占用,只读,用于观测 | 不用改 |
fs.inotify.max_user_instances |
inotify 实例数(大量监听时报) | 默认 128 |
fs.inotify.max_user_watches |
inotify 监视上限 | 默认 65536 |
net.core.somaxconn |
socket 监听队列 | 高并发 TCP 相关 |
net.ipv4.tcp_max_syn_backlog |
SYN 半连接队列 | 同上 |
关联参数
- Nginx/Java 等软件自身还有个
worker_rlimit_nofile/ JVM 的ulimit,软件层限制也要看。 - 用
ulimit -n看当前 shell 的进程限制,改的话:- 临时:
ulimit -n 65535 - 永久:写
/etc/security/limits.conf(* soft nofile/* hard nofile)
- 临时:
总结
先用 file-nr 判断系统还是进程爆 → 再定位到具体进程 → 查它是不是 fd 泄漏(一直涨不回落)还是真高并发 → 高并发就提限制,泄漏就修代码。
如何模拟和分析 DDoS 攻击?有哪些防御手段?
一、攻击原理
DDoS 的本质:用大量分布式机器(僵尸网络)同时向目标发起请求,耗尽目标的带宽、连接数或计算资源,让正常用户无法访问。
按攻击目标分三类:
- 带宽型:UDP Flood、ICMP Flood,打爆链路带宽
- 连接型:SYN Flood、HTTP 慢速连接,占满半连接队列或连接数
- 应用型:HTTP Flood(CC 攻击)、DNS 查询 Flood,拖垮 CPU/数据库
二、模拟方法
- hping3:
hping3 -S -p 80 --flood 目标IP模拟 SYN Flood - ab / wrk:
ab -n 100000 -c 500 http://目标/模拟高并发 HTTP - slowloris:Python 脚本模拟慢速 HTTP 连接,占连接资源
- LOIC / HULK:图形化工具,适合复现应用层 Flood
- Scapy:Python 自定义构造任意报文,灵活模拟畸形包
关键:只在授权/隔离的测试环境做,避免误伤生产,也避免给自己惹法律麻烦。
三、防御手段
1. 网络层(带宽与流量清洗)
- 云厂商高防(阿里云、AWS Shield)、流量清洗中心
- 运营商黑洞/限速策略
2. TCP 连接层(防火墙/内核)
- 启用
syn_cookies:sysctl -w net.ipv4.tcp_syncookies=1 - 调大半连接队列
tcp_max_syn_backlog、缩短tcp_synack_retries - 配置 iptables 限速:
-m limit --limit 100/s - 部署反向代理(Nginx/LVS)做连接收敛和限流
3. 应用层(业务防护)
- 限流(令牌桶/漏桶)、IP 黑名单、GeoIP 拦截
- Web 应用防火墙(WAF)识别 CC 攻击和恶意特征
- CDN 缓存分发,把流量打散到边缘节点
- 验证码、人机校验、频率控制
4. 架构与应急
- 冗余部署、负载均衡、多地多活
- 实时监控告警(流量突增触发),自动化清洗策略
- 提前制定应急演练预案,明确升级路径
如何调试一个无法启动的二进制程序?
第 1 步:查缺库
ldd ./your_binary
看到 not found 就是缺动态库,装上对应库就行。
第 2 步:跑一下看退出码
./your_binary
echo $?
退出码能提示是权限、缺文件还是崩溃。
第 3 步:strace 看卡在哪
strace ./your_binary
最后失败的调用就是根因,比如打不开配置文件、权限不足。
第 4 步:崩溃用 gdb
gdb --args ./your_binary
(gdb) run
(gdb) bt # 看调用栈
顺序:ldd → echo $? → strace → gdb,九成问题在 ldd 和 strace 就能定位。
描述 ext4 和 xfs 文件系统的区别和选型建议。
区别
-
扩展能力。ext4 单文件最大 16TB,XFS 最大可达 8EB,受实际块设备限制。文件系统容量上限 XFS 也更高。
-
元数据存储。ext4 沿用传统索引节点分配方式,索引节点和目录结构相对固定。XFS 用 B+树管理元数据,扩展性和并发访问表现更优。
-
写入机制。XFS 支持延迟分配和预分配,写入大文件时能减少碎片和写放大。ext4 这方面支持不完整。
-
日志机制。两者都带日志,XFS 的元数据日志在大量并发写入时表现更好。
-
在线调整。这是关键差异。ext4 既能在线扩容也能在线缩容,XFS 只能扩不能缩。需要缩小分区时必须选 ext4。
-
碎片情况。ext4 长时间使用容易产生碎片,XFS 几乎不碎片化。
-
工具成熟度。ext4 的工具链和恢复手段更丰富成熟,XFS 相对少。
选 ext4 的场景
- 通用桌面系统、小型服务器、根分区
- 需要在线缩容或频繁调整分区大小
- 强调兼容性和工具成熟度,需要完善的故障恢复手段
选 XFS 的场景
- 大数据量文件,如数据库数据盘、视频、日志归档
- 高并发写入、追求高吞吐
- 文件系统规模很大,数百 TB 以上
- 确定只扩不缩的场景,如 RHEL 系默认
总结
追求大文件、高吞吐、长期稳定就选 XFS。需要灵活调整分区大小、强调兼容和工具成熟度就选 ext4。生产环境的数据库和 Kubernetes 持久化卷多数更偏好 XFS。
8月11日技术每日一讲:
如何手动释放 Linux 的 Page Cache 和 Slab?
手动释放 Linux 的 Page Cache 和 Slab,核心命令是 sync 配合 echo > /proc/sys/vm/drop_caches。
命令
# 先同步脏数据到磁盘,避免缓存数据丢失
sync
# 释放 Page Cache(页缓存)
echo 1 > /proc/sys/vm/drop_caches
# 释放 dentries 和 inodes(Slab 的一部分)
echo 2 > /proc/sys/vm/drop_caches
# 释放 Page Cache + dentries + inodes(最彻底)
echo 3 > /proc/sys/vm/drop_caches
参数含义
| 值 | 含义 |
|---|---|
| 1 | 仅释放 Page Cache |
| 2 | 释放 dentries(目录项)和 inodes(索引节点),即部分 Slab |
| 3 | 同时释放 Page Cache、dentries、inodes |
注意事项
- 需要 root 权限,普通用户无法写入
/proc/sys。 - 必须先用
sync:否则还没落盘的脏页被清掉会丢数据。这是关键,很多人会漏。 echo 2和echo 3只清部分 Slab(dentry/inode),不会释放 Slab 里其他对象(比如 kmem_cache)。想彻底清 Slab,要配合slabtop定位占用大户,再用drop_caches或重启相关进程。- 释放后缓存会自动重新生长,这是正常现象,不代表没释放成功。判断是否生效看
free -h的buff/cache列是否下降。 - 生产环境不建议频繁操作,会引发 IO 抖动,影响性能。
开启自动回收
# 调整脏页写回阈值
sysctl -w vm.dirty_ratio=20
sysctl -w vm.dirty_background_ratio=5
解释 CPU 的 C-states 和 P-states,它们对运维有何影响?
CPU 的 C-states 和 P-states 是两个完全不同层面的省电机制,一个是管"空闲时",一个是管"运行时",对运维的影响也不一样。
C-states,管的是 CPU 核心空闲时怎么休眠。C0 是正常工作状态,之后依次加深:C1 只是停止执行指令,唤醒极快;C1E 开始降压降频;C3 会把一部分缓存关掉;最深的是 C6,直接清空缓存彻底断电。核心规律是状态越深越省电,但唤醒延迟越大,最深的状态唤醒可能要几十微秒到毫秒级。
P-states,管的是 CPU 在运行(C0)时用多快的频率干活。P0 是最高频率,往下 P1、P2 依次降频降压,由操作系统的调频器比如 intel_pstate 或者 CPUFreq governor 根据负载动态切换。频率越高性能越强,但功耗大致按频率的三次方暴涨。
对运维的实际影响,主要看业务对延迟敏不敏感。第一种是延迟敏感场景,比如数据库、Redis、低延迟交易系统。默认的深 C-states 会在请求突来时产生唤醒延迟,导致 QPS 抖动,这种环境应该限制最大 C-state,比如在系统参数里禁用 C6,让核心低频待命、随叫随到,用功耗换延迟稳定。第二种是性能吞吐场景,比如高并发计算和压测,直接把调频器切到 performance,恒定高频。第三种是功耗散热,数据中心节能要看闲置 C-state 有没有真正生效。第四种是故障排查,机器主频上不去,先查是不是 P-state 被温控或者功耗墙卡住了,或者调频器策略问题,别急着换硬件。第五种是虚拟化环境,KVM 里要把 P-states 和 C-states 正确透传给客户机,避免省电状态干扰时钟和延迟。
最佳实践一句总结:通用容器和 Web 服务用默认的省电加动态调频就够了,数据库、核心网关、实时服务要强制关掉深 C-states。再浓缩成一句话,C-states 管空闲省电,P-states 管运行性能,运维按业务延迟敏感度来做取舍。
systemd 和 sysvinit 的主要区别是什么?如何查看一个服务的依赖关系?
systemd 和 sysvinit 的主要区别:
启动方式:sysvinit 是一个脚本一个脚本串行执行,按 runlevel 里编号顺序一个个来,慢且一个失败可能影响后面。systemd 是并行启动,没有依赖冲突的服务同时拉起,启动速度快很多。
进程管理:sysvinit 靠 PID 文件和 init 脚本,只管 start、stop、restart 这种粗粒度操作。systemd 用 cgroup 统一管理,能跟踪服务所有子进程,支持开机自启、崩溃自动重启、限制 CPU 和内存。
配置方式:sysvinit 的启停脚本散落在 /etc/init.d 和各个 rc 目录。systemd 统一用 unit 文件(service、socket、timer 等)描述,集中在 system 目录,状态管理也更清楚,能明确区分 active、failed、enabled。
额外能力:systemd 多了 socket 激活、定时器、journald 统一日志、设备管理这些,sysvinit 都没有。
查看服务依赖关系:
命令:
systemctl list-dependencies sshd
列出 sshd 依赖了哪些东西,树状展开。想看反过来谁依赖它,加 --reverse:
systemctl list-dependencies sshd --reverse
想看得更精确,可以看它的 unit 文件声明,重点是 Requires(硬依赖)、Wants(软依赖)、After(启动顺序)、Before 这些字段:
systemctl cat sshd
systemctl show sshd -p Requires -p Wants -p After
区别在于:Requires 依赖失败会让服务也失败,Wants 只是尽力拉起不影响自己,After 只控制先后顺序不影响成败。
如果是老的 sysvinit(CentOS 6),直接看目录里的启停脚本和编号:
ls -l /etc/rc.d/rc3.d/
S 开头表示启动、K 表示停止,后面的数字决定执行顺序,数字小的先跑。
如何配置 Linux 系统的安全加固?
- 系统与内核层面
- 系统更新:关闭自动更新但保持内核补丁跟进,
yum update-minimal --security或apt install --only-upgrade linux-image-* - SSH 加固(最关键):
- 禁用 root 远程登录:
PermitRootLogin no - 密钥登录、关闭密码:
PasswordAuthentication no - 更换默认端口,限制
AllowUsers - 修改
/etc/ssh/sshd_config后systemctl reload sshd
- 禁用 root 远程登录:
- 防火墙:
firewalld或iptables只放行必要端口,默认拒绝
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload
- 账户与权限
- 最小权限原则:不用 root 跑日常操作,用 sudo 授权
- sudoers 细化:只给必要命令,如
visudo配置 - 口令策略:
/etc/login.defs里配置PASS_MAX_DAYS 90、PASS_MIN_LEN 12 - 锁定多余账户:检查
/etc/passwd,禁用无用系统账号
- 文件与进程防护
- SELinux / AppArmor:生产环境开启 enforcing 模式,别图省事关掉
- umask:默认设置
umask 022,敏感目录收紧 - 关键文件只读:
/etc/passwd、/etc/shadow权限 644/600 - cron 权限:限制
cron.allow,防止滥用
- 审计与监控
- auditd:开启系统审计
auditctl -w /etc/passwd -p wa -k identity
- 日志集中:
/var/log/secure关注登录失败,配合 rsyslog 转发 - 入侵检测:部署 fail2ban 防暴力破解,rkhunter 查 rootkit
- 网络与服务
- 最小化安装:
netstat/ss检查监听端口,禁用无用服务 - 关闭 ICMP 重定向、禁 ping 等 按需
- 内核参数:
/etc/sysctl.conf加固
net.ipv4.conf.all.rp_filter=1
net.ipv4.tcp_syncookies=1
kernel.randomize_va_space=2
优先级:先做 SSH 加固、防火墙、账户最小权限这三项,性价比最高;再逐步上 SELinux、auditd、fail2ban。安全加固不是一次性的,要配合定期巡检和变更记录。
如何排查 DNS 解析缓慢的问题?
1. 先确认是不是 DNS 的锅
time nslookup example.com
time dig example.com
如果耗时长(比如几百毫秒到秒级),基本确定是解析慢;如果很快,问题可能在应用层或网络层。
2. 区分「本地解析慢」还是「上游慢」
用 dig 指定不同解析源对比:
dig @223.5.5.5 example.com # 阿里 DNS
dig @8.8.8.8 example.com # Google DNS
dig @127.0.0.1 example.com # 本地 DNS(unbound/dnsmasq)
- 直接查公共 DNS 快、查本地慢 → 问题在本地 DNS 服务或缓存配置
- 全部慢 → 网络到上游的链路问题,或上游本身慢
3. 检查响应时间分项
用 dig 的统计字段看瓶颈:
dig example.com
看 Query time 和 SERVER(实际响应的是哪个服务器),判断是不是本地缓存走了转发。
4. 看缓存
systemd-resolve --status # systemd 场景
cat /etc/resolv.conf # 看 nameserver 配置
本地 DNS 是否配置了合理的缓存(TTL、缓存大小),是否频繁 cache miss。
5. 网络层排查
ping -c 5 上游DNS服务器地址 # 看 RTT 和丢包
tcpdump -i eth0 port 53 # 看是否有大量解析请求
UDP 53 被限速、MTU 问题导致分片、防火墙丢包,都会让解析变慢。
常见坑:
- resolv.conf 里配了多个失效 DNS,超时才落到下一个
- IPv6 AAAA 查询导致 IPv4 环境等待超时
- nsswitch.conf 里 hosts 顺序导致走 files 还是 dns 出错
解释 NTP 同步原理。如何检查时间是否同步?
一、同步原理
核心思路:客户端拿本地时间和服务器比对,算出差值再校准,靠的是分层时间源。
-
分层架构(Stratum):Stratum 0 是原子钟、GPS 等基准源,Stratum 1 直接连基准,Stratum 2 连 Stratum 1,以此类推。层级越高精度越低,客户端一般连 Stratum 2、3。
-
时间戳算法:客户端发请求时记录发送时间 t1,服务器收到记 t2,回包时记 t3,客户端收到记 t4。用这四个时间戳算两个关键量:
- 网络延迟:
(t4 - t1) - (t3 - t2) - 时间偏移:
((t2 - t1) + (t3 - t4)) / 2
- 网络延迟:
-
校准过程:客户端根据时间偏移调整本地时钟。偏差大时直接调(step),偏差小时平滑微调(slew),避免时间跳变影响服务。
-
连续采样:不是一次就完,而是周期性多次采样取最优结果,过滤掉网络抖动带来的误差。
二、检查时间是否同步
Linux 上按客户端不同用不同命令:
chrony(新版主流):
chronyc tracking # 看系统时间和参考源
chronyc sources -v # 看上游源状态
ntpd(传统):
ntpq -p # 看对端和偏移
ntpstat # 简版同步状态
判断要点:chronyc tracking 里看 Leap status: Normal,System time 的偏移量越小越好;sources 里 ^* 表示当前选中的主源。
快速确认:
timedatectl status # 看 "NTP synchronized: yes"