Linux 进阶

最后更新:2026-05-07 相关文档:Linux入门(/linux-ru-men-wan-quan-zhi-nan/) Docker Compose完全指南(/docker-compose-wan-quan-zhi-nan/) Nginx完全指南(/nginx-wan-quan-zhi-nan/) GitHub Actions完全指南(/github-actions-wan-quan-zhi-nan/) 生产脚本开头始终加这三行: set -e 会让脚本在任何命令返回非零时退出。某些命令正常失败(如 grep 未找到返回 1),需特殊处理: 变量中含

分享

官方文档:https://www.kernel.org/doc/html/latest/ | man 手册:man <command>
适用版本:Ubuntu 22.04 / Debian 12(2026-05-07 核实)

最后更新:2026-05-07

相关文档:Linux入门 Docker Compose完全指南 Nginx完全指南 GitHub Actions完全指南


1. 进程管理

进程查看

# 实时监控进程
top
htop         # 更友好,需安装:apt install htop

# 查看进程树
pstree -p
ps aux --forest

# 按名称查找进程
pgrep -l nginx
pidof python3

# 查看进程详情
ps aux | grep python
ls -la /proc/<pid>/   # 进程的 /proc 目录
cat /proc/<pid>/cmdline | tr '\0' ' '  # 启动命令

进程信号

# 常用信号
kill -9 <pid>      # SIGKILL:强制终止(不可捕获)
kill -15 <pid>     # SIGTERM:优雅终止(默认)
kill -1 <pid>      # SIGHUP:重新加载配置
kill -2 <pid>      # SIGINT:等同 Ctrl+C

# 按名称批量终止
pkill nginx
pkill -f "python worker.py"

# 批量终止
killall gunicorn

进程优先级

# 以较低优先级启动(nice 值 -20 最高,19 最低)
nice -n 10 python heavy_task.py

# 修改已运行进程的优先级
renice -n 5 -p <pid>

2. 系统资源监控

CPU 和内存

# CPU 信息
lscpu
nproc   # CPU 核心数
cat /proc/cpuinfo | grep "model name" | head -1

# 内存使用
free -h
vmstat -s

# 实时监控
watch -n 1 free -h

# 内存详细使用(按进程)
ps aux --sort=-%mem | head -20

磁盘

# 磁盘使用情况
df -h              # 文件系统使用情况
du -sh *           # 当前目录各文件/目录大小
du -sh /var/log/*  # 日志目录大小

# 找出最大的目录
du -h / --max-depth=2 2>/dev/null | sort -rh | head -20

# 磁盘 I/O 监控
iostat -x 1        # 需安装 sysstat
iotop              # 按进程查看磁盘 I/O

网络

# 网络接口
ip addr
ip route

# 网络连接状态
ss -tulpn          # 监听端口
ss -antp           # 所有 TCP 连接
netstat -tulpn     # 老式命令(ss 替代)

# 实时网络流量
iftop              # 按连接查看流量
nethogs            # 按进程查看流量
nload              # 网卡总流量

# 测试连通性
ping -c 4 8.8.8.8
traceroute 8.8.8.8
curl -I https://example.com

3. 文本处理三剑客进阶

awk

# 打印特定列
awk '{print $1, $3}' file.txt

# 条件过滤
awk '$3 > 100 {print $0}' file.txt

# 自定义分隔符
awk -F: '{print $1}' /etc/passwd

# 统计
awk '{sum += $1} END {print "Total:", sum}' numbers.txt

# 复杂处理:统计 Nginx 访问日志中各 IP 请求次数
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

sed

# 替换(s 命令)
sed 's/old/new/' file.txt          # 每行第一个
sed 's/old/new/g' file.txt         # 全部替换
sed -i 's/old/new/g' file.txt      # 就地修改

# 删除行
sed '/pattern/d' file.txt          # 删除包含 pattern 的行
sed '1,5d' file.txt                # 删除第 1-5 行

# 打印指定行
sed -n '10,20p' file.txt           # 打印第 10-20 行

# 多个命令
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt

# 在指定行后插入
sed '/PATTERN/a\新增内容' file.txt

grep 高级用法

# 正则表达式
grep -E "error|warn" log.txt      # 扩展正则
grep -P "\d{4}-\d{2}-\d{2}" log.txt  # Perl 正则

# 上下文
grep -A 3 "ERROR" log.txt         # 匹配行后 3 行
grep -B 3 "ERROR" log.txt         # 匹配行前 3 行
grep -C 3 "ERROR" log.txt         # 前后各 3 行

# 统计和文件
grep -c "ERROR" log.txt           # 只输出匹配行数
grep -l "ERROR" *.log             # 只输出包含匹配的文件名
grep -r "TODO" src/               # 递归搜索

# 反转匹配
grep -v "DEBUG" log.txt           # 不含 DEBUG 的行

4. Shell 脚本

变量与字符串

#!/bin/bash
set -euo pipefail   # 推荐:出错立即退出,未定义变量报错,管道失败报错

# 变量
NAME="Alice"
echo "Hello, ${NAME}"

# 命令替换
DATE=$(date +%Y-%m-%d)
FILE_COUNT=$(ls | wc -l)

# 字符串操作
str="hello_world.txt"
echo "${str%.*}"          # hello_world(删除最后一个 . 及后面)
echo "${str##*.}"         # txt(删除最后一个 . 及前面)
echo "${str/hello/hi}"    # hi_world.txt(替换)
echo "${#str}"            # 字符串长度
echo "${str:0:5}"         # hello(截取)

条件判断

# 文件测试
if [ -f "/etc/nginx/nginx.conf" ]; then
    echo "文件存在"
fi

if [ -d "/var/log" ]; then
    echo "目录存在"
fi

# 字符串比较
if "${ENV}" == "production"; then
    echo "生产环境"
fi

# 数字比较
if [ "$COUNT" -gt 100 ]; then
    echo "超过 100"
fi

# 组合条件
if -f "$FILE" && -r "$FILE"; then
    echo "文件存在且可读"
fi

循环

# for 循环
for i in {1..10}; do
    echo "第 $i 次"
done

# 遍历文件
for file in /var/log/*.log; do
    echo "处理: $file"
    gzip "$file"
done

# while 循环
count=0
while [ $count -lt 5 ]; do
    echo "count=$count"
    ((count++))
done

# 读取文件逐行处理
while IFS= read -r line; do
    echo "处理: $line"
done < input.txt

函数

# 定义函数
log() {
    local level="$1"
    local msg="$2"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $msg"
}

# 返回值(通过 echo + $? 获取)
get_file_size() {
    local file="$1"
    if [ ! -f "$file" ]; then
        return 1   # 错误码
    fi
    stat -c%s "$file"
}

size=$(get_file_size "myfile.txt") && echo "大小: $size bytes"

实用脚本模板

#!/bin/bash
# deploy.sh — 部署脚本模板
set -euo pipefail

readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly LOG_FILE="/var/log/deploy.log"
readonly APP_DIR="/opt/myapp"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; }
die() { log "ERROR: $*"; exit 1; }

# 检查依赖
command -v docker >/dev/null 2>&1 || die "Docker 未安装"
command -v git >/dev/null 2>&1 || die "Git 未安装"

log "开始部署..."

cd "$APP_DIR" || die "目录不存在: $APP_DIR"
git pull origin main || die "Git pull 失败"

docker compose pull
docker compose up -d --remove-orphans

log "部署完成"

5. 定时任务(cron)

# 编辑当前用户的 crontab
crontab -e

# 查看当前 crontab
crontab -l

# 格式:分 时 日 月 周 命令
# ┌───── 分钟 (0-59)
# │ ┌──── 小时 (0-23)
# │ │ ┌─── 日 (1-31)
# │ │ │ ┌── 月 (1-12)
# │ │ │ │ ┌─ 周几 (0-7, 0和7都是周日)
# │ │ │ │ │
# * * * * * 命令
# 示例
0 2 * * *     /opt/backup.sh          # 每天凌晨 2 点
*/5 * * * *   /usr/bin/health-check   # 每 5 分钟
0 9 * * 1     /opt/weekly-report.sh   # 每周一 9 点
0 0 1 * *     /opt/monthly-cleanup.sh # 每月 1 号午夜
# 使用 systemd timer(比 cron 更可靠,有日志)
# /etc/systemd/system/myapp.timer
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

# /etc/systemd/system/myapp.service
[Service]
ExecStart=/opt/myapp/run.sh

systemctl enable --now myapp.timer
systemctl list-timers

6. 系统日志

# journalctl — systemd 日志
journalctl -u nginx             # 查看 nginx 服务日志
journalctl -u nginx -f          # 实时跟踪
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2026-01-01" --until "2026-01-02"
journalctl -p err               # 只看错误级别
journalctl --disk-usage         # 日志占用磁盘
journalctl --vacuum-size=1G     # 清理旧日志,保留 1G

# 传统日志文件
tail -f /var/log/syslog
tail -f /var/log/auth.log       # SSH 登录日志

# 日志轮转配置
cat /etc/logrotate.d/nginx

7. 性能分析

strace — 跟踪系统调用

# 跟踪进程的系统调用
strace python3 script.py
strace -p <pid>          # 附加到已运行的进程

# 只显示特定系统调用
strace -e trace=open,read,write python3 script.py

# 统计各系统调用耗时
strace -c python3 script.py

lsof — 查看打开的文件

# 查看进程打开的文件
lsof -p <pid>

# 查看谁在使用某文件
lsof /var/log/nginx/access.log

# 查看某端口被哪个进程占用
lsof -i :8080
lsof -i :8080 -t   # 只输出 pid

perf — 性能剖析

# CPU 性能剖析
perf stat python3 script.py          # 统计 CPU 事件
perf record python3 script.py        # 采样记录
perf report                          # 查看报告(火焰图)

8. 安全加固

SSH 安全配置

# /etc/ssh/sshd_config
PermitRootLogin no          # 禁止 root SSH 登录
PasswordAuthentication no   # 禁止密码登录,只允许密钥
PubkeyAuthentication yes
Port 2222                   # 修改默认端口
AllowUsers alice bob        # 只允许特定用户

systemctl restart sshd

防火墙(ufw)

ufw enable
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp            # SSH
ufw allow 80/tcp            # HTTP
ufw allow 443/tcp           # HTTPS
ufw allow from 192.168.1.0/24   # 允许内网
ufw status verbose

fail2ban — 防暴力破解

# 安装
apt install fail2ban

# /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 3
bantime = 3600
findtime = 600

systemctl enable --now fail2ban
fail2ban-client status sshd    # 查看封禁状态

9. 文件权限进阶

ACL(访问控制列表)

# 查看 ACL
getfacl /var/www/html

# 给特定用户加权限(不改变 owner/group)
setfacl -m u:deploy:rwx /var/www/html
setfacl -m g:developers:rx /opt/app

# 默认 ACL(新创建的文件继承)
setfacl -d -m u:deploy:rwx /var/www/html

# 删除 ACL
setfacl -x u:deploy /var/www/html
setfacl -b /var/www/html   # 删除所有 ACL

特殊权限位

# SUID:以文件所有者权限执行(passwd 命令用此机制)
chmod u+s /usr/local/bin/mytool

# SGID:以文件所属组权限执行;目录:新建文件继承父目录组
chmod g+s /shared/project/

# Sticky Bit:只有文件所有者才能删除(/tmp 使用)
chmod +t /shared/uploads/

# 查看特殊权限(s/S/t/T)
ls -la /tmp        # drwxrwxrwt → t 是 sticky bit
ls -la /usr/bin/passwd  # -rwsr-xr-x → s 是 SUID

最佳实践

Shell 脚本健壮性三件套

生产脚本开头始终加这三行:

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
选项 效果
set -e 任何命令返回非零立即退出
set -u 使用未定义变量时立即退出(防止 rm -rf /$UNDEFINED_VAR/
set -o pipefail 管道中任意命令失败时整体返回非零
IFS=$'\n\t' 防止 word splitting 导致含空格的变量被拆分

日志与可观测性

# 统一日志格式:带时间戳
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
}

log "INFO: Starting deployment..."
log "ERROR: Failed to connect database"

# 脚本执行全程记录
exec > >(tee -a /var/log/deploy.log) 2>&1

权限最小化原则

  • 应用程序使用专用服务账户(非 root),如 www-datapostgres
  • SSH 禁用 root 登录:PermitRootLogin no
  • 使用 sudo 按需提权,配合 /etc/sudoers.d/ 细粒度配置
  • 生产服务器防火墙只开放必要端口(22、80、443),其余一律 DROP

性能排查优先顺序

1. CPU 占用高?     → top / htop → perf top → 火焰图
2. 内存不足?       → free -h → /proc/meminfo → 查 OOM 日志
3. 磁盘 I/O 高?    → iotop / iostat -x 1 → 定位进程和文件
4. 网络延迟/丢包?  → ping / traceroute → ss -tnp → tcpdump
5. 系统调用瓶颈?   → strace -p <pid> → 找到阻塞的 syscall

重要文件和目录速查

路径 用途
/etc/systemd/system/ 自定义 systemd 单元文件
/var/log/syslog 系统日志
/var/log/auth.log 认证日志(SSH 登录记录)
/proc/sys/ 内核参数(可通过 sysctl 修改)
/etc/security/limits.conf 进程资源限制(ulimit)
~/.ssh/authorized_keys SSH 公钥认证
/etc/cron.d/ 系统级定时任务

10. 踩坑与注意事项

set -e 与命令失败

set -e 会让脚本在任何命令返回非零时退出。某些命令正常失败(如 grep 未找到返回 1),需特殊处理:

# 方法一:用 || true 忽略失败
grep "pattern" file.txt || true

# 方法二:单独关闭
set +e
grep "pattern" file.txt
FOUND=$?
set -e

变量引号问题

变量中含空格时,未加引号会被分割:

FILE="my file.txt"
cat $FILE      # 错误:cat: my: No such file; cat: file.txt: No such file
cat "$FILE"    # 正确

子 shell 变量不传递父 shell

# 管道每个部分都在子 shell 中运行
count=0
cat file.txt | while read line; do
    ((count++))   # 修改的是子 shell 的 count
done
echo "$count"   # 仍为 0

# 解决:用进程替换
while read line; do
    ((count++))
done < file.txt

常见陷阱

陷阱:rm -rf 误删根目录

现象: 执行 rm -rf /rm -rf $MYDIR/ 时变量为空,导致删除整个文件系统。
原因: Shell 变量展开为空时,路径变为 /,加上 --no-preserve-root 或老版本 rm 会直接删除。
解决: 始终用 ${MYDIR:?变量未设置} 语法验证变量非空;敏感操作前先 echo 确认展开结果;用 trash-cli 替代 rm 做软删除。

陷阱:管道中的 exit 只退出子 Shell

现象: cat file | while read line; do exit 1; done 之后脚本继续执行,没有真正退出。
原因: 管道右侧的命令在子 Shell 中运行,exit 退出的是子 Shell 而非脚本本体。
解决: 用进程替换替代管道:while read line; do exit 1; done < file;或将退出逻辑放到管道外的变量中传递。

陷阱:cron 任务在交互式 Shell 中正常但 crontab 中失败

现象: 脚本手动运行正常,添加到 crontab 后报 command not found 或静默失败。
原因: cron 的环境极简(PATH=/usr/bin:/bin),没有 .bashrc 和用户 PATH,找不到 python3npm 等非系统默认路径的命令。
解决: crontab 脚本中用绝对路径,或在脚本首行设置 PATHPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$HOME/.local/bin


参见

Linux入门

阅读更多

Web 安全基础

1. HTML 转义(服务端渲染必须): 2. CSP(Content Security Policy): 3. HttpOnly Cookie:防止 JS 读取会话 Cookie: 4. 前端框架防护: 攻击者在第三方网站构造一个表单,诱导已登录用户提交,浏览器会自动携带目标站的 Cookie。 触发条件: 1. 用户已登录目标网站(Cookie 有效) 2. 目标 API 仅凭 Cookie 识别用户身份 3. 请求来源未验证 1. CSRF Token(推荐): 2. SameSite Cookie: 3. 验证 Origin/Referer 头:

By yellowdog

HTTP 协议深度指南

HTTP(HyperText Transfer Protocol)是 Web 的基础传输协议,基于 TCP/IP,采用请求/响应模型。 相关文档:Web安全基础(/web-an-quan-ji-chu/) FastAPI完全指南(/fastapi-wan-quan-zhi-nan/) Nginx完全指南(/nginx-wan-quan-zhi-nan/) 幂等性:多次执行相同请求,服务器状态结果相同。PUT /users/1 多次执行结果一致;POST /users 每次创建新资源,非幂等。 浏览器直接从本地缓存读取,不向服务器发送请求。 缓存命中时,状

By yellowdog

系统设计基础

SLA 对照表: 选择建议:无状态服务(Web 层、API 层)优先水平扩展;数据库初期垂直扩展,达到瓶颈后考虑分库分表或读写分离。 缓存穿透(查询不存在的 key,每次都打到 DB): 缓存击穿(热点 key 过期,瞬间大量请求打到 DB): 缓存雪崩(大量 key 同时过期,或缓存服务宕机): 令牌桶 Python 实现: Redis 实现分布式限流(滑动窗口): URL 命名规则: Cursor 分页响应格式: 雪花算法结构(64 bit): 定义:分布式系统不能同时满足以下三个特性: 在分布式环境中 P 是必须保证的,所以实际是 CP vs AP

By yellowdog

算法思路与模板

二分查找要求序列有序,每次将搜索范围缩减一半,时间复杂度 O(log n)。 两个指针从两端向中间收缩,常用于有序数组。 滑动窗口维护一个满足条件的区间 left, right,right 不断向右扩张,条件不满足时收缩 left。 滑动窗口通用框架: 1. 确定"子问题":原问题可以分解为哪些规模更小的同类问题 2. 定义 dpi 或 dpij 的含义,要足够清晰 3. 推导状态转移方程 4. 确定初始状态(边界条件) 5. 确定计算顺序(确保依赖的子问题先计算) 每件物品最多选一次。dpj = 容量为 j 时的最大价值,逆序遍历容量防止重复选取。 每

By yellowdog