每个开发者都需要了解的 Linux 命令
1. 总览
做开发的无不曾通过 SSH 连上服务器、打开终端调试或部署某个应用,然后就开始费力寻找正确的命令。本文汇总了日常工作中最常用的 Linux 命令:文件管理、搜索、文本处理、进程监控、网络检查、查看日志。读完这篇文章后,你就掌握了一套“必杀技”命令,可以快速调试,再也不用每次都去 Google。
在这篇文章中,我以 Ubuntu/Debian 上的 bash 为主要示例,这些命令在所有发行版上基本相同。
2. 基本的文件和目录操作
mkdir -p ~/projects/order-service/src/main/java
cd ~/projects/order-service
touch application.properties
ls -la
mkdir -p递归创建多级目录,如果目录已存在也不会报错。touch创建空文件(或者如果文件已存在,则更新时间戳)。ls -la列出所有文件(包括隐藏文件如.env、.git),并显示权限、所有者和大小。
drwxr-xr-x 3 nonla nonla 4096 Oct 5 10:00 .
-rw-r--r-- 1 nonla nonla 0 Oct 5 10:00 application.properties
一些需要谨慎操作的命令:
cp -r src/ src-backup/ # 递归复制目录
mv OrderService.java OrderServiceImpl.java # 重命名或移动
rm -rf target/ # 递归删除,不提示
提示:
rm -rf没有回收站,删除即永久丢失。在执行前,请始终用pwd检查当前目录,特别是在复制粘贴来自其他地方的命令时。
3. 使用 find 和 grep 搜索
3.1. find — 按条件查找文件
find . -name "*.java" -newer pom.xml
这个命令查找所有在 pom.xml 之后修改过的 .java 文件 — 在提交前想知道哪些文件刚被改过时很有用。
find . -type f -size +10M
查找大于 10MB 的文件,通常用来清理占用空间的日志或 build artifact。
3.2. grep — 在文件中查找内容
grep -rn "PaymentService" --include="*.java" src/
-r递归查找子目录。-n打印行号。--include仅限.java文件,避免搜索target/目录。
src/main/java/com/nonla/OrderController.java:15: private final PaymentService paymentService;
通过 pipe 将 grep 与 find 结合,处理更复杂的筛选:
find . -name "*.log" | xargs grep -l "OutOfMemoryError"
xargs 将来自 find 的文件列表传给 grep -l(仅打印包含匹配模式的文件名,不打印内容)。
4. 使用 awk、sed、cut 处理文本
这是一组“日志处理”命令 — 当需要从冗长的输出中提取数据时威力巨大。
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
awk '{print $1}'提取每行的第一列(通常是 IP)。sort | uniq -c分组并统计出现次数。sort -rn按数字降序排列,head -5取前 5 个。
152 192.168.1.10
98 10.0.0.5
47 172.16.0.3
这是找出请求量最多的 IP 的最快方法,无需编写脚本。
sed 用于直接替换文件中的文本:
sed -i 's/spring.profiles.active=dev/spring.profiles.active=prod/' application.properties
-i 表示原地修改文件。如果想更安全,可以使用 sed -i.bak '...' 自动创建备份文件 .bak。
cut 按分隔符分割列,比 awk 简单,当你只需要一列时:
cat /etc/passwd | cut -d: -f1 | head -3
5. 监控进程和系统资源
ps aux | grep java
打印所有进程,过滤包含 java 的行 — 快速了解你的 Spring Boot 应用是否在运行以及它的 PID 是多少。
nonla 12345 2.1 5.3 2345678 432100 ? Sl 10:00 0:15 java -jar order-service.jar
第二列是 PID。用这个 PID 杀掉进程或查看详细信息:
kill -15 12345 # 发送 SIGTERM,让应用优雅关闭
kill -9 12345 # 强制杀死,只有在 -15 不起作用时才用
提示:
kill -9不给应用运行 shutdown hook 的机会(比如关闭连接池、刷新日志)。总是先尝试-15。
实时查看资源使用情况:
top -o %MEM
-o %MEM 按内存使用量排序进程 — 当怀疑内存泄漏时非常有用。想要更好的界面可以安装 htop。
检查磁盘:
df -h
du -sh /var/log/*
df -h 查看每个分区的使用空间(人类可读格式)。du -sh 查看 /var/log 中每个子目录占用的空间 — 当服务器报告“no space left on device”时非常必要。
6. 网络和端口检查
ss -tulnp | grep 8080
ss是新版的netstat,速度更快。-tTCP,-uUDP,-l监听状态,-n数字格式(不解析 DNS),-p包含进程。
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("java",pid=12345,fd=45))
立即知道 8080 端口被 PID 12345 的 Java 进程占用 — 当遇到 Address already in use 错误时非常有用。
使用 curl 快速测试 API:
curl -s -X POST http://localhost:8080/api/orders \
-H "Content-Type: application/json" \
-d '{"customerId":1,"amount":99.5}'
-s 静默模式(隐藏进度条),-X POST 指定方法,-d 设置 JSON body。如果要查看响应头,加上 -i。
lsof 命令可以查看进程打开的具体文件/socket:
lsof -i :8080
7. 文件权限
chmod +x deploy.sh
chown nonla:nonla application.properties
chmod 640 .env
chmod +x给脚本添加执行权限。chown user:group改变所有者 — 通常需要sudo当文件属于其他用户。chmod 640表示所有者可读写(6)、组可读(4)、其他人无权限(0) — 这是.env等敏感文件的标准权限。
-rw-r----- 1 nonla nonla 128 Oct 5 10:00 .env
提示: 千万不要在生产环境
chmod 777。这是暴露.env或 SSH key 等敏感文件的最快方式。
8. 压缩和解压
tar -czvf order-service.tar.gz order-service/
tar -xzvf order-service.tar.gz -C /opt/apps/
-c创建归档,-x解压,-z使用 gzip,-v详细输出,-f指定文件名。-C解压时指定目标目录,而不是解压到当前目录。
部署时结合 scp 或 rsync 上传文件到服务器:
scp order-service.tar.gz user@10.0.0.5:/opt/apps/
rsync -avz --progress target/*.jar user@10.0.0.5:/opt/apps/
rsync 仅传输变化部分(delta transfer),比 scp 快得多,特别是多次更新大文件时。
9. 实时查看日志
tail -f /var/log/order-service/app.log
-f(follow)保持终端打开,新行写入文件时立即显示 — 调试生产环境时必须掌握的命令。
按模式过滤 tail 输出的日志:
tail -f app.log | grep --line-buffered "ERROR"
--line-buffered 很关键,因为 grep 默认按块 buffer,没有这个标志输出可能会延迟。
如果应用运行在 systemd 上,用 journalctl 代替手工查找日志文件:
journalctl -u order-service -f --since "10 minutes ago"
-u 指定服务单位,-f follow,--since 限制时间范围 — 避免读取数百万行旧日志。
10. 从 Java 调用 Linux 命令
有时你需要从 Java 代码直接调用 shell 命令,比如在写大文件前检查磁盘:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
public class ShellRunner {
public static String run(List<String> command) throws Exception {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process process = builder.start();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String output = reader.lines().reduce("", (a, b) -> a + b + "\n");
process.waitFor();
return output;
}
}
}
ProcessBuilder接受参数列表(不是手工拼接的命令字符串,避免 shell 注入)。redirectErrorStream(true)将标准错误合并到标准输出,便于读取单一流。process.waitFor()阻塞当前线程直到子进程完成。
用 JUnit 5 + AssertJ 测试:
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class ShellRunnerTest {
@Test
void shouldReturnCurrentDirectoryListing() throws Exception {
String output = ShellRunner.run(List.of("ls", "-la"));
assertThat(output).contains("total");
}
}
这个测试实际运行 ls -la 并检查输出包含 “total”(ls -la 始终输出的第一行,显示块总数) — 确认 ProcessBuilder 可以真实调用 shell 命令。
提示: 从 Java 生产代码调用 shell 命令是把双刃剑 — 容易依赖 OS、难以测试、且若参数来自用户输入易引发注入。仅用于内部工具或运维脚本,避免在核心业务逻辑中使用。
11. 常见错误
- 运行
rm -rf时环境变量为空,比如$DIR未设置的rm -rf $DIR/*— 删掉根目录。在脚本中总是用set -u或提前检查变量。 - 忘记
sudo而需要 root 权限,导致模糊的Permission denied— 先用ls -la检查权限。 - 习惯性使用
kill -9,导致 Spring Boot 应用无法关闭连接池,引发数据库泄漏。 tail -f后跟grep却忘了--line-buffered,误以为日志没有更新但实际上被 buffer 了。- 运行
chmod 777来“快速解决权限问题” — 这是安全漏洞,特别危险的是给.env或 SSH key 这样的敏感文件。
12. 结语
本文的命令 — find、grep、awk/sed、ps/kill、ss/curl、tar、tail -f、journalctl — 是你自主调试的最小工具集,无需等待 DevOps 团队。精通它们不是要记住每个标志,只需知道某个命令解决什么问题,遇到细节时查 man。终端仍然是最快的调试工具,无论你身边有多少 Grafana、Kibana 或 APM 工具。