Day 5:本周串联实操

今日目标:权限 → 后台进程 → 进程管理 → 前后台切换 → 重定向,一整条链路串起来 🎯

命令速览(本周全部命令)

whoami id groups chmod chown su sudo ps top kill pkill jobs fg bg Ctrl+Z > >> 2> 2>&1 | <<EOF

场景一:部署一个模拟 Web 服务并管理它

你用 python3 -m http.server(或 nc -l)模拟一个 Web 服务,完成部署 → 后台化 → 监控 → 杀进程的全流程。

操作流程

第一步:准备服务脚本

1
2
3
4
5
6
7
8
9
10
11
12
cd /tmp
cat > server.sh <<'EOF'
#!/bin/bash
# 模拟一个持续输出日志的服务
count=0
while true; do
echo "[$(date)] INFO request count=$count"
count=$((count + 1))
sleep 2
done
EOF
chmod 755 server.sh

第二步:后台启动与监控

  1. ./server.sh > server.log 2>&1 &——后台启动,输出重定向到日志
  2. echo $!——记录后台进程 PID($! 是上一个后台进程的 PID)
  3. jobs——确认任务在后台运行
  4. tail -f server.log——实时查看日志输出
  5. Ctrl+Z 挂起 tailbg 让它在后台继续

第三步:进程查找与管理

  1. ps aux | grep server.sh | grep -v grep——找到服务进程
  2. pgrep -fl server——另一种方式查找
  3. top -p <PID>——只看这个进程的资源占用
  4. kill -15(TERM 信号)<PID>——优雅终止,给进程清理资源的机会
  5. ps aux | grep server.sh——确认已终止

第四步:权限实验

  1. sudo chown root:root server.sh——改所有权
  2. ls -l server.sh——验证权限
  3. ./server.sh &——以自己身份运行,应该可以
  4. sudo ./server.sh &——以 root 身份运行一版
  5. ps aux | grep server.sh——能看到两个 server.sh,一个属于你一个属于 root

第五步:静默清理

  1. sudo pkill -f server.sh——全部杀掉(需 sudo 才能杀掉 root 拥有的进程)
  2. ps aux | grep server.sh | grep -v grep——确认无残留
  3. rm -f server.sh server.log

场景二:权限故障模拟

1
2
3
4
5
6
7
mkdir /tmp/permtest
echo "secret data" > /tmp/permtest/secret.txt
chmod 000 /tmp/permtest/secret.txt
cat /tmp/permtest/secret.txt # 报错 Permission denied
chmod 644 /tmp/permtest/secret.txt
cat /tmp/permtest/secret.txt # 成功
rm -rf /tmp/permtest

💪 今日必刷(全部终端实操)

  1. 写一个 while 循环脚本(或 sleep 命令),后台启动 2 个实例,输出分别重定向到不同的日志文件
  2. ps 找到这 2 个进程,对比它们的 PID、父进程、启动时间
  3. kill -15(TERM 信号)终止其中一个,用 kill -9(KILL 信号)终止另一个——理解两种信号的差异
  4. 模拟场景:创建文件 → chmod 000 → cat 报错 → chmod 644 → cat 成功
  5. 排错题:你 ./server.sh & 后台启动后关闭了终端,重新登录后发现进程没了——为什么?如何让进程在终端关闭后继续运行?(提示:nohup
  6. 排错题ps aux 输出过多,你想找到 nginx 进程,执行 ps aux | grep nginx,但每次结果都包含 grep 自身——如何过滤干净?

📚 命令详解

命令 详细参考
whoami 权限与用户管理-whoami
id 权限与用户管理-id
groups 权限与用户管理-id
chmod 权限与用户管理-chmod
chown 权限与用户管理-chown
su 权限与用户管理-su
sudo 权限与用户管理-sudo
ps 进程管理-ps
top 进程管理-top
kill 进程管理-kill
pkill 进程管理-pkill
jobs bg-fg-jobs
fg bg-fg-jobs
bg bg-fg-jobs

第二周 · 综合实战

实战场景

你是运维值班,凌晨收到告警:一台 Web 服务器的 nginx 进程疑似僵死,日志疯狂写入,磁盘快满了。你需要登录服务器排查并解决问题。


环境搭建

先在 /tmp 下模拟场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cd /tmp
mkdir -p web-ops/{logs,scripts,backup}

# 模拟一个疯狂写日志的进程
cat > web-ops/scripts/bad-writer.sh <<'EOF'
#!/bin/bash
while true; do
echo "[$(date)] ERROR something went wrong" >> /tmp/web-ops/logs/app.log
sleep 0.1
done
EOF
chmod 755 web-ops/scripts/bad-writer.sh

# 创建一些已有的日志(模拟磁盘占用)
dd if=/dev/zero of=/tmp/web-ops/logs/old-giant.log bs=1M count=50 2>/dev/null
dd if=/dev/zero of=/tmp/web-ops/backup/old-backup.tar bs=1M count=30 2>/dev/null

任务一:摸清系统状态

  1. df -h 查看磁盘使用情况(关注 /tmp 所在分区)
  2. du -sh /tmp/web-ops/* 查看各子目录大小,找出哪个目录最占空间
  3. du -sk /tmp/web-ops/logs/* | sort -rn | head -5 找出最大的几个日志文件
  4. uptime 查看系统负载

任务二:找到肇事进程

  1. 后台启动肇事脚本:/tmp/web-ops/scripts/bad-writer.sh &
  2. jobs 确认后台任务
  3. tail -f /tmp/web-ops/logs/app.log 观察日志增长速度(看一会 Ctrl+C 退出)
  4. ps aux 找到 bad-writer.sh 进程,记录其 PID 和 CPU/内存占用
  5. lsof -p <PID>(如果系统有 lsof)查看该进程打开了哪些文件

任务三:止损与清理

  1. kill -15(TERM 信号)终止 bad-writer.sh,确认已停止
  2. 如果 kill -15(TERM 信号)无效,使用 kill -9(KILL 信号)强制终止
  3. 删除 old-giant.logold-backup.tar 释放空间
  4. app.log 备份并清空:
    1
    2
    cp /tmp/web-ops/logs/app.log /tmp/web-ops/backup/app.log.bak
    > /tmp/web-ops/logs/app.log
  5. 验证 app.log 已清空且进程已不存在

任务四:权限加固

  1. web-ops/scripts/ 目录权限设为 750(只有所有者和组可读写执行)
  2. web-ops/logs/ 目录权限设为 755
  3. 创建一个专用的 webops 组(sudo groupadd webops),将 logs/ 目录的所有组改为 webops
  4. 验证:没有权限的用户能否进入 scripts/

故障排查一

现象:你执行 sudo /tmp/web-ops/scripts/bad-writer.sh 启动脚本,然后 kill <PID> 杀进程,报 Operation not permitted

  • 为什么会这样?
  • 如何正确杀掉这个进程?

故障排查二

现象ps aux | grep bad-writer 显示进程还在,状态为 T(Stopped)。你发送 kill -15(TERM 信号)后,进程并未消失,仍处于 T 状态。

说明:进程进入 T(Stopped)状态的常见原因是被 Ctrl+Z 挂起、收到 SIGSTOP 信号、或被调试器(gdb/strace)attach。处于停止状态的进程不会立即处理 TERM 信号(信号会挂起等待),需要先收到 SIGCONT 恢复运行。

  • T 状态意味着什么?
  • 如何彻底终止它?(提示:kill -9 可强制终止处于 T 状态的进程;也可以先 kill -CONT 恢复运行后再 kill -15 优雅终止)
  • 如果 kill -9(KILL 信号)也无效(进程处于 D 状态——不可中断睡眠),可能是什么原因?怎么排查?

Day 1:用户身份与基本权限

今日目标:知道”我是谁”、”我属于哪些组”,能查看和修改文件的基本读写执行权限 🎯

命令速览

命令 用途 核心参数
whoami 显示当前用户名 (无)
id 显示用户 UID/GID/所属组 -u -g
groups 显示当前用户所属组 (无)
chmod 修改文件/目录权限 755 u+x -R

逐个击破

① whoami — 当前用户名

  • 语法whoami
  • 🖥️ 上手练
    1. 终端输入 whoami,记住你的用户名
    2. su - root(需要 root 密码),然后 whoami——变成 root 了
    3. exit 退出 root,再次 whoami——回到原用户
  • ⚠️ 常见坑whoamiwho am i 是不同的命令,后者显示登录时的原始身份

② id — 用户与组信息

  • 语法id [<USER>]
  • 参数-u→只显示 UID,-g→只显示 GID
  • 🖥️ 上手练
    1. id——查看自己的 UID、GID、所有组
    2. id -u——只输出 UID 数字
    3. id root——查看 root 用户的 UID(应该是 0)
    4. 理解输出:uid=1000(mr) gid=1000(mr) groups=1000(mr),4(adm),27(sudo)
  • ⚠️ 常见坑:UID=0 就是 root(超级管理员),不要轻易给普通用户 UID=0

③ groups — 查看所属组

  • 语法groups [<USER>]
  • 🖥️ 上手练
    1. groups——列出你的所有组
    2. groups root——查看 root 的组
    3. 理解:用户属于多个组时,第一个是主组

④ chmod — 修改文件权限

  • 语法chmod <MODE> <DEST>
  • 两种模式
    • 数字模式r=4 w=2 x=1,组合相加
      • 755 → 所有者 rwx,组 rx,其他人 rx
      • 644 → 所有者 rw,组 r,其他人 r
      • 777 → 所有人 rwx(危险)
    • 符号模式u/g/o + a 组合 +/-/=
      • u+x → 所有者加执行权限
      • g-w → 组去掉写权限
      • o=r → 其他人设为只读
  • 参数-R 递归修改目录及其下所有文件
  • 🖥️ 上手练
    1. touch /tmp/test.sh && ls -l /tmp/test.sh——查看默认权限
    2. chmod 755 /tmp/test.sh && ls -l /tmp/test.sh——观察权限变化
    3. chmod u+x /tmp/test.sh && ls -l /tmp/test.sh——给所有者加执行权限
    4. chmod 000 /tmp/test.sh && cat /tmp/test.sh——测试无权限时的报错
    5. chmod 644 /tmp/test.sh——恢复正常权限
    6. mkdir -p /tmp/chmodtest/sub && touch /tmp/chmodtest/sub/f.txt; chmod -R 700 /tmp/chmodtest——递归修改
  • ⚠️ 常见坑chmod 777 是安全大忌!目录 777 任何用户可读写,生产环境慎用

💪 今日必刷(全部终端实操)

  1. 执行 idgroups,记录你的 UID、GID 和所有组
  2. 创建 /tmp/my-script.sh,默认权限是什么?把它改为只有你自己可读写执行
  3. 修改 /tmp/my-script.sh 权限为 744,用符号模式实现同样的效果
  4. 创建一个目录 /tmp/secret/,设置权限为 700,验证其他用户(如 nobody)能否进入
  5. 排错题:你用 vim 写了一个脚本 run.sh,执行 ./run.shPermission denied——排查步骤?可能的修复方式?(至少 2 种)
  6. 排错题:执行 chmod -R 755 /tmp/mydir 后,/tmp/mydir/secret.key 的权限变成了 755(你希望它是 600),怎么办?在 chmod -R 中如何避免这种情况?

📚 命令详解

命令 详细参考
whoami 权限与用户管理-whoami
id 权限与用户管理-id
groups 权限与用户管理-id
chmod 权限与用户管理-chmod

Day 2:权限深入与提权

今日目标:掌握文件所有权的修改、用户切换和 sudo 提权——知道什么时候用 su、什么时候用 sudo 🎯

命令速览

命令 用途 核心参数
chown 修改文件所有者与组 user:group
su 切换用户 - (加载目标用户环境)
sudo 以 root 身份执行单条命令 (见下方常用场景)

逐个击破

① chown — 修改文件所有权

  • 语法chown <USER>:<GROUP> <DEST>
  • 🖥️ 上手练
    1. touch /tmp/owned.txt && ls -l /tmp/owned.txt——查看当前所有者
    2. sudo chown root:root /tmp/owned.txt && ls -l /tmp/owned.txt——所有者变成 root
    3. sudo chown $USER:$USER /tmp/owned.txt——改回来($USER 是当前用户环境变量)
    4. sudo chown root /tmp/owned.txt——只改用户不改组;sudo chown :adm /tmp/owned.txt——只改组不改用户
  • ⚠️ 常见坑:普通用户不能 chown 给别人(只能改自己的文件到自己名下),需要 sudo

② su — 切换用户

  • 语法su - <USER>
  • 参数:加 - 加载目标用户的完整环境(PATH、HOME 等),不加 - 只切换身份不切换环境
  • 🖥️ 上手练
    1. su(无参数)默认切换到 root,需要 root 密码
    2. su - root——切换到 root 并加载 root 环境(PATH 变化了)
    3. su - <你的用户名>——切换到自己(需要输入自己的密码)
    4. 对比:su root 后执行 pwd(还在原目录) vs su - root 后执行 pwd(进入了 /root)
  • ⚠️ 常见坑susu - 的区别是日常排错重灾区——环境变量不同导致命令找不到

③ sudo — 以超级用户身份执行

  • 语法sudo <CMD>
  • 🖥️ 上手练
    1. sudo whoami——验证以 root 身份执行
    2. sudo apt update(Debian/Ubuntu)或 sudo echo "test"——执行需要 root 权限的操作
    3. sudo -i——进入 root shell(等价于 sudo su -
    4. sudo -u nobody whoami——以其他用户身份执行(需要 root 权限)
    5. sudo !!——用 sudo 重新执行上一条命令(忘记加 sudo 时的救命操作)
  • ⚠️ 常见坑sudo 不是万能的——sudo echo "text" > /etc/protected.conf 不会生效!因为 > 重定向由当前 shell 处理,不是 sudo 的权限范围。正确做法:echo "text" | sudo tee /etc/protected.conf

💪 今日必刷(全部终端实操)

  1. 创建 /tmp/mytest.txt,用 sudo chown 将其所有者改为 root:root,然后改回你的用户名
  2. 对比 su root(不加 -)和 su - root 执行 echo $PATH 的输出差异
  3. 故意忘记 sudo:尝试 cat /etc/shadow(报错),然后用 sudo !! 重新执行——验证成功
  4. sudo -u nobody whoami 验证能以 nobody 身份执行命令
  5. 排错题:你用 su 切到 root,执行 nginx -s reloadcommand not found,但你自己用户下能执行——为什么?怎么解决?(提示:PATH 差异)
  6. 排错题:执行 sudo echo "127.0.0.1 myapp.local" >> /etc/hostsPermission denied——哪一步出问题了?正确的实现方式是什么?

📚 命令详解

命令 详细参考
chown 权限与用户管理-chown
su 权限与用户管理-su
sudo 权限与用户管理-sudo

Day 3:进程查看与管理

今日目标:会看进程列表、找进程、杀进程——知道 kill -9(KILL 信号)的后果,不乱杀 🎯

命令速览

命令 用途 核心参数
ps 查看进程快照 aux -ef
top 实时进程监控 P/M/q 交互键
kill 向进程发送信号 -9 (KILL) / -15 (TERM)
pkill 按名称杀进程 (按进程名匹配)

逐个击破

① ps — 查看进程快照

  • 语法ps [options]
  • 常用组合
    • ps aux → BSD 风格:显示所有用户进程,含 CPU/内存占用
    • ps -ef → Unix 风格:显示完整命令行
  • 🖥️ 上手练
    1. ps aux | head -10——看前 10 行进程列表
    2. ps aux | grep bash——找出所有 bash 进程
    3. ps -ef | grep sshd——用 Unix 风格查找 sshd 进程
    4. ps aux --sort=-%mem | head——按内存占用从高到低排列
  • ⚠️ 常见坑ps aux | grep nginx 结果中最后那行 grep 自身也在里面,用 ps aux | grep nginx | grep -v grep 排除

② top — 实时进程监控

  • 语法top
  • 交互键(在 top 内使用):
    • P(大写)→ 按 CPU 排序
    • M(大写)→ 按内存排序
    • q → 退出
    • k → 输入 PID 杀进程(会提示输入信号)
    • 1 → 切换显示每个 CPU 核心
  • 🖥️ 上手练
    1. 运行 top,观察当前系统负载(load average)、CPU 使用率、内存使用率
    2. 在 top 中按 M 排序,找出内存占用最高的进程
    3. P 排序,找出 CPU 占用最高的进程
    4. q 退出
  • ⚠️ 常见坑top 显示的 RES 是实际物理内存,VIRT 是虚拟内存(含未使用的共享库),别把 VIRT 当真实占用

③ kill — 向进程发信号

  • 语法kill [<SIGNAL>] <PID>
  • 关键信号
    • -15 (SIGTERM) → 优雅终止,给进程机会清理资源(默认信号)
    • -9 (SIGKILL) → 立即强制杀死,进程无法捕获和处理
  • 🖥️ 上手练
    1. sleep 300 &——后台启动一个 sleep 进程,记下 PID
    2. kill -15 <PID>——优雅终止 sleep
    3. sleep 300 &——再启动,这次用 kill -9 <PID> 强制杀
    4. kill -l——列出所有支持的信号
  • ⚠️ 常见坑kill -9(KILL 信号)是最后手段!进程没有机会清理临时文件、关闭连接、释放锁。优先用 kill -15(TERM 信号)

④ pkill — 按名称杀进程

  • 语法pkill [<OPTIONS>] <PATTERN>
  • 🖥️ 上手练
    1. sleep 300 & sleep 300 & sleep 300 &——启动 3 个 sleep
    2. pgrep -a sleep——查看所有 sleep 进程(观察 3 个 PID)
    3. pkill sleep——一次性全部杀掉
    4. pgrep -a sleep——确认已全部消失
  • ⚠️ 常见坑pkill 按名称部分匹配,pkill nginx 可能杀掉 nginx-devel 等不相关的进程,先用 pgrep 确认匹配范围再杀

💪 今日必刷(全部终端实操)

  1. ps aux 找出当前系统内存占用最高的 3 个进程(写出完整命令)
  2. 后台启动 sleep 600 &,记下 PID,用 kill -15 终止,验证进程是否消失
  3. 再开 3 个 sleep 999 &,用 pkill 一次性全部杀掉,然后确认
  4. 运行 top,按 M 排序,截图(或记录)内存 top3 进程,退出
  5. 排错题ps aux | grep java 出来一堆结果,你 kill <PID> 后发现 java 进程还在——排查:PID 对吗?用什么信号?用 ps 确认是否真的还在
  6. 排错题:你 pkill nginx 后发现还有 nginx worker 进程残留——什么原因?怎么办?(提示:worker 进程的父进程是什么?)

📚 命令详解

命令 详细参考
ps 进程管理-ps
top 进程管理-top
kill 进程管理-kill
pkill 进程管理-pkill

Day 4:前后台控制与重定向管道

今日目标:控制进程前后台切换、理解输入输出流——把命令的输出送到文件、把错误和正常输出分开或合并 🎯

命令速览

命令/操作 用途
jobs 查看当前 shell 的后台任务
fg / bg 前台恢复 / 后台继续运行
Ctrl+Z 挂起当前前台进程
> / >> 标准输出重定向(覆盖/追加)
2> 标准错误重定向
2>&1 错误合并到标准输出
| 管道:前一个命令的输出作为后一个命令的输入
<<EOF Here Document:内联多行输入

逐个击破

① 前后台切换 — jobs / fg / bg / Ctrl+Z

  • 关键操作
    • 命令 & → 直接在后台启动
    • Ctrl+Z → 挂起正在运行的前台进程
    • jobs → 列出当前 shell 的后台任务
    • fg %1 → 把编号 1 的任务调到前台
    • bg %1 → 让编号 1 的任务在后台继续运行
  • 🖥️ 上手练
    1. sleep 300(前台运行),然后按 Ctrl+Z——进程被挂起
    2. jobs——看到 sleep 状态是 “Stopped”
    3. bg %1——sleep 在后台继续运行
    4. jobs——状态变为 “Running”
    5. fg %1——拉回前台,等它跑完或 Ctrl+C 终止
    6. sleep 120 &——直接在后台启动,jobs 验证
  • ⚠️ 常见坑:后台进程的输出仍然会打印到终端,干扰你输入。加 > /dev/null 2>&1 静默

② 标准输出重定向 — > 和 >>

  • 语法命令 > 文件(覆盖)/ 命令 >> 文件(追加)
  • 🖥️ 上手练
    1. echo "hello" > /tmp/out.txt && cat /tmp/out.txt——覆盖写入
    2. echo "world" > /tmp/out.txt && cat /tmp/out.txt——再次覆盖,只剩 “world”
    3. echo "line1" > /tmp/out2.txt && echo "line2" >> /tmp/out2.txt && cat /tmp/out2.txt——追加模式保留两行
    4. > /tmp/empty.txt——清空文件或创建空文件(> 前面放空就是清空)
  • ⚠️ 常见坑> 覆盖文件是立即发生的(命令执行前就清空文件),如果命令中途失败,原文件内容已经被消除

③ 错误重定向 — 2> 和 2>&1

  • 语法
    • 命令 2> 文件 → 错误输出写入文件
    • 命令 > 文件 2>&1 → 标准输出+错误输出合并写入同一文件
    • 命令 > /dev/null 2>&1 → 静默所有输出
  • 🖥️ 上手练
    1. ls /etc/hosts > /tmp/ok.txt 2>/tmp/err.txt——成功时 ok.txt 有内容,err.txt 空
    2. ls /nonexist > /tmp/ok.txt 2>/tmp/err.txt——失败时 ok.txt 空,err.txt 有报错
    3. ls /etc/hosts /nonexist > /tmp/all.txt 2>&1——成功和失败信息都在同一个文件
    4. ls /nonexist 2>&1 | head——把错误也送入管道(默认管道只传标准输出!)
    5. sleep 300 > /dev/null 2>&1 &——静默后台运行
  • ⚠️ 常见坑2>&1 必须放在 > 之后!ls 2>&1 > file 是错误的——错误输出不会写入文件

④ 管道 — |

  • 语法命令1 | 命令2 | 命令3
  • 🖥️ 上手练
    1. cat /etc/passwd | wc -l——统计行数
    2. ls -l /etc | sort -k5 -rn | head -5——最大的 5 个文件
    3. ps aux | grep nginx | grep -v grep | wc -l——nginx 进程数量
  • ⚠️ 常见坑:管道只传递标准输出,错误输出默认仍打印到终端。需 命令 2>&1 | 下一个命令 把错误也传入管道

⑤ Here Document — <<EOF

  • 语法
    1
    2
    3
    4
    cat > 文件 <<EOF
    多行内容
    多行内容
    EOF
  • 🖥️ 上手练
    1. 用 Here Document 创建 /tmp/readme.txt,内容 3 行任意文字
    2. 用 Here Document 追加内容到同一个文件(用 >>
  • ⚠️ 常见坑
    • EOF 前后不能有空格(除非使用 <<-EOF 配合 tab 缩进)
    • <<EOF(分隔符无引号):内容中的 $变量$(命令) 会被 shell 展开替换
    • <<'EOF'<<"EOF"(分隔符加引号):所有内容原样输出,变量和命令不会被展开

💪 今日必刷(全部终端实操)

  1. 后台启动 sleep 300,用 jobs 确认,再用 fg 拉回前台,Ctrl+C 终止
  2. 执行 ls /etc/hosts /nonexist(既有成功也有失败),将正常输出和错误输出分别写入不同文件
  3. 再执行一次同样的命令,但把正常输出和错误输出合并写入同一个文件
  4. ps aux 的输出按内存占用排序,只显示前 5 行(管道串联 sort + head
  5. 用 Here Document 创建 /tmp/config.ini,内容为 3 行配置项
  6. 排错题ls /nonexist 2>&1 > /tmp/out.txt——终端仍然显示错误信息,为什么?修正这条命令
  7. 排错题:你在后台运行了一个长时间脚本 long-task.sh &,终端不断被脚本的输出刷屏。如何在不杀进程的情况下让它静默?(提示:进程已在后台运行)

📚 命令详解

命令 详细参考
jobs bg-fg-jobs
fg bg-fg-jobs
bg bg-fg-jobs

Day 1:路径与目录切换

今日目标:在任意目录间自由跳转,用 ls 看清目录里有什么、多大、什么时候改的 🎯

环境准备

面向 Windows 用户,推荐 WindTerm 连接云服务器。备选:Windows Terminal + ssh 命令。

SSH 连接到云服务器

1
2
# 在 WindTerm 中新建会话,填写公网 IP,或终端中执行:
ssh root@你的服务器公网IP
  • 首次连接会提示 Are you sure you want to continue connecting (yes/no)?,输入 yes 回车
  • 输入密码时光标不会移动,这是正常的,输完回车即可

tmux 保活会话

云服务器网络波动会导致 SSH 断开,正在编辑的内容会丢失。tmux 让会话在服务端保持运行:

1
2
3
4
tmux new -s learn    # 新建名为 learn 的会话
# ... 在里面正常操作 ...
# 断线重连后:
tmux attach -t learn # 恢复会话,所有状态都在

在 tmux 内的快捷键(前缀 Ctrl+B,松开后再按下一个键):

操作 快捷键
水平分屏 Ctrl+B"
垂直分屏 Ctrl+B%
切换窗格 Ctrl+B → 方向键
暂时离开会话 Ctrl+Bd

如果不会操作 tmux 也不要紧。先用裸终端完成命令练习,把 tmux 记住一个就够了。

命令速览

命令 用途 核心参数
pwd 打印当前所在目录 -P 显示物理路径
cd 切换目录 ~ / .. / - / /
ls 列出目录内容 -l -a -lh -lt -ltr

逐个击破

① pwd — 打印当前工作目录

  • 语法pwd
  • 参数-P 显示物理路径(解析符号链接后的真实路径)
  • 🖥️ 上手练
    1. 打开终端直接输入 pwd,记录当前目录位置
    2. cd /tmp && pwd——验证已切换到 /tmp
    3. ln -s /tmp /tmp/mylink 2>/dev/null; cd /tmp/mylink; pwd && pwd -P——观察两者差异
  • ⚠️ 常见坑cd 软链接目录后 pwd 显示的是链接路径,用 pwd -P 才看到真实路径

② cd — 切换目录

  • 语法cd [DIR]
  • 参数
    • cd ~cd 直接回车 → 回到 home 目录
    • cd .. → 上一级
    • cd - → 回到上一次所在目录(反复执行可在两个目录间来回切换)
    • cd / → 根目录
  • 🖥️ 上手练
    1. cd /var/log && pwd,然后 cd - 看回到哪里,再 cd - 看又去哪了
    2. 从 home 目录开始,用 cd .. 一路退到根目录 /
    3. cd /etc/apt && cd——有什么区别?
  • ⚠️ 常见坑cd - 只能在最近两个目录间来回切,不是历史记录栈

③ ls — 列出目录内容

  • 语法ls [OPTIONS] [PATH]
  • 参数
    • -l → 长格式(权限、大小、修改时间)
    • -a → 显示隐藏文件(以 . 开头)
    • -lh → 人类可读的文件大小(K/M/G)
    • -lt → 按修改时间排序,最新的在前
    • -ltr → 按修改时间排序,最旧的在前(反向排序)
  • 🖥️ 上手练
    1. 分别执行 ls / ls -l / ls -lh,对比大小列的显示差异
    2. ls -la ~——home 目录下有多少隐藏文件?
    3. ls -lt /var/log——最近修改过的日志文件是哪个?
    4. ls -ltr /var/log——最旧的日志文件是哪个?
  • ⚠️ 常见坑ls -l 显示的文件大小默认是字节,看起来不直观,加 -h 变成人类可读

💪 今日必刷(全部终端实操)

  1. 不敲任何 ls,只用 cdpwd 从 home 目录出发,进入 /usr/share 再回到 /var/log,最后回到 home
  2. 列出 /etc 下所有以 host 开头的文件(提示:ls /etc/host*
  3. 用一条命令列出 /tmp 下所有文件(含隐藏文件),按修改时间排序,最新在前
  4. 排错题:某同学执行 cd /usr/share 后又执行 ls -ltr,发现输出为空。为什么?(提示:cd 拼写错误会静默停留在原目录;/usr/share 下如果只有子目录且用 ls -ltr 查看,在某些极端场景也可能无常规文件。排查思路:先 pwd 确认当前位置,再用 ls -la 查看所有内容。)
  5. 排错题:执行 ls -lh /rootPermission denied,是什么原因?如何查看该目录?(不要求 sudo,想想为什么没权限)

📚 命令详解

命令 详细参考
pwd 文件与目录管理-pwd
cd 文件与目录管理-cd
ls 文件与目录管理-ls

Day 2:文件与目录操作

今日目标:熟练创建、删除、复制、移动、软链接文件与目录,不误删不迷路 🎯

命令速览

命令 用途 核心参数
touch 创建空文件/更新文件时间戳 (无)
rm 删除文件或目录 -r -f
mkdir 创建目录 -p (级联创建)
rmdir 删除空目录 (只能删空目录)
cp 复制文件或目录 -r (递归复制目录)
mv 移动/重命名文件或目录 (无)
ln -s 创建软链接(符号链接) -s (不加就是硬链接)

逐个击破

① touch — 创建空文件或更新时间戳

  • 语法touch <FILE>
  • 🖥️ 上手练
    1. touch /tmp/test.txt——生成一个空文件
    2. ls -l /tmp/test.txt——查看大小是否为 0
    3. 等 1 分钟后再次 touch /tmp/test.txtls -l 观察修改时间是否更新
  • ⚠️ 常见坑touch 对已存在文件不会覆盖内容,只更新修改时间

② mkdir / rmdir — 创建与删除目录

  • 语法mkdir [OPTIONS] <DIR> / rmdir <DIR>
  • 参数mkdir -p a/b/c 一次性创建三级嵌套目录
  • 🖥️ 上手练
    1. mkdir /tmp/testdir——创建一个空目录
    2. rmdir /tmp/testdir——删除空目录(成功)
    3. mkdir -p /tmp/a/b/c && ls -R /tmp/a——验证三级目录一次性创建
    4. rmdir /tmp/a——报错,为什么?因为目录非空
  • ⚠️ 常见坑rmdir 只能删空目录,非空目录用 rm -rf

③ rm — 删除文件或目录

  • 语法rm [OPTIONS] <DEST>
  • 参数
    • -r → 递归删除(删目录必须加)
    • -f → 强制删除,不提示确认
    • -rf → 组合使用,递归强制删除
  • 🖥️ 上手练
    1. touch /tmp/delme.txt && rm /tmp/delme.txt && ls /tmp/delme.txt——确认已删除
    2. mkdir -p /tmp/deltest/sub && rm -rf /tmp/deltest——递归删除非空目录
    3. rm /tmp——报错(不能删目录,加 -r 才能)
  • ⚠️ 致命坑rm -rf / 是灾难命令!永远不要在 / 后不加路径就回车。rm -rf * 前请再三确认 pwd

④ cp — 复制文件或目录

  • 语法cp [OPTIONS] <SRC> <DEST>
  • 参数-r → 递归复制(复制目录必须加)
  • 🖥️ 上手练
    1. cp /etc/hosts /tmp/hosts.bak——复制文件到 /tmp
    2. cp -r /etc/apt /tmp/apt.bak——复制整个目录
    3. cp /etc/hosts /tmp/hosts.bak——如果 /tmp/hosts.bak 已存在会怎样?被覆盖!
  • ⚠️ 常见坑cp 默认覆盖同名文件不提示,加 -i 可开启确认;复制目录不加 -r 会报错

⑤ mv — 移动或重命名

  • 语法mv <SRC> <DEST>
  • 🖥️ 上手练
    1. touch /tmp/oldname.txt && mv /tmp/oldname.txt /tmp/newname.txt——重命名
    2. mkdir /tmp/mvdir && mv /tmp/mvdir /tmp/mvdir2——目录也一样可以重命名
    3. mv /tmp/newname.txt /tmp/mvdir2/——移动到目录内
  • ⚠️ 常见坑mv 在同文件系统内不复制数据,只改目录项(很快);跨文件系统则等价于 cp + rm

⑥ ln -s — 软链接(符号链接)

  • 语法ln -s <TARGET> <LINK_NAME>
  • 🖥️ 上手练
    1. ln -s /etc/hosts /tmp/myhosts && ls -l /tmp/myhosts——观察箭头指向
    2. cat /tmp/myhosts——通过软链接读取目标文件内容
    3. rm /tmp/myhosts——删除软链接不影响目标文件;验证:cat /etc/hosts 仍正常
  • ⚠️ 常见坑:删除软链接用 rm <LINK_NAME> 而不是 rm <LINK_NAME>/;目标文件被删后软链接还在但变成”死链接”

💪 今日必刷(全部终端实操)

  1. /tmp 下一次性创建目录结构 project/srcproject/docs
  2. /etc/hosts 复制到 project/src/ 下,改名为 hosts.bak
  3. project/ 下创建一个指向 /etc/hosts 的软链接,命名为 hosts_link
  4. ls -l 验证软链接指向正确;用 cat 通过软链接读取原文件内容
  5. 一次性删除整个 project/ 目录
  6. 排错题:执行 rmdir /tmpDirectory not empty,怎么办?(思考:非空目录的正确删除命令是什么?注意:不要在真实系统执行 rm -rf /tmp,这会删除系统临时目录!用你自建的测试目录 /tmp/project/ 来验证你的答案。)
  7. 排错题ln -s /etc/hosts /tmp/hosts_link 执行成功,但 cat /tmp/hosts_linkNo such file or directory——可能是什么原因?排查步骤是什么?

📚 命令详解

命令 详细参考
touch 文件与目录管理-touch
rm 文件与目录管理-rm
mkdir 文件与目录管理-mkdir
rmdir 文件与目录管理-rmdir
cp 文件与目录管理-cp
mv 文件与目录管理-mv
ln 文件与目录管理-ln

Day 3:文件内容查看

今日目标:不用编辑器也能快速查看文件——全貌、头部、尾部、实时追踪、分页浏览 🎯

命令速览

命令 用途 核心参数
cat 输出文件全部内容 -n 显示行号
head 查看文件开头 N 行 -n N
tail 查看文件末尾 N 行 / 实时追踪 -n N / -f
less 分页浏览大文件 空格/b//搜索/q

逐个击破

① cat — 输出文件全部内容

  • 语法cat <FILE>cat <FILE1> <FILE2>(拼接多文件)
  • 参数-n 给每一行加行号
  • 🖥️ 上手练
    1. cat /etc/hostname——查看本机主机名
    2. cat -n /etc/hosts——带行号查看 hosts 文件
    3. cat /etc/hosts /etc/hostname——两个文件内容拼接输出
  • ⚠️ 常见坑cat 大文件(如日志几百MB)会刷屏,应该用 less 分页查看

② head — 查看文件开头

  • 语法head -n <N> <FILE>
  • 🖥️ 上手练
    1. head -n 5 /etc/passwd——看系统账号文件前 5 行
    2. head -n 3 /etc/hosts——看 hosts 前 3 行
    3. 不用 -nhead /etc/passwd——默认输出前 10 行
  • ⚠️ 常见坑:参数是 -n 5 而不是 -5(旧写法可能兼容但不推荐)

③ tail — 查看文件末尾 / 实时追踪

  • 语法tail -n <N> <FILE> / tail -f <FILE>
  • 参数
    • -n N → 末尾 N 行
    • -f → 持续追踪文件新写入的内容(Ctrl+C 退出)
  • 🖥️ 上手练
    1. tail -n 5 /var/log/syslog——查看最近 5 条日志
    2. tail -f /var/log/syslog,打开另一个终端做一些操作,观察该终端日志变化
    3. tail -n 20 /etc/passwd——查看 passwd 最后 20 行
  • ⚠️ 常见坑tail -f 会阻塞终端,别忘了 Ctrl+C 退出

④ less — 分页浏览大文件

  • 语法less <FILE>
  • 操作键(在 less 内):
    • 空格 → 向下翻一页
    • b → 向上回翻一页
    • /关键词 回车 → 向下搜索,n 跳下一个匹配,N 跳上一个
    • q → 退出
  • 🖥️ 上手练
    1. less /var/log/syslog,用空格翻页、b 回翻、q 退出
    2. 在 less 中搜索 error(输入 /error 回车),用 n 查看所有匹配
    3. less /etc/services——这是个大文件,体验分页浏览比 cat 好在哪里
  • ⚠️ 常见坑:在 less 里按 q 退出后终端内容消失(less 不污染终端),想保留内容用 more 或用重定向

💪 今日必刷(全部终端实操)

  1. 查看 /etc/passwd 的第 1 行和第 50 行(提示:管道组合 head + tail
  2. less 打开 /var/log/syslog,搜索 error,找到 3 个匹配项后退出
  3. 用一条命令统计 /etc/passwd 的前 10 行(先 head 取前 10 行,再用 wc -l 确认是 10 行)
  4. touch /tmp/watch.log 创建文件(不创建的话 tail -f 会立即报错退出),然后打开两个终端窗口:终端A 执行 tail -f /tmp/watch.log;终端B 执行 echo "hello" >> /tmp/watch.log,观察终端A 的变化
  5. 排错题:执行 cat /var/log/syslog 终端疯狂刷屏看不清内容——如何优雅查看?
  6. 排错题tail -f /var/log/nginx/access.logNo such file or directory——可能原因是什么?如何排查日志文件实际位置?

📚 命令详解

命令 详细参考
cat 文件查看与文本处理-cat
head 文件查看与文本处理-head
tail 文件查看与文本处理-tail
less 文件查看与文本处理-less

Day 4:文本统计与处理

今日目标:统计行数/单词数、排序、去重——用管道串起来处理文本数据 🎯

命令速览

命令 用途 核心参数
wc 统计行数/单词数/字节数 -l -w -c
sort 排序 -r (逆序) / -n (按数值)
uniq 去重/统计重复次数 -c (计数)

逐个击破

① wc — 字数统计

  • 语法wc [OPTIONS] <FILE>
  • 参数
    • -l → 只统计行数
    • -w → 只统计单词数
    • -c → 只统计字节数
  • 🖥️ 上手练
    1. wc /etc/passwd——观察三个数字分别是什么(行/词/字节)
    2. wc -l /etc/passwd——系统有多少个用户账号?
    3. ls -l /etc | wc -l——/etc 下有多少文件?(ls -l 列目录时首行有 total N 汇总行,结果比实际文件数多 1,修正:ls -l /etc | tail -n +2 | wc -l
  • ⚠️ 常见坑wc -l 统计的是换行符个数,最后一行如果没有换行符不会被计入

② sort — 排序

  • 语法sort [OPTIONS] <FILE>
  • 参数
    • -r → 逆序(从大到小)
    • -n → 按数值排序(默认按字典序,10 < 2 字典序成立但数值序不成立)
    • -t + -k → 指定分隔符和排序列(后续 awk 课程会用到)
  • 🖥️ 上手练
    1. sort /etc/passwd——默认按字典序排列所有行
    2. sort -r /etc/passwd——逆序排列
    3. printf "2\n10\n1\n" | sort vs printf "2\n10\n1\n" | sort -n——观察字典序和数值序的区别
    4. ls -l /etc | sort -k5 -n | head——按文件大小排序列出 /etc 下文件
  • ⚠️ 常见坑:不加 -nsort 按字典序排列数字,10 排在 2 前面

③ uniq — 去重

  • 语法uniq [OPTIONS] <FILE>
  • 参数-c → 在每行前显示重复次数
  • 🖥️ 上手练
    1. printf "a\na\nb\nb\nb\nc\n" | uniq——相邻重复行被合并
    2. printf "a\na\nb\nb\nb\nc\n" | uniq -c——显示每行出现次数
    3. printf "a\nb\na\n" | uniq——为什么两个 a 没被合并?(不相邻!)
    4. printf "a\nb\na\n" | sort | uniq -c——先排序再去重,正确统计
  • ⚠️ 致命坑uniq 只合并相邻重复行,去重前通常要 sort | uniqsort -u

💪 今日必刷(全部终端实操)

  1. 统计 /etc/passwd 有多少行,然后只输出这个行数(不显示文件名)
  2. /etc/passwd 按逆序排列,取前 5 行
  3. 统计 /etc/passwd 中每种 shell 各被多少人使用(提示:awk -F: '{print $NF}' /etc/passwd | sort | uniq -c | sort -rn
  4. ls -l /etc | sort -k5 -rn | head -5 找出 /etc 下最大的 5 个文件
  5. 排错题:执行 cat /tmp/data.txt | uniq 后发现大量重复行还在——为什么?正确的去重方式是什么?
  6. 排错题sort -n /tmp/scores.txt 排序后 2 排在 10 前面正确,但 100 排在 20 前面——哪里错了?排查思路:先确认文件内容格式,再确认参数

📚 命令详解

命令 详细参考
wc 文件查看与文本处理-wc
sort 文件查看与文本处理-sort
uniq 文件查看与文本处理-uniq
0%