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-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),需特殊处理:
# 方法一:用 || 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,找不到 python3、npm 等非系统默认路径的命令。
解决: crontab 脚本中用绝对路径,或在脚本首行设置 PATH:PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$HOME/.local/bin。