> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Linux 进阶
- URL: https://blog.vercanti.com/linux-jin-jie/
- Published: 2026-08-28T14:34:27.000Z
- Updated: 2026-08-28T14:56:34.000Z
- Description: 最后更新：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），需特殊处理： 变量中含
- Author: yellowdog
- Tags: Linux

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

最后更新：2026-05-07

相关文档：[Linux入门](https://blog.vercanti.com/linux-ru-men-wan-quan-zhi-nan/) [Docker Compose完全指南](https://blog.vercanti.com/docker-compose-wan-quan-zhi-nan/) [Nginx完全指南](https://blog.vercanti.com/nginx-wan-quan-zhi-nan/) [GitHub Actions完全指南](https://blog.vercanti.com/github-actions-wan-quan-zhi-nan/)

---

## 1\. 进程管理

### 进程查看

```bash
# 实时监控进程
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' ' '  # 启动命令

```

### 进程信号

```bash
# 常用信号
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

```

### 进程优先级

```bash
# 以较低优先级启动（nice 值 -20 最高，19 最低）
nice -n 10 python heavy_task.py

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

```

---

## 2\. 系统资源监控

### CPU 和内存

```bash
# 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

```

### 磁盘

```bash
# 磁盘使用情况
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

```

### 网络

```bash
# 网络接口
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

```bash
# 打印特定列
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

```bash
# 替换（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 高级用法

```bash
# 正则表达式
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 脚本

### 变量与字符串

```bash
#!/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（截取）

```

### 条件判断

```bash
# 文件测试
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

```

### 循环

```bash
# 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

```

### 函数

```bash
# 定义函数
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"

```

### 实用脚本模板

```bash
#!/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）

```bash
# 编辑当前用户的 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 号午夜

```

```bash
# 使用 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\. 系统日志

```bash
# 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 — 跟踪系统调用

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

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

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

```

### lsof — 查看打开的文件

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

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

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

```

### perf — 性能剖析

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

```

---

## 8\. 安全加固

### SSH 安全配置

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

systemctl restart sshd

```

### 防火墙（ufw）

```bash
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 — 防暴力破解

```bash
# 安装
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（访问控制列表）

```bash
# 查看 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

```

### 特殊权限位

```bash
# 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 脚本健壮性三件套

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

```bash
#!/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 导致含空格的变量被拆分             |

### 日志与可观测性

```bash
# 统一日志格式：带时间戳
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-data`、`postgres`
- 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），需特殊处理：

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

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

```

### 变量引号问题

变量中含空格时，未加引号会被分割：

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

```

### 子 shell 变量不传递父 shell

```bash
# 管道每个部分都在子 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，找不到 `python3`、`npm` 等非系统默认路径的命令。  
**解决：** crontab 脚本中用绝对路径，或在脚本首行设置 `PATH`：`PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$HOME/.local/bin`。

---

## 参见

[Linux入门](https://blog.vercanti.com/linux-ru-men-wan-quan-zhi-nan/)