每个开发者都需要了解的 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,速度更快。
  • -t TCP,-u UDP,-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 工具。

linuxdevopsbashproductivityjava