8.7-8日每日一讲

8.7-8日每日一讲

8月7日技术每日一讲:

如何实时查看系统日志?如何跟踪一个特定进程的日志输出?

实时查看系统日志

核心命令是 tail -f,配合 journalctl 按需选择:

# 实时跟踪所有系统日志(systemd 系统)
journalctl -f

# 只跟踪某个服务
journalctl -fu nginx

# 传统 syslog 文件
tail -f /var/log/messages
tail -f /var/log/syslog

常用辅助选项:

  • -n 100 先显示最近 100 行再跟踪
  • --since "5 min ago" 只看某时间段
  • grep 过滤关键词,例如 journalctl -f | grep -i error

跟踪特定进程的日志输出

分两种情况:

  1. 进程通过 systemd 管理(最常见):
journalctl -fu nginx.service
tail -f /var/log/nginx/error.log
  1. 进程直接运行在前台/后台,没有日志文件,可用 strace 或重定向:
# 用 strace 跟踪进程的所有系统调用和输出
strace -p <PID>

# 如果进程已启动,直接把它的输出重定向到文件
/path/to/program >> /var/log/app.log 2>&1 &

什么是 inode?什么情况下会导致磁盘空间充足但无法创建文件?

inode 是 Linux 文件系统里的索引节点,用来保存文件的元数据,比如文件大小、所有者、权限、时间戳,以及数据块的位置。每个文件(或目录)都对应一个 inode。

关键点:

  • 文件名和 inode 是靠目录项(dentry)关联的,真正存数据的是 inode。
  • 所以文件系统有两个独立的"容量":数据块空间inode 数量

磁盘空间充足但无法创建文件,常见原因:

  1. inode 耗尽
    文件系统创建时分配了固定数量的 inode,格了之后不能动态增加(除非用支持动态 inode 的如 Btrfs)。大量小文件会快速吃光 inode。df -i 查看。
    检查:df -i

  2. 进程打开文件句柄数(fd)达上限
    报错通常是 too many open files,受 ulimit -n/proc/sys/fs/file-max 限制。
    检查:ulimit -ncat /proc/sys/fs/file-max

  3. 目录权限/只读挂载
    目录没有写权限,或分区被 ro 重新挂载。
    检查:mount | grep rols -ld 目录

  4. 磁盘配额(quota)超限,针对用户或项目。

  5. 文件系统损坏,块已满但 inode 显示有剩余。

排查顺序:df -h 看空间,再 df -i 看 inode,最后看 ulimit 和挂载权限,基本能定位。最典型就是 inode 耗尽。


服务器磁盘 I/O 使用率100%,请描述你的排查思路和步骤。

一、先分清是哪一具体 100%

  1. iostat%util 接近 100%,表示磁盘请求持续排队,磁盘确实满负荷
  2. topiowait 高,说明 CPU 在等待磁盘,通常伴随 %util
  3. 云平台监控显示 IOPS 或吞吐打满,属于云盘性能上限被限流

二、排查步骤

  1. 定位是哪个盘、什么负载:用 iostat -x 1%utilawaitr/sw/s。重点看 await,很高说明请求在排队,是真的满了;很低则可能是瞬时抖动
  2. 找出读写进程:用 iotop -oP,没有就用 pidstat -d 1 按进程看读写速率
  3. 判断偶发还是持续:偶发多为备份、日志切割、定时任务、索引重建;持续则多为业务压力大或磁盘降级、RAID 重建、坏道

三、按现象对症

  • 大量随机写:多为数据库、日志 fsync,可调刷盘参数、优化落盘策略
  • 大量顺序读:多为数据仓库、日志分析,可上 SSD、加缓存、限并发
  • 日志疯狂写:应用刷屏打日志,降低日志级别、做轮转
  • 云盘限流:看云监控的 IOPS 上限,升配或开突发

结论:排查不能停在"看到 100%",要落到"下一步动作"。核心是看 await 区分排队型和限流型,再用 iotop 揪出元凶进程,最后针对负载类型做优化。

服务器 CPU 使用率100%,请描述你的排查思路和步骤。

第一步:确认现象和范围

先用 topuptime 看整体,重点看 load average 的三档趋势(1/5/15 分钟),判断是持续性问题还是瞬时尖峰。用 mpstat -P ALL 确认是单核打满还是多核打满,这决定了是单线程瓶颈还是资源整体耗尽。

第二步:定位进程

top -cps aux --sort=-%cpu 找到 CPU 占用最高的进程,判断占用来源:

  • 业务进程(应用服务、数据库)
  • 系统组件(内核线程、IO 进程)
  • 异常进程(挖矿、僵死、恶意脚本,需要结合lastcrontab 排查安全)

第三步:区分用户态和系统态

通过 top 的 CPU 占比(us/sy/wa/st)判断瓶颈性质:

  • us 高:应用逻辑问题,需要深入代码层
  • sy 高:系统调用或上下文切换频繁,常见于锁竞争、大量短连接
  • wa 高:表面是 CPU 100%,实则磁盘 IO 瓶颈,属于误判
  • st 高:云主机被宿主机抢占,属虚拟化层面

这一步非常关键,因为很多"CPU 100%"实际是 IO 或虚拟化问题,方向错了就白查。

第四步:线程级下钻

对目标进程用 top -Hp <pid> 找到最忙的线程,再根据技术栈深入:

  • Java:jstack 抓线程 dump,找 RUNNABLE 状态堆栈,配合 GC 日志判断是否 GC 频繁
  • 数据库:show processlist 定位慢 SQL,用 explain 看执行计划
  • 通用:perf topstrace 看热点函数和系统调用

第五步:定位根因并给出结论

最终落到具体原因,比如慢 SQL 缺索引、代码死循环、JVM 参数不合理、连接数过高导致上下文切换爆炸等,并说明对应的优化手段。


8月8日技术每日一讲:

服务器内存不足,OOM Killer 被触发,如何查看它杀掉了哪些进程?

内核在触发 OOM Killer 时,会把被杀进程的信息写进内核日志。这块记录不依赖任何应用,是内核自己的输出,所以只要找到内核日志就能看到。

日志里的核心记录包含三个关键要素:被杀进程的 PID、进程名,以及它的 oom_score_adj 值。oom_score_adj 很关键,它代表这个进程被杀的优先级,数值越大越容易被选为牺牲对象。

定位日志有两条路径。一是看实时和最近的记录,用 dmesg 就能拿到当前内核环形缓冲区里的内容,过滤 "killed process" 关键词即可,适合刚出问题立刻查的场景。二是查历史记录,走系统日志,从 journald 里过滤关键词,或者看 /var/log/messages/var/log/syslog/var/log/kern.log 这几个传统日志文件,适合事件过去之后复盘。

除了被杀进程本身,还能挖出更多信息。把 "out of memory" 关键词出现处附近的日志展开,能看到 OOM 触发那一刻系统里内存占用最高的进程清单。这能帮你判断两件事:是被杀进程自己吃满内存,还是另一个进程把内存耗尽导致它被误杀。

如何统计 /var/log/nginx/access.log 中访问量最高的前10个IP?

统计访问量最高的前10个IP,用 awk 提取 IP 字段再排序取前10即可。

awk '{print $1}' /var/log/nginx/access.log \
  | sort \
  | uniq -c \
  | sort -rn \
  | head -10

命令拆解:

  1. awk '{print $1}':默认按空格分隔,Nginx 日志第一个字段是客户端 IP。
  2. sort:排序,让相同 IP 相邻(uniq -c 依赖排序)。
  3. uniq -c:去重并统计每个 IP 出现次数。
  4. sort -rn:按出现次数倒序(-n 数值比较,-r 反序)。
  5. head -10:取前 10 行。

输出第一列是访问次数,第二列是 IP。

补充:

  • 如果 Nginx 前面有代理(如负载均衡),$1 会是代理 IP,需改用 $NF(最后一个字段,\ 转义后的真实 IP)。
  • 只统计今天或某个时间段,可以用 grep 过滤日期后再统计。
  • 想按 IP 维度看访问量,直接 awk '{print $1}' | sort | uniq -c 即可看到全部 IP 分布。

如何查找当前目录下7天以前大于100M的日志文件并删除?

查找 7 天前、大于 100M 的日志文件:

find /your/path -type f -name "*.log" -mtime +7 -size +100M
  • -type f 只匹配普通文件
  • -name "*.log" 限定日志(可按实际情况调整或去掉)
  • -mtime +7 修改时间 7 天以前(严格超过 7×24h)
  • -size +100M 大于 100MB

确认列表无误后删除:

# 方式一:find 直接删(注意 -delete 在最后)
find /your/path -type f -name "*.log" -mtime +7 -size +100M -delete

# 方式二:配合 xargs(更直观,可加日志)
find /your/path -type f -name "*.log" -mtime +7 -size +100M -print0 | xargs -0 rm -f

注意事项:

  1. -delete 必须在所有条件之后,顺序不能乱
  2. 删除前强烈建议先跑第一条命令看结果,或用 -ls 预览
  3. 如果要按访问时间用 -atime,按创建时间(Linux 无直接选项,可用 -newermt 反向表达)

如何用一个命令查看指定进程的线程数?

ps -T -p <PID>

直接看进程 PID 的线程数,输出最后一列 SPID 就是线程列表,配合 wc -l 数个数:

ps -T -p 1234 | wc -l

注意 wc -l 会把表头也算进去,所以实际线程数是结果减 1

更精确的只数线程(不计表头)用:

ps -T -p 1234 --no-headers | wc -l

命令拆解:

  • -T 显示该进程下的所有线程(含子线程)
  • -p <PID> 指定进程
  • --no-headers 去掉表头行

其他常用变体:

  • 按进程名查:ps -T -C nginx
  • 实时监控线程数:top -H -p 1234
  • 更权威的线程统计用 /procls /proc/1234/task | wc -l

三者都可以,ps -T 最直观,/proc/<pid>/task 最准确(直接就是内核线程目录数)。

描述ssh免密登录的配置过程及其原理(公私钥认证)。

SSH 免密登录核心是基于公私钥的非对称认证,替代每次都输密码的方式。

一、原理

SSH 认证本质是证明"我持有与公钥匹配的私钥",全程不传输私钥本体。

  1. 客户端生成一对密钥:私钥(自己保留,权限 600)和公钥(可公开)。
  2. 把公钥上传到服务器,追加到目标用户的 ~/.ssh/authorized_keys
  3. 连接时服务器生成随机挑战数,用该用户的公钥加密后发给客户端。
  4. 客户端用私钥解密挑战数,回传摘要(签名)。
  5. 服务器用公钥验证签名匹配,验证通过即放行,无需密码

关键点:私钥永不离开客户端,攻击者拿到公钥也无法反推私钥,这是核心安全基础。

二、配置步骤(A 机免密登录 B 机)

假设从 A 机免密 ssh 到 B 机的 buser 用户:

# 1. 在 A 机生成密钥对(已有可跳过,会询问是否覆盖)
ssh-keygen -t rsa -b 4096
# 一路回车,默认存到 ~/.ssh/id_rsa(私钥)和 id_rsa.pub(公钥)
# 安全起见建议设置 passphrase(私钥口令)

# 2. 把公钥传到 B 机(会要求输入一次 B 机密码)
ssh-copy-id buser@B机IP
# 等价于手动操作:
#   cat ~/.ssh/id_rsa.pub | ssh buser@B机IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# 3. 验证免密登录
ssh buser@B机IP
# 若设置了 passphrase,可配合 ssh-agent 避免每次输入
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa

三、权限要求

  • 服务器端:~/.ssh 权限 700authorized_keys 权限 600
  • 客户端:~/.ssh 权限 700,私钥 id_rsa 权限 600
  • 权限过宽会被 SSH 拒绝加载密钥,是免密失效最常见原因。

如何用tcpdump抓取到达主机192.168.1.1端口80的流量并保存到文件?

tcpdump 抓取到达 192.168.1.1 端口 80 的流量并保存到文件,命令如下:

sudo tcpdump -i eth0 'dst host 192.168.1.1 and tcp dst port 80' -w /tmp/http.pcap
  1. -i eth0:指定监听的网卡,换成你实际的网卡名(可用 ip aifconfig 查看)。
  2. 过滤表达式:
    • dst host 192.168.1.1:抓取目的地址是该主机的包。
    • and tcp dst port 80:同时满足 TCP 目的端口为 80(HTTP)。
    • 两个条件用 and 组合,只抓"发往该主机 80 端口"的流量。
  3. -w /tmp/http.pcap:把原始数据包写入文件(二进制格式,供 wireshark 分析)。

抓完按 Ctrl+C 停止。之后可用 -r 读取:

sudo tcpdump -r /tmp/http.pcap
  • 不加 -w 时默认在终端打印包内容;-w 存的是完整报文,不丢细节。
  • 如果只想看交互过程,可加 -A(ASCII)或 -X(十六进制)打印内容。
  • 文件是 pcap 格式,直接拷贝到本机用 Wireshark 打开即可分析。

如何用sed命令将文本中所有的foo替换为bar,但忽略包含baz的行?

sed 加地址范围(! 取反)实现,在模式空间里先做匹配,非 baz 行才执行替换。

sed '/baz/!s/foo/bar/g' 文件
  1. /baz/:正则地址,匹配包含 baz 的行
  2. !:取反,即匹配 baz 的行才执行后面的命令
  3. s/foo/bar/g:把 foo 替换为 bar,g 表示一行内全部替换而非只替换首个

逻辑就是巴az 行原样保留,其余行里的 foo 全部变成 bar。

若只想整行不处理但允许行内出现 foo 时不改,如上即可。若希望跳过的是全局大小写无关的 baz,加 I 修饰符:

sed '/baz/I!s/foo/bar/g' 文件

复杂度换行则用 { } 分组,但单条命令以上写法最简洁。

Read more

Linux 运维文件写入操作

Linux 运维文件写入操作

面向 Linux 运维/SRE 的文件写入操作参考手册。既讲每条命令怎么用,也讲它背后的机制(为什么这么行为),配真实输出示例与边界情况,最后给出常见陷阱速查表与标准动作模板。 目录 1. 总览:运维"写文件"的全景 2. Shell 重定向:机制与基础符号 3. 重定向顺序的坑:为什么 2>&1 > f 不行 4. 文件描述符与 exec:持久打开、交换、关闭 5. 防止误覆盖:noclobber 与 >| 6. Here 文档与 Here 字符串 7. tee:

By Admin
Linux 定时任务(附学习指南)

Linux 定时任务(附学习指南)

Linux 系统的定时任务(Scheduled Tasks)是运维和开发中最常用的自动化手段之一。系统中最核心的两套定时任务工具是 cron(定时器) 和 at(一次性任务队列)。下面从原理到实战逐层展开。 一、cron:周期性定时任务 1. cron 是什么 cron 是一个守护进程(daemon),负责在约定的时间点自动执行用户定义的任务。它对应的服务名在大多数发行版中是 crond,相关的命令和文件包括: 命令/文件 作用 crond cron 守护进程 crontab 用户管理自己的定时任务 /etc/crontab 系统级定时任务(注意有用户字段,格式不同) /etc/cron.d/ 系统级定时任务的扩展目录(每个文件类似 /etc/crontab) /etc/cron.hourly/、daily/、weekly/

By Admin
自定义你的DSH

自定义你的DSH

DSH 界面主题定制插件 给 DSH 换一套界面主题 把设计 Token 变成所见即所得的「DIY 主题」设置面板。配色、字体、背景、阴影、圆角,改完立即生效,不用写一行代码。 GitHub 仓库 更多内容 DeepSeek Harness(DSH)是 DeepSeek 推出的 AI 编程助手框架。通过 dsh web 启动浏览器界面,就能和 AI 对话、读写文件、执行命令、规划任务。功能强大,但外观一直比较朴素,默认只有浅色、深色、跟随系统三档。 我写了一个插件 dsh-ui-customizer,把界面定制做成了所见即所得的「主题设置面板」:进入 设置

By Admin