learn.ochresign
阶段 0 · 补前置

Linux 命令行入门

装好 WSL2,掌握文件、权限、进程和管道,以及写服务器时天天要用的十几个命令。

为什么要先学这个

后端服务几乎都跑在 Linux 上,epoll 也是 Linux 独有的。后面每个阶段你都要在终端里编译、运行、看日志、查端口、杀进程。这些操作越熟练,调试就越快。

准备环境:WSL2

Windows 用户不用装双系统,用 WSL2 就行。在管理员 PowerShell 里运行:

wsl --install -d Ubuntu-24.04

重启后会提示你设置一个 Linux 用户名和密码。然后在 VS Code 里装 WSL 插件,按 Ctrl+Shift+P 选 “WSL: Connect to WSL”,之后的编辑、终端和调试就都在 Linux 里进行了。

代码放在 Linux 的家目录里(例如 ~/code),不要放在 /mnt/c/... 下。跨系统读写文件会慢很多。

四个核心概念

概念 一句话解释 相关命令
文件与目录 一切从根目录 / 开始,~ 是你的家目录 pwd ls cd mkdir cp mv rm
权限 每个文件分别对所有者、组、其他人设置读 r、写 w、执行 x 权限 ls -l chmod chown
进程 运行中的程序,每个进程有一个 PID ps top kill
管道与重定向 把一个命令的输出交给另一个命令,或者写进文件 \| > >> 2>&1

写服务器时最常用的命令

# 找文件、搜内容
find . -name "*.cpp"
grep -rn "epoll_wait" src/

# 看进程
ps aux | grep epoll_echo
top                         # 按 q 退出,按 P 按 CPU 排序

# 看端口:谁在监听 8888
ss -ltnp | grep 8888

# 后台运行并把输出写进日志
./epoll_echo > server.log 2>&1 &
tail -f server.log          # 实时看日志,Ctrl+C 退出

# 结束进程
kill <PID>                  # 礼貌地请它退出(SIGTERM)
kill -9 <PID>               # 强制结束(SIGKILL),阶段 2 测持久化会用到

# 查文档
man 2 epoll_wait            # 第 2 节是系统调用

ss 是新版的 netstat。-l 表示只看监听中的,-t 表示 TCP,-n 表示显示数字端口,-p 表示显示进程。

常见的坑

  • 端口被占用:bind: Address already in use。先用 ss -ltnp 找到占用端口的进程,再决定是结束它还是换个端口。
  • 没有执行权限:Permission denied。运行 chmod +x 文件名。
  • Ctrl+Z 不是退出:它只是把程序挂起,程序还占着端口。退出要用 Ctrl+C,挂起的程序可以用 fg 拿回前台再结束。

自测

./a.out > out.txt 2>&1 里的 2>&1 是什么意思?

把标准错误(文件描述符 2)重定向到标准输出(文件描述符 1)当前指向的地方,也就是 out.txt。这样正常输出和错误信息都会写进同一个文件。

kill 和 kill -9 有什么区别?

kill 默认发送 SIGTERM,程序可以捕获这个信号,做完清理(比如刷盘、关闭连接)再退出。kill -9 发送 SIGKILL,程序无法捕获,会被立即终止,来不及做任何清理。

怎么查出是哪个进程占用了 6379 端口?

ss -ltnp | grep 6379,输出里的 users:(("名字",pid=1234,...)) 就是占用端口的进程。

面试常问

进程和线程有什么区别?

参考回答: 进程是资源分配的单位,有独立的地址空间、fd 表等资源;线程是 CPU 调度的单位,同一进程内的线程共享地址空间和 fd,只各自拥有栈和寄存器。所以线程创建和切换更便宜,通信也方便(直接读写共享内存),但一个线程崩溃会拖垮整个进程,共享数据还要加锁。

可能的追问: 进程间通信有哪些方式?答管道、消息队列、共享内存、信号量、信号、socket,其中共享内存最快,但需要自己做同步。

线上一个服务 CPU 跑到 100%,你怎么排查?

参考回答: 先用 top 找到占 CPU 的进程,再用 top -H -p <pid> 看是哪个线程。然后用 perf top -p <pid> 或 perf record -g 看热点函数;没有 perf 的话,gdb -p <pid> 挂上去执行 thread apply all bt,多抓几次调用栈,总停在同一处的就是热点。常见原因是死循环、忙等(比如 epoll_wait 超时设成 0)、或者 LT 模式下一直关注 EPOLLOUT。

僵尸进程和孤儿进程是什么?

参考回答: 子进程退出后,父进程没有调用 wait / waitpid 回收,它的进程表项就一直留着,这就是僵尸进程(ps 里状态是 Z)。父进程先退出、子进程还在跑,子进程就成了孤儿进程,会被 init(1 号进程)收养,没有危害。处理僵尸进程的办法是父进程调用 waitpid,或者处理 SIGCHLD 信号。

怎么看一台机器上的 TCP 连接状态?

参考回答: 用 ss -tanp(老系统用 netstat -tanp)列出所有 TCP 连接、状态和所属进程。想统计各状态的数量,可以 ss -tan | awk '{print $1}' | sort | uniq -c。查某个端口被谁占了用 ss -ltnp | grep 6379 或 lsof -i :6379。

原文与延伸