CS 教程 · 第 12 章

Linux 系统管理

Shell / 权限 / 服务 / 运维

学会 Linux 命令行,你就掌握了一把万能钥匙——几乎所有服务器都运行着 Linux。

无论是部署网站、管理数据库,还是运行机器学习任务,Linux 都是最主流的服务器操作系统。本章从发行版选择开始,带你掌握日常管理必备的命令和技巧。


12.1 Linux 发行版选择

Linux 不是"一个操作系统",而是一族操作系统。核心都是 Linux 内核,外围软件和包管理不同形成不同发行版(Distribution)

主流发行版家族

Debian 系                     Red Hat 系
├── Debian (稳定之选)         ├── RHEL (企业版,付费)
├── Ubuntu (最流行)           ├── CentOS Stream (RHEL 上游)
│   ├── Desktop 版           ├── Fedora (新特性尝鲜)
│   └── Server 版            └── Rocky Linux (CentOS 替代)
├── Linux Mint (桌面友好)
└── Kali Linux (安全渗透)

其他:
├── Arch Linux (滚动更新,极客之选)
├── Alpine Linux (超轻量,Docker 首选)
└── openSUSE (欧洲流行)

你该选哪个?

场景 推荐 原因
新手入门 Ubuntu Desktop 社区最大,教程最多
生产服务器 Ubuntu Server / Debian 稳定、LTS 长期支持
企业环境 RHEL / Rocky Linux 商业支持、稳定性
Docker 容器 Alpine Linux 镜像极小(~5MB)
想学底层 Arch Linux 安装过程就是学习过程

12.2 Shell 基础命令

Shell 是你和 Linux 对话的界面。打开终端,你会看到:

lou@server:~$ _
│    │    │
│    │    └── 当前目录(~ = 家目录)
│    └── 主机名
└── 当前用户

文件系统导航

# 你在哪?
pwd                          # 打印工作目录 → /home/lou

# 看看周围
ls                           # 列出文件
ls -l                        # 详细信息(权限、大小、时间)
ls -la                       # 包括隐藏文件(以 . 开头)
ls -lh                       # 人类可读的大小(K, M, G)
ls -lt                       # 按修改时间排序

# 到处走走
cd /home                     # 进入 /home 目录
cd /                         # 进入根目录
cd ~                         # 回到家目录
cd ..                        # 回到上一级
cd -                         # 回到之前所在的目录

Linux 目录结构

/                  根目录(一切从这里开始)
├── /bin            基本命令(ls, cp, cat, ...)
├── /boot           启动文件(内核、引导加载程序)
├── /dev            设备文件(磁盘、终端、USB 等)
├── /etc            系统配置文件
├── /home           用户家目录
│   └── /home/lou   我的文件在这里
├── /lib            共享库文件
├── /mnt /media     挂载点(临时挂载、USB、光盘)
├── /opt            第三方软件
├── /proc           虚拟文件系统(进程和内核信息)
├── /root           root 用户的家目录
├── /run            运行时数据(临时文件系统)
├── /sbin           系统管理命令
├── /tmp            临时文件(重启可能清空)
├── /usr            用户程序和数据
│   ├── /usr/bin    用户命令
│   └── /usr/local  本地编译安装的软件
└── /var            可变数据(日志、缓存、数据库)
    ├── /var/log    日志文件 ⭐
    └── /var/www    网站文件

文件操作

# 创建
touch file.txt               # 创建空文件
mkdir mydir                   # 创建目录
mkdir -p a/b/c                # 递归创建嵌套目录

# 查看文件内容
cat file.txt                  # 显示全部
less file.txt                 # 分页浏览(按 q 退出,/ 搜索)
head -n 20 file.txt           # 前 20 行
tail -n 20 file.txt           # 后 20 行
tail -f /var/log/syslog       # 实时追踪文件末尾(看日志神器)

# 复制和移动
cp source.txt dest.txt        # 复制文件
cp -r sourcedir/ destdir/     # 递归复制目录
mv oldname.txt newname.txt    # 移动/重命名
mv file.txt /tmp/             # 移动到 /tmp

# 删除
rm file.txt                   # 删除文件
rm -r directory/              # 递归删除目录
rm -rf directory/             # 强制删除,不提示(⚠️危险!)

# 查找
find /home -name "*.log"      # 按名称查找
find . -type f -size +10M     # 查找大于 10MB 的文件
find . -mtime -7              # 最近 7 天修改的文件
find . -name "*.tmp" -delete  # 查找并删除

# 搜索文件内容
grep "error" app.log                   # 搜索包含 error 的行
grep -i "error" app.log               # 忽略大小写
grep -r "TODO" ./src/                 # 递归搜索目录
grep -v "debug" app.log              # 排除包含 debug 的行
grep -c "error" app.log              # 统计匹配行数

# 管道和重定向
cat app.log | grep "error" | wc -l    # 管道:前一个命令输出 → 后一个命令输入
echo "hello" > file.txt               # 重定向输出(覆盖)
echo "world" >> file.txt              # 重定向输出(追加)
command 2>&1 | tee output.log        # 同时输出到终端和文件

实用命令速查

# 系统信息
uname -a                      # 系统信息
lsb_release -a                # 发行版信息(Ubuntu)
cat /etc/os-release           # 发行版信息(通用)
hostname                      # 主机名
uptime                        # 运行时间
who                           # 当前登录用户

# 磁盘和内存
df -h                         # 磁盘使用情况(人类可读)
du -sh /home/*                # 目录占用的空间
free -h                       # 内存使用情况
lsblk                         # 列出块设备(硬盘、分区)

# 文本处理
wc -l file.txt                # 统计行数
sort file.txt                 # 排序
uniq file.txt                 # 去重(需先 sort)
cut -d ',' -f 1 data.csv      # 按分隔符提取字段
awk '{print $1,$3}' data.txt # awk:强大的文本处理
sed 's/old/new/g' file.txt    # sed:文本替换

# 文件权限
chmod 755 script.sh           # 设置权限
chown user:group file.txt     # 更改所有者/组

12.3 用户和权限管理

Linux 权限模型

ls -l
# -rwxr-xr-- 1 lou developers 1024 May 25 19:00 script.sh
#  │││││││││
#  │└┬┘└┬┘└┬┘  ← 三组权限
#  │ │  │  └ 其他用户 (r--)  ← 只能读
#  │ │  └ 组用户 (r-x)       ← 读+执行
#  │ └ 文件所有者 (rwx)      ← 读+写+执行
#  └ 文件类型(- 普通文件,d 目录,l 符号链接)

# 权限数字:
# r = 4, w = 2, x = 1
# 755 = rwxr-xr-x  (所有者全权限,组和其他用户读+执行)
# 644 = rw-r--r--  (所有者读写,组和其他只读)
# 600 = rw-------  (只有所有者能读写,私密文件)

用户管理

# 查看用户信息
whoami                        # 我是谁
id                            # 用户 ID 和组信息

# 创建用户(需要 sudo 或 root)
sudo useradd -m -s /bin/bash newuser   # -m 创建家目录,-s 指定 Shell
sudo passwd newuser                     # 设置密码
sudo usermod -aG docker newuser         # 将用户加入 docker 组
sudo userdel -r newuser                 # 删除用户(-r 一并删除家目录)

# 切换用户
su - newuser                   # 切换到 newuser
sudo command                   # 以 root 权限执行一条命令
sudo -i                        # 切换到 root Shell(慎用)
sudo -u postgres psql          # 以 postgres 用户身份运行 psql

sudo 配置

# 编辑 sudoers 文件(必须用 visudo!)
sudo visudo

# 常用配置
lou ALL=(ALL:ALL) ALL              # 允许 lou 执行所有命令
%developers ALL=(ALL) ALL          # 允许 developers 组的所有用户
lou ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
# 允许 lou 无密码执行特定的 systemctl 命令

# sudo 相关命令
sudo -l                        # 列出当前用户可以执行的 sudo 命令
sudo !!                        # 以 sudo 重新执行上一条命令(超实用!)

12.4 systemd 服务管理

systemd 是现代 Linux 的系统和服务管理器,管理着几乎所有后台进程。

# 服务生命周期管理
sudo systemctl start nginx          # 启动服务
sudo systemctl stop nginx           # 停止服务
sudo systemctl restart nginx        # 重启服务
sudo systemctl reload nginx         # 重新加载配置(不中断服务)
sudo systemctl status nginx         # 查看服务状态
sudo systemctl enable nginx         # 开机自启
sudo systemctl disable nginx        # 禁止开机自启
sudo systemctl is-enabled nginx     # 检查是否开机自启

# 查看所有服务
systemctl list-units --type=service    # 正在运行的服务
systemctl list-units --type=service --all  # 所有服务(包括未运行的)
systemctl list-unit-files --type=service  # 所有已安装的服务

# 查看失败的单元
systemctl --failed

# 系统状态
systemctl reboot                   # 重启系统
systemctl poweroff                 # 关机

编写 systemd 服务文件

当你需要将自己的程序注册为系统服务:

# /etc/systemd/system/myapp.service
[Unit]
Description=My Web Application
After=network.target postgresql.service   # 在网络和数据库就绪后启动

[Service]
Type=simple
User=myapp                                # 以哪个用户运行
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/venv/bin/python app.py
Restart=on-failure                        # 崩溃后自动重启
RestartSec=5                              # 重启前等待 5 秒
Environment="DATABASE_URL=postgresql://localhost/myapp"
EnvironmentFile=/etc/myapp/env            # 或从文件加载环境变量
StandardOutput=journal                    # 日志输出到 journald
StandardError=journal

[Install]
WantedBy=multi-user.target                # 在系统进入多用户模式时启动
# 部署服务
sudo cp myapp.service /etc/systemd/system/
sudo systemctl daemon-reload     # 重新加载 systemd 配置
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp      # 确认运行正常

12.5 包管理

包管理器让你一行命令安装、更新、删除软件,自动处理依赖关系。

apt(Debian/Ubuntu)

# 更新包索引
sudo apt update

# 升级所有已安装的包
sudo apt upgrade

# 升级 + 必要时智能处理依赖(推荐)
sudo apt full-upgrade

# 安装
sudo apt install nginx python3 postgresql
sudo apt install ./local-package.deb     # 安装本地 .deb 文件

# 删除
sudo apt remove nginx                    # 删除软件包,保留配置文件
sudo apt purge nginx                     # 删除软件包 + 配置文件
sudo apt autoremove                      # 删除不再需要的依赖

# 搜索和查看信息
apt search keyword                        # 搜索包
apt show nginx                            # 查看包详细信息
apt list --installed                      # 列出已安装的包
apt list --upgradable                     # 列出可升级的包
dpkg -l | grep nginx                     # 更详细的包状态

# 添加第三方仓库(如 Docker)
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update && sudo apt install docker-ce

yum/dnf(RHEL/CentOS/Fedora)

# RHEL 7 / CentOS 7 — yum
sudo yum install nginx
sudo yum update
sudo yum remove nginx
sudo yum search keyword
sudo yum info nginx

# RHEL 8+ / Fedora — dnf(yum 的下一代)
sudo dnf install nginx
sudo dnf update
sudo dnf remove nginx

# 添加 EPEL 仓库(Extra Packages for Enterprise Linux)
sudo dnf install epel-release

Snap 和 Flatpak(跨发行版)

# Snap(Ubuntu 推广)
sudo snap install vlc
snap list
sudo snap remove vlc

# Flatpak(通用 Linux 应用格式)
flatpak install flathub org.videolan.VLC
flatpak list
flatpak uninstall org.videolan.VLC

12.6 进程管理

查看进程

# 经典命令
ps aux                                  # 列出所有进程的详细信息
ps aux | grep nginx                     # 查找特定进程
ps -ef --forest                         # 显示进程树

# 实时监控
top                                     # 动态查看进程(按 q 退出,按 1 看每个 CPU 核心)
htop                                    # top 的增强版(需要安装,更直观)

# 按资源排序查找
ps aux --sort=-%mem | head -10          # 按内存使用排序 Top 10
ps aux --sort=-%cpu | head -10          # 按 CPU 使用排序 Top 10

终止进程

# 优雅终止(给进程清理的机会)
kill 1234                               # 发送 TERM 信号
kill -TERM 1234                         # 同上,显式写法

# 强制终止(不给清理机会,万不得已时用)
kill -9 1234                            # 发送 KILL 信号
kill -KILL 1234                         # 同上

# 按名称终止
pkill nginx                             # 终止所有 nginx 进程
killall nginx                           # 同上
pkill -f "python app.py"                # 终止匹配完整命令行的进程

常用信号:

信号 编号 含义
SIGTERM 15 请求进程终止(默认,最礼貌)
SIGKILL 9 强制终止(进程无法捕获或忽略)
SIGHUP 1 挂起信号(常用来让进程重新加载配置)
SIGINT 2 中断信号(Ctrl+C)

后台运行

# 在后台运行程序
python app.py &                          # 放到后台
nohup python app.py &                    # 忽略挂断信号(关闭终端后继续运行)
nohup python app.py > output.log 2>&1 & # 同时重定向输出

# 任务控制
jobs                                     # 查看后台任务
fg %1                                    # 将后台任务 1 调回前台
bg %1                                    # 让前台暂停的任务 1 在后台继续
Ctrl+Z                                   # 暂停当前前台任务

# 更好的方案:tmux 或 screen
tmux new -s mysession                    # 创建新会话
# Ctrl+B 然后 D → 脱离会话(程序继续运行)
tmux attach -t mysession                 # 重新连接会话
tmux ls                                  # 列出所有会话
💡 强烈推荐 tmux:比 nohup 好用太多。一个 tmux 会话可以存活数周,随时断开再重连。

12.7 日志查看

journalctl(systemd 日志)

# 查看所有系统日志
journalctl

# 查看特定服务的日志
journalctl -u nginx                     # nginx 服务的日志
journalctl -u nginx -f                  # 实时追踪(类似 tail -f)
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2025-05-25" --until "2025-05-26"

# 查看最近的启动日志
journalctl -b                           # 本次启动以来的日志
journalctl -b -1                        # 上一次启动的日志

# 按优先级过滤
journalctl -p err                       # 只看错误和更严重的
# 优先级:emerg(0) alert(1) crit(2) err(3) warning(4) notice(5) info(6) debug(7)

# 查看内核日志
journalctl -k

# 持久化日志(默认存储在内存,重启丢失)
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald

tail 和 grep 组合看日志

# 实时查看 Nginx 访问日志
tail -f /var/log/nginx/access.log

# 只看 500 错误
tail -f /var/log/nginx/access.log | grep " 500 "

# 按 IP 地址统计访问量
cat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# 查看特定时间段的日志
grep "2025-05-25 19:" /var/log/app.log
sed -n '/2025-05-25 19:00/,/2025-05-25 20:00/p' /var/log/app.log

# 查看错误日志并翻页
less /var/log/syslog
# 按 G 跳到末尾,按 g 跳到开头,按 / 搜索

常见日志位置

日志 路径 用途
系统日志 `/var/log/syslog` (Debian) 或 `/var/log/messages` (RHEL) 通用系统消息
认证日志 `/var/log/auth.log` (Debian) 或 `/var/log/secure` (RHEL) 登录、sudo 记录
内核日志 `/var/log/kern.log` 或 `dmesg` 硬件、驱动信息
Nginx 访问 `/var/log/nginx/access.log` HTTP 请求记录
Nginx 错误 `/var/log/nginx/error.log` Nginx 错误
PostgreSQL `/var/log/postgresql/` 数据库日志
cron `/var/log/syslog` 定时任务执行记录

12.8 定时任务 cron

cron 让你在指定的时间自动执行脚本。

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

# 格式(5 个时间字段 + 命令):
# ┌─────────── 分钟 (0-59)
# │ ┌─────────── 小时 (0-23)
# │ │ ┌─────────── 日 (1-31)
# │ │ │ ┌─────────── 月 (1-12)
# │ │ │ │ ┌─────────── 星期几 (0-7, 0 和 7 都表示周日)
# │ │ │ │ │
# * * * * * command

常用示例

# 每天凌晨 2 点备份数据库
0 2 * * * /opt/scripts/backup-db.sh >> /var/log/backup.log 2>&1

# 每小时清理临时文件
0 * * * * find /tmp -type f -mtime +1 -delete

# 每 5 分钟检查服务状态
*/5 * * * * /opt/scripts/healthcheck.sh

# 每周一早上 8 点更新系统
0 8 * * 1 sudo apt update && sudo apt upgrade -y

# 每月 1 号凌晨 3 点清理旧日志
0 3 1 * * find /var/log -name "*.log" -mtime +30 -delete

# 每天 18:00 发送提醒
0 18 * * * echo "下班时间到!" | mail -s "提醒" user@example.com

crontab 管理

crontab -l                     # 查看当前用户的定时任务
crontab -e                     # 编辑
crontab -r                     # 删除所有任务(⚠️慎用)

# 系统级 crontab 文件
/etc/crontab                   # 系统 crontab(可以指定用户)
/etc/cron.d/                   # 放置 cron 任务文件的目录
/etc/cron.hourly/              # 每小时执行的脚本
/etc/cron.daily/               # 每天执行的脚本
/etc/cron.weekly/              # 每周执行的脚本
/etc/cron.monthly/             # 每月执行的脚本

# 查看 cron 是否执行成功
grep CRON /var/log/syslog      # Ubuntu/Debian
journalctl -u cron             # 使用 systemd 的系统

时间表达式速查

表达式 含义
`* * * * *` 每分钟
`*/10 * * * *` 每 10 分钟
`0 * * * *` 每小时整点
`0 8 * * *` 每天早上 8:00
`0 8 * * 1-5` 工作日早上 8:00
`0 0 1 * *` 每月 1 号凌晨
`30 18 * * 6` 每周六 18:30

12.9 SSH 远程连接

SSH(Secure Shell)是登录远程服务器的标准方式。

基本连接

# 密码登录
ssh user@192.168.1.100
ssh -p 2222 user@example.com      # 指定端口(默认 22)

# 执行单条命令(不登录 Shell)
ssh user@server 'ls -la /var/www'
ssh user@server 'sudo systemctl restart nginx'

# 传输文件
scp file.txt user@server:/home/user/          # 本地 → 远程
scp user@server:/home/user/file.txt ./        # 远程 → 本地
scp -r project/ user@server:/home/user/       # 递归传输目录

rsync -avz project/ user@server:/home/user/   # 增量同步(更快!)
rsync -avz --delete project/ user@server:/home/user/  # 删除目标中多余文件

SSH 密钥认证(推荐)

# 生成密钥对(如果还没有)
ssh-keygen -t ed25519 -C "your_email@example.com"
# Ed25519 比 RSA 更安全且更快

# 密钥文件位置
# 私钥:~/.ssh/id_ed25519  (绝不要分享!)
# 公钥:~/.ssh/id_ed25519.pub

# 将公钥复制到远程服务器
ssh-copy-id user@server

# 之后登录不需要输入密码了!
ssh user@server

SSH 配置文件

# ~/.ssh/config — 为常用连接创建别名
# ~/.ssh/config
Host prod-web
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host dev-server
    HostName 192.168.1.50
    User lou
    ForwardAgent yes        # 转发 SSH Agent(跳板机场景)

Host github
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519
# 现在可以用别名连接
ssh prod-web
scp config.json prod-web:/opt/app/

# 测试 Git SSH 连接
ssh -T github

SSH 隧道(端口转发)

# 本地端口转发:访问本地 8080 → 转发到远程服务器的 80 端口
ssh -L 8080:localhost:80 user@server
# 现在访问 http://localhost:8080 就等于访问远程服务器的 80 端口

# 远程端口转发:远程服务器的 9090 → 转发到本地 3000
ssh -R 9090:localhost:3000 user@server
# 让远程服务器能访问你本地的服务

# 动态端口转发(SOCKS 代理)
ssh -D 1080 user@server
# 配置浏览器使用 SOCKS5 代理 localhost:1080,流量通过服务器转发

安全加固

# /etc/ssh/sshd_config(需要 sudo 编辑)
# 修改后执行:sudo systemctl restart sshd

# 禁止 root 登录
PermitRootLogin no

# 禁止密码登录(只允许密钥)
PasswordAuthentication no

# 更改默认端口
Port 2222

# 只允许特定用户
AllowUsers deploy lou

# 限制尝试次数
MaxAuthTries 3

12.10 实战:部署一个 Python Web 应用

让我们把学到的知识串联起来,部署一个真实的 Web 应用:

# === 1. 登录服务器 ===
ssh deploy@my-server

# === 2. 安装依赖 ===
sudo apt update
sudo apt install python3 python3-pip python3-venv nginx postgresql

# === 3. 设置数据库 ===
sudo -u postgres psql
# CREATE DATABASE myapp;
# CREATE USER myapp WITH PASSWORD 'strong_password';
# GRANT ALL PRIVILEGES ON DATABASE myapp TO myapp;
# \q

# === 4. 部署应用代码 ===
sudo mkdir -p /opt/myapp
sudo chown deploy:deploy /opt/myapp
cd /opt/myapp
git clone https://github.com/user/myapp.git .
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# === 5. 创建 systemd 服务 ===
sudo tee /etc/systemd/system/myapp.service << 'EOF'
[Unit]
Description=MyApp Service
After=network.target postgresql.service

[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 app:app
Restart=on-failure
EnvironmentFile=/etc/myapp/env

[Install]
WantedBy=multi-user.target
EOF

# === 6. 配置环境变量 ===
sudo mkdir -p /etc/myapp
sudo tee /etc/myapp/env << 'EOF'
DATABASE_URL=postgresql://myapp:strong_password@localhost/myapp
SECRET_KEY=your-secret-key-here
EOF
sudo chmod 600 /etc/myapp/env

# === 7. 启动应用服务 ===
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp

# === 8. 配置 Nginx 反向代理 ===
sudo tee /etc/nginx/sites-available/myapp << 'EOF'
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /static/ {
        alias /opt/myapp/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t                    # 测试配置
sudo systemctl reload nginx

# === 9. 配置 HTTPS(Let's Encrypt 免费证书)===
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
# 证书自动续期,无需手动操作

# === 10. 设置定时备份 ===
(crontab -l 2>/dev/null; echo "0 2 * * * pg_dump myapp > /backups/myapp_\$(date +\%Y\%m\%d).sql") | crontab -

echo "✅ 部署完成!"

本章小结


[⬅️ 上一章:11-Web开发基础](./11-Web开发基础.html) · [🏠 目录](./README.html) · [🏠 回到目录](./README.html)

Collaplex · 克拉普莱克斯 collaplex.me · 2026 浙ICP备2026080865号