AIHub

Linux 与命令行:后端工程师的日常武器

入门18 分钟读完2026-08-06#后端#Linux#命令行#运维排障
Linux 与命令行:后端工程师的日常武器

后端工程师的代码最终跑在 Linux 服务器上,而服务器没有图形界面、没有鼠标,只有一个终端。凌晨三点收到报警,你能依靠的只有命令行。命令行熟练度,直接决定你是五分钟定位问题,还是五小时抓瞎。

好消息是,日常 90% 的场景只需要不到 20 个命令。本篇不罗列命令大全,只讲真正高频的,并且每个都配真实的使用场景。建议在本地终端(macOS 的 Terminal 或 Windows 的 WSL)边看边敲——只看不敲,本篇的价值会直接打对折。

先看大局:机器现在怎么样

登上服务器的第一件事,永远是看整体状态,就像医生先看体温和心率。

top

top 是实时仪表盘,重点看三行:

  • load average:系统负载,三个数字分别是 1/5/15 分钟平均值。经验法则:持续超过 CPU 核数就说明有任务在排队
  • %Cpu(s)us(用户程序占用)高说明你的服务在忙;wa(IO 等待)高说明磁盘或网络是瓶颈,CPU 在干等。
  • MiB Mem:看 free(空闲)而不是 used——Linux 会主动用空闲内存做缓存,used 高不等于内存不够。

top 界面里按 P 按 CPU 排序、按 M 按内存排序、按 1 展开每个核、按 q 退出。更喜欢彩色界面的话可以装 htop,操作逻辑一样。

配套的两个快速命令:

df -h        # 磁盘使用情况,-h 用人类可读的 G/M 显示
free -h      # 内存使用情况

磁盘写满是最常见的低级事故——日志不停写,某天磁盘 100%,数据库无法写入,服务全体报错。df -h 应该成为你登机器的条件反射。

进程与端口:我的程序怎么了

场景一:找到那个吃 CPU 的进程。

ps aux --sort=-%cpu | head -10

ps aux 列出所有进程,--sort=-%cpu 按 CPU 降序排,head -10 只看前 10 个。找到你的服务进程,记下 PID(进程号)。想精确找某个服务:

ps aux | grep node
pgrep -fl node     # 更简洁的写法

场景二:端口被谁占了? 启动服务时报 EADDRINUSE(地址已被占用),用这两个命令查:

ss -tlnp | grep 3000     # 谁在用 3000 端口(t=TCP l=监听 n=数字端口 p=进程)
lsof -i :3000            # 等价的另一种写法,macOS 上常用

ssnetstat 的现代替代品,更快,输出里直接带进程名和 PID。macOS 没有 ss,用 lsof -i :3000

场景三:杀掉失控的进程。

kill 12345        # 礼貌地请求 PID 12345 退出(发 SIGTERM)
kill -9 12345     # 强制杀死(SIGKILL),不给它收拾残局的机会

永远先 killkill -9kill -9 会跳过进程的清理逻辑,正在写的文件可能损坏、连接可能没正常关闭——那是最后手段,不是默认手段。

Linux 排障命令全景

日志排查三件套:tail、grep、awk

线上排障 70% 的时间在看日志。三个命令组合起来威力巨大。

tail:实时追踪日志流。

tail -f /var/log/app/error.log      # 持续滚动显示新写入的日志
tail -n 500 app.log | less          # 先看最后 500 行

tail -f 是排障的第一反应:复现问题的同时盯着日志滚动,错误往往在滚动中自己跳出来。

grep:从海量日志里捞出你要的行。

grep "ERROR" app.log                    # 所有错误行
grep -i "timeout" app.log               # 忽略大小写
grep -C 5 "ERROR" app.log               # 错误行前后各 5 行上下文(最重要!)
grep -c "ERROR" app.log                 # 只数有多少条
grep "ERROR" app.log | grep "userId=42" # 管道串联:错误里再筛特定用户

只看错误行往往看不懂原因,-C 5 看上下文才是关键——真正的线索常常在报错前几行的警告里。

awk:把日志当表格处理。 假设日志每行是 时间 级别 耗时 消息 这样的结构:

awk '{print $1, $3}' app.log              # 打印第 1、3 列
awk '$3 > 1000' app.log                   # 耗时超过 1000ms 的行
awk '{print $2}' app.log | sort | uniq -c | sort -rn | head   # 各级别日志数量统计

最后那条是经典组合拳:取第 2 列 → 排序 → 去重计数 → 按数量倒序 → 看前 10。三十秒内你就能回答“今天哪类报错最多”。

一套实战排障套路:报警说接口超时 → 先 top 看机器整体 → ss -tlnp 确认进程活着且端口在听 → tail -f error.log 复现请求看实时报错 → grep -C 5 挖上下文 → 如果是偶发问题,用 awk 统计错误的时间分布规律。这个顺序能解决大部分线上问题。

文件、权限与磁盘

服务器上另一类高频问题是权限和空间。看懂 ls -l 的输出是第一步:

ls -l app.js
# -rw-r--r-- 1 deploy admin 4096 Aug  6 10:00 app.js

开头十位是权限:第 1 位是文件类型(- 文件、d 目录),后九位分三组——属主、属组、其他人,每组 rwx 分别代表读、写、执行。上面的 rw-r--r-- 表示属主可读写,其他人只读。改权限:

chmod +x deploy.sh       # 给脚本加执行权限
chmod 600 ~/.ssh/id_rsa  # 私钥只允许属主读写(SSH 强制要求)

数字模式里 4=读、2=写、1=执行,600 就是属主 4+2、其他全 0。服务起不来、报 Permission denied 时,先 ls -l 看看权限和属主对不对——尤其是以 root 身份拷了文件、却用普通用户跑服务的场景。

磁盘排查两个命令:

du -sh /var/log/* | sort -rh | head        # 哪个日志目录最占空间
find /var/log -name "*.log" -mtime +7 -delete   # 删除 7 天前的日志

du 定位“谁吃掉了磁盘”,find 负责清理。带 -delete 的命令先在测试目录里跑一遍再上生产。

后台运行与环境变量

本地开发时 Ctrl+C 关掉程序很自然,但服务器上你关掉 SSH 窗口,前台进程也会被杀掉。让程序在后台常驻的入门写法:

nohup node server.js > app.log 2>&1 &

拆解一下:nohup 让进程忽略挂断信号(SSH 断开不死),> app.log 2>&1 把标准输出和标准错误都写进日志文件,最后的 & 放到后台运行。这只是入门方案——生产环境应该用 systemd 或 PM2 这类进程管理器,它们能在程序崩溃后自动重启,nohup 不会。

环境变量是配置注入的标准方式,密钥、数据库地址都不该写死在代码里:

export DATABASE_URL="postgres://localhost:5432/shop"   # 设置(仅当前终端有效)
echo $DATABASE_URL                                      # 查看
env | grep DATABASE                                     # 列出相关变量

临时对单个命令生效可以写在命令前面:NODE_ENV=production node server.js。要永久生效就写进 ~/.bashrc(或 zsh 的 ~/.zshrc),改完执行 source ~/.bashrc 立即加载。

vim 保命操作

在服务器上改配置只能用终端编辑器,vim 几乎每台机器都有。你不需要精通,只需要保命四招

vim app.conf
  • i 进入编辑模式(左下角出现 -- INSERT --),这时才能打字
  • Esc 退回普通模式
  • 普通模式下输入 :wq 回车:保存并退出
  • 普通模式下输入 :q! 回车:不保存强制退出(改错了就用这招)

再加两个实用的:普通模式下按 G 跳文件末尾、gg 回首行,/关键词 回车搜索。记住黄金法则:任何时候慌了就连按 Esc,然后 :q! 全身而退

SSH 与文件传输

SSH:远程登录的标准姿势。

ssh user@192.168.1.100          # 密码登录
ssh -p 2222 user@host           # 非默认端口

生产环境应该用密钥登录:本地 ssh-keygen 生成密钥对,把公钥(~/.ssh/id_rsa.pub 的内容)追加到服务器的 ~/.ssh/authorized_keys,之后免密登录。记得把服务器的密码登录关掉/etc/ssh/sshd_configPasswordAuthentication no),这是最基本的加固。

scp 与 rsync:传文件。

scp app.tar.gz user@host:/opt/apps/          # 本地传到服务器
scp user@host:/var/log/app.log ./            # 从服务器拉回来
rsync -avz --progress dist/ user@host:/var/www/   # 同步整个目录

rsyncscp 聪明:-a 保留权限和时间戳、-v 显示过程、-z 压缩传输,而且只传有变化的文件,中断后重跑能续传。部署静态资源、备份日志,都用 rsync

管道与重定向:命令行真正的超能力

前面反复出现的 |>,才是命令行区别于图形界面的本质。|(管道)把前一个命令的输出交给后一个命令当输入,> 把输出写进文件(>> 是追加)。这意味着每个命令只需做好一件事,靠组合就能完成复杂任务:

history | grep ssh                          # 找以前敲过的 ssh 命令
tail -n 1000 app.log | grep ERROR | wc -l   # 最近 1000 行里有多少错误
ps aux | grep node | grep -v grep | awk '{print $2}'   # 只取 node 进程的 PID

最后一条里的 grep -v grep 是个经典细节:-v 反向过滤,把 grep 自己的进程从结果里剔除。当你发现自己在图形界面上反复点来点去做机械操作时,停下来想想——那件事多半能用一行管道命令完成。

顺带一提 Ctrl+R:在终端里按下它可以反向搜索历史命令,比你一遍遍按上箭头翻找快十倍,是命令行老手使用频率最高的快捷键之一。

再补一个长任务保命技巧:tmux。在服务器上跑耗时操作(数据迁移、大文件压缩)时,如果 SSH 断了,前台任务就完了。tmux 创建一个独立于 SSH 连接的会话:tmux 进入会话后正常跑命令,按 Ctrl+B 再按 D 脱离会话,任务在后台继续;下次登录用 tmux attach 回到原来的会话,屏幕上的内容分毫未动。

常见误区

  • 误区一:上来就 kill -9 强杀会跳过清理逻辑,可能导致数据损坏。先礼貌 kill,等几秒不行再升级。
  • 误区二:看到 used 内存高就以为内存泄漏。 Linux 会把空闲内存用作磁盘缓存,判断内存压力要看 free -h 里的 available 列。
  • 误区三:只看报错那一行日志。 错误的根因几乎总在上下文里,养成 grep -C 5 的习惯。
  • 误区四:在生产服务器上边查边学。 把本篇命令在本地练到形成肌肉记忆再去碰生产;生产上敲命令前多想一秒,尤其是带 rmkill、重定向 > 的。
  • 误区五:什么都用 sudo 遇到权限问题就 sudo 一把梭,结果文件属主全变成 root,普通用户的服务再也读写不了,制造出新问题。正确做法是先 ls -l 看清属主和权限,用 chown/chmod 精准修复,而不是用 sudo 绕过。

小结

后端工程师的 Linux 日常可以浓缩为:top 看大局,ps/ss/lsof 管进程和端口,tail -f + grep -C + awk 三件套排查日志,ls -l/chmod/du/find 搞定权限与磁盘,nohup 和环境变量管住进程与配置,vimi/Esc/:wq/:q! 四招保命,ssh 登录、rsync 传文件。命令不多,但每个都要练熟——线上故障时你的手速就是止损速度。

至此,你已经有了路线图(第 1 篇)、看透了网络(第 2 篇)、握住了日常武器(本篇)。下一篇我们深入代码运行的机器内部,以 Node.js 为例吃透语言运行时——为什么你的异步代码是那样的执行顺序,事件循环到底在循环什么。


系列导航:上一篇《网络基础抓包级理解:HTTP、TCP/IP 与 DNS》(/content/backend-expert-02-network) · 下一篇《吃透语言运行时:以 Node.js 事件循环为例》(/content/backend-expert-04-nodejs-runtime)

相关教程

Linux 与命令行:后端工程师的日常武器 | AIHub