模块 01

Linux 系统

服务器世界的通用语言。这一页解决三个问题:东西放在哪、怎么高效操作、出问题怎么查。

8 个章节 命令驱动 适合有基础想系统化的同学

01目录结构与规范

一切皆文件。先搞清楚文件系统的骨架,后面所有操作才有坐标系。

Linux 只有一个根目录 /,所有设备、分区都挂载到这棵树上。理解目录职责,能避免「把数据放错地方」这类低级事故。

目录用途备注
/bin /sbin基础命令现代发行版多软链到 /usr/bin
/etc配置文件改配置优先来这里
/home /root普通用户 / root 家目录业务数据不放这里
/var可变数据:日志、缓存、队列/var/log 是排障第一站
/usr安装的软件与库/usr/local 放手工编译软件
/opt第三方独立软件整体安装、整体删除
/tmp临时文件可能被系统定期清理,别存重要数据
/proc /sys内核与进程的虚拟文件系统只存在于内存,用于查看运行时状态
/dev设备文件/dev/sda/dev/null

查看目录占用的两条命令

# 树形展示两层目录
tree -L 2 -d /etc

# 按大小排序查看当前目录各子目录占用(人类可读)
du -sh ./* 2>/dev/null | sort -hr | head -10

# 整盘使用率
df -hT
💡

df -h 看的是文件系统剩余空间,du -sh 看的是文件实际占用。两者差异大,通常是有进程持有已删除文件的句柄(lsof | grep deleted 可验证)。

02文件与目录操作

最高频的一类命令,目标是脱离鼠标、键盘完成一切。

基础操作

ls -alh              # 详细列表,人类可读大小,含隐藏文件
cd -                 # 回到上一个目录
cp -a src/ dst/      # 递归复制并保留权限、时间戳
mv old.txt new.txt   # 重命名 / 移动
rm -i file           # 删除前确认(推荐加 alias)
ln -s /opt/app/current /opt/app/run   # 软链接,常用于版本切换

mkdir -p /data/app/{logs,conf,data}   # 一次创建多级 + 多目录
🚫

高危:rm -rf /rm -rf $VAR/(VAR 为空时会变成删根)。写删除命令时坚持三个习惯:变量加引号并校验、先 ls 确认、必要时用 -i

查找:find 与 locate

# 按名称 + 类型查找
find /var/log -type f -name "*.log" -size +100M

# 按修改时间查找(7 天以前)
find /data -type f -mtime +7

# 查找到后批量执行(比 xargs 更安全,可配合 -print0 处理空格文件名)
find /tmp -name "*.tmp" -print0 | xargs -0 rm -f

# 数据库索引查找,速度快但可能不是最新
locate nginx.conf
sudo updatedb        # 手动重建索引

查看文件内容的取舍

命令场景
cat小文件、配合管道
less大文件阅读,支持 / 搜索、G 跳尾、q 退出
head -n 50看开头,如日志头部有启动信息
tail -f / tail -F实时追踪日志;-F 在文件被切割重建后仍能跟踪
wc -l统计行数,比大小更能反映日志量

03用户、权限与属主

权限问题是非 root 用户 80% 报错的根因。

执行 ls -l 会看到 -rwxr-xr-- 这样的 10 个字符:第 1 位是类型(- 文件、d 目录、l 软链),后面 9 位每 3 位一组,分别代表属主、属组、其他人的 r/w/x。

数字权限含义
4r
2w
1x执行 / 对目录表示可进入
chmod 644 app.conf        # rw-r--r--
chmod 755 deploy.sh       # rwxr-xr-x
chmod +x script.sh        # 追加执行权限
chmod -R u+w,g-w dir/     # 用符号模式微调

chown appuser:appgroup -R /data/app
chgrp devs report.txt

umask                     # 默认权限掩码,普通用户通常 0022

# 特殊权限
chmod u+s /usr/bin/passwd # setuid:以属主身份执行
chmod g+s /data/share     # setgid:目录下新建文件继承属组
chmod +t /data/share      # sticky:仅属主可删除自己的文件,如 /tmp

提权与切换

sudo -u appuser whoami    # 以指定用户身份执行
sudo -i                   # 切换到 root 的登录 shell
su - appuser              # 完全切换用户(加载其环境变量)

# 只读 /etc/sudoers,务必用 visudo 编辑(会做语法校验)
sudo visudo
⚠️

看到 Permission denied 先执行 namei -l /path/to/file,它会逐级列出每一层目录的权限。目录缺少 x 权限时,即使文件本身可读也访问不了。

04进程与 systemd

服务起不来、进程杀不掉、开机不自动运行,都在这一节。

进程查看与信号

ps -ef | grep java                       # 传统写法
ps aux --sort=-%mem | head              # 按内存排序
pgrep -af java                          # 直接按名字找 PID 并显示命令行
pstree -p 1234                          # 看进程树,判断父子关系

top                                     # 交互式,按 M 内存排序、P CPU 排序、1 展开核心
kill -15 1234                           # SIGTERM,优雅退出(首选)
kill -9 1234                            # SIGKILL,强杀,可能丢数据
pkill -f "app.jar"                      # 按命令行匹配杀进程

nohup java -jar app.jar > app.log 2>&1 &   # 后台常驻(简易方案)
jobs / fg / bg                          # 作业控制

systemd 管理服务

生产环境更推荐用 systemd 托管进程:开机自启、崩溃重启、日志统一收集。

# /etc/systemd/system/myapp.service
[Unit]
Description=My Java Application
After=network.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/app
ExecStart=/usr/bin/java -jar /opt/app/app.jar
Restart=on-failure
RestartSec=5
SuccessExitStatus=143
Environment="JAVA_OPTS=-Xms512m -Xmx1g"
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload       # 改完 unit 文件必须执行
sudo systemctl enable --now myapp  # 开机自启并立即启动
systemctl status myapp             # 查看状态与最近日志
systemctl restart myapp
journalctl -u myapp -f             # 实时跟踪服务日志
journalctl -u myapp --since "10 min ago" -p err   # 只看错误级别
💡

Restart=on-failure 只在非正常退出时重启。若 Java 进程收到 SIGTERM(143)退出属于正常,需用 SuccessExitStatus 显式声明,否则会被反复重启。

05文本三剑客:grep / sed / awk

日志分析的核心武器,能省下大量「肉眼找」的时间。

grep:过滤

grep -rn "TODO" src/               # 递归 + 显示行号
grep -i "error" app.log            # 忽略大小写
grep -v "^#" nginx.conf            # 排除注释行
grep -c "500 " access.log          # 统计匹配行数
grep -A3 -B1 "Exception" app.log   # 显示匹配行前后 3 行 / 1 行
grep -E "Timeout|Refused" app.log  # 扩展正则,多关键词
grep -o '"[A-Z]*"' file            # 只输出匹配部分

sed:替换与提取

sed -n '100,200p' app.log                 # 打印 100-200 行
sed 's/localhost/10.0.0.5/g' conf.txt     # 全局替换(仅输出,不改文件)
sed -i.bak 's/8080/9090/g' app.yml        # 原地修改并备份
sed '/^$/d' file                          # 删除空行
sed -n '/ERROR/,/END/p' app.log           # 打印两个模式之间的内容
⚠️

sed -i 会直接改文件。在关键配置上先用不带 -i 的形式确认输出,或加 .bak 备份后缀。

awk:按列处理与统计

# 打印第 1、7 列(常用:用户名、命令)
ps -ef | awk '{print $1, $7}'

# 以 : 分隔,筛选第 3 列大于 1000 的行
awk -F: '$3 > 1000 {print $1}' /etc/passwd

# 统计访问日志中各状态码出现次数
awk '{print $9}' access.log | sort | uniq -c | sort -nr

# 求某列总和
awk '{sum += $5} END {print sum/1024/1024 " MB"}' data.txt

# 输出行号与内容
awk '{printf "%5d  %s\n", NR, $0}' file

组合技:一条命令定位日志

# 统计最近 1 小时内每个接口的 TOP 10 耗时
awk -v since="$(date -d '1 hour ago' +%H:%M:%S)" '$0 >= since' app.log \
  | awk '{print $7, $NF}' \
  | sort -k2 -nr | head -10

06网络与端口排查

「服务连不上」的排查顺序:本机监听 → 防火墙 → 路由 → DNS。

查看监听与连接

ss -tulnp                    # 等价于 netstat -tulnp,更现代快速
ss -tnp state established    # 只看已建立的连接
lsof -i:8080                 # 谁占用了 8080
fuser -k 8080/tcp            # 强制结束占用该端口的进程(谨慎)

curl -v http://127.0.0.1:8080/health      # 带过程详情
curl -o /dev/null -s -w '%{http_code} %{time_total}s\n' https://example.com
telnet 10.0.0.5 3306         # 测端口连通性(未安装可用 nc -zv)

防火墙

# firewalld
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload

# ufw (Debian/Ubuntu)
sudo ufw status verbose
sudo ufw allow 8080/tcp

# iptables 查看规则(只读,勿随意修改)
sudo iptables -L -n -v --line-numbers

路由与 DNS

ip addr show                 # 查看网卡与 IP(替代 ifconfig)
ip route show                # 查看路由表与默认网关
ping -c 4 8.8.8.8            # 通 = 网络可达
ping -c 4 example.com        # 不通但上面通 = DNS 问题
cat /etc/resolv.conf         # 查看 DNS 配置
dig +short example.com       # 精确查询解析结果
traceroute example.com       # 逐跳定位链路中断位置
💡

排查顺序建议固定:ss -tulnp 确认进程是否在听 → curl 127.0.0.1 确认本机可用 → telnet 从外部测端口 → 查防火墙与安全组。逐层收敛,不要跳步。

07磁盘、内存与性能排查

掌握「四看」:看负载、看 CPU、看内存、看 IO。

整体负载

uptime
# load average: 1.20, 0.98, 0.75
# 三个值分别是 1、5、15 分钟平均负载;
# 可运行任务数 = load / 核心数,持续 > 1 说明有排队

内存

free -h
# 关注 available 列,而不是 free 列(buff/cache 可被回收)
vmstat 1 5
# si/so 持续非 0 说明正在使用交换分区,性能会明显下降

# 找出吃内存的进程
ps aux --sort=-%mem | head -5

# 定位 OOM 记录
dmesg | grep -i "out of memory"
journalctl -k | grep -i oom

CPU 与热点线程

top -H -p 1234        # 查看某进程的线程级 CPU 占用
# 找到高占用线程 TID 后,转十六进制
printf '%x\n' 12345
# 再用 jstack 定位 Java 代码
jstack 1234 | grep -A 20 "0x3039"

磁盘 IO

iostat -x 1 5
# %util 接近 100% 表示设备饱和;await 明显偏高说明有 IO 等待

iotop -o              # 找出读写最多的进程(需 root)
lsof /data/app.log    # 哪个进程打开了该文件

# 磁盘空间不足的常见位置
du -sh /var/log/* | sort -hr | head
find / -xdev -size +1G -type f 2>/dev/null   # 找出超大文件

一句话排障口诀

负载高但 CPU 不高

多为 IO 等待或锁竞争,查 iostatvmstatbwa 列。

内存持续上涨

先区分是缓存还是泄漏,看 available;再结合 pmapjmap 定位。

磁盘写满但找不到大文件

检查被删除但仍被占用的句柄:lsof | grep deleted

服务偶发超时

ss -s 的 TIME_WAIT、连接队列,以及文件描述符上限 ulimit -n

08自测清单

勾选表示已动手验证过,进度会保存在本地浏览器中。

你应该能不查资料完成以下操作

  • 用一条命令找出 /var/log 下大于 100MB 的文件
  • 解释 chmod 750 的含义,并说出 755644 的适用场景
  • namei -l 定位一次 Permission denied
  • 写一个 systemd unit 并实现开机自启 + 崩溃重启
  • awk 统计 Nginx 访问日志中状态码为 500 的请求数
  • sed -i 批量替换配置文件中的端口并保留备份
  • 按「本机监听 → 防火墙 → 路由 → DNS」顺序排查一次连接不通
  • 通过 top -H + jstack 找到 Java 进程中最耗 CPU 的代码行
  • 说出 load average 与 CPU 核心数的关系,并判断当前机器是否过载
  • 解释 freefreeavailable 的区别
🎯

完成 8 项以上,就可以进入 Java 语言 模块了。Linux 的很多能力是在真实故障中长出来的,保持记录习惯即可。