AI摘要

本文为Java程序员提供Linux实战手册:详解ps、jps、kill优雅停机,tail –F、grep、less日志技巧,top、du、find、awk等性能与文件处理命令,并强调tmux、别名、脚本化等习惯,助开发者摆脱“上线懵逼”,全面提升线上排查与运维效率。

面对Linux终端,很多Java程序员会感到陌生和畏惧。但我想告诉你,熟练使用Linux不是系统管理员的专利,而是现代Java开发者必须掌握的硬核技能。它能让你摆脱“本地一切正常,上线一脸懵逼”的困境,真正掌控你的应用。

一、进程管理:不只是pskill

1. ps - 深入进程细节

ps auxps -ef是基础,但关键在于如何解读输出和组合使用。

ps aux输出详解:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
myapp    12345  2.5  6.8 2982344 689012 ?      Sl   May15  30:20 java -Xms512m -Xmx1g -jar myapp.jar
  • VSZ (6982344): 虚拟内存大小,包含进程可能访问的所有内存(包括交换分区、库函数占用的内存等)。这个数字可能很大,不用太担心。
  • RSS (689012): 常驻内存集,进程实际使用的物理内存大小(单位KB)。这是判断Java应用真实内存占用的关键指标。上面的689012KB约等于673MB。
  • STAT (Sl): 进程状态码。S代表可中断的睡眠状态(通常就是在等待事件),l代表它是一个多线程进程。对于Java进程,看到Sl或者Ssl(还是会话领导者)是正常的。

实用组合拳:

  • 查看特定用户进程: ps -u myapp
  • 按内存排序: ps aux --sort=-%mem | head -10 (找内存消耗前10的进程)
  • 按CPU排序: ps aux --sort=-%cpu | head -10
  • 查看进程的线程: ps -T -p 12345-T显示线程,-p指定PID)

2. jps - 但要知道它的局限

jps很方便,但它有个大坑:它只能列出与当前用户、当前目录有相同有效权限的Java进程。如果你用sudo切换了用户,可能就找不到进程了。这时ps -ef | grep java更可靠。

3. kill - 优雅停机的艺术

粗暴地kill -9是最后手段,它会带来一系列问题:

  1. 数据库事务无法回滚,导致数据不一致。
  2. 线程池中的任务被强制中断,可能处于中间状态。
  3. 应用没有机会执行ShutdownHook,无法完成清理工作(如关闭网络连接、释放文件锁、将注册信息从注册中心移除)。

正确的停机流程:

# 1. 先发送TERM信号(15),允许优雅停机
kill 12345

# 2. 等待一段时间(比如30秒),让应用处理完存量请求
sleep 30

# 3. 检查进程是否还在
ps -p 12345

# 如果进程还在,说明可能卡住了,发送INT信号(2),类似Ctrl+C
kill -2 12345

# 再等待10秒
sleep 10

# 如果还在,才使用终极手段KILL信号(9)
kill -9 12345

Spring Boot应用的优雅停机:
如果你使用Spring Boot,并通过server.shutdown=graceful开启优雅停机,应用在收到TERM信号后,会停止接收新请求,并等待存量请求完成,这通常需要配合spring.lifecycle.timeout-per-shutdown-phase设置最大等待时间。

二、日志查看:从会看到“精通”

1. tail - 实时追踪的进阶技巧

  • tail -f 默认跟踪文件描述符,即使文件被重命名(如日志轮转logrotate),它可能就失效了。
  • tail -F (大写F)会检查文件的inode,即使文件被轮转重建,它也能继续跟踪新文件生产环境强烈推荐使用-F
# 最佳实践:实时追踪,并高亮关键信息
tail -F /app/logs/application.log | grep --line-buffered -i -E "(error|exception|timeout)" --color=auto
  • --line-buffered: 确保grep逐行输出,而不是攒够一缓冲区再输出,保证实时性。
  • -E: 启用扩展正则表达式,可以用|表示“或”。

2. grep - 日志分析的瑞士军刀

  • 查看异常堆栈: 异常信息通常跨越多行。grep-A(之后), -B(之前), -C(前后)参数至关重要。

    # 搜索"NullPointerException",并显示其之后20行(完整的堆栈信息)
    grep -A 20 "NullPointerException" application.log
    
    # 显示异常的前5行(上下文)和后20行(堆栈)
    grep -C 5 -A 20 "SomeBusinessException" application.log
  • 反向搜索: grep -v 排除包含某些关键词的行。例如,查看非DEBUG级别的日志:

    grep -v "DEBUG" application.log
  • 统计出现次数: grep -c "某个错误" 可以快速统计错误发生的次数,有助于判断问题严重性。

3. less - 大文件查看的利器

less不仅仅是为了分页,它的搜索和导航功能极其强大。

less application.log

进入less后:

  • /ERROR: 向下搜索"ERROR"。
  • ?WARN: 向上搜索"WARN"。
  • n: 跳转到下一个匹配项。
  • N: 跳转到上一个匹配项。
  • G: 跳转到文件末尾。(查看最新日志的神键)
  • g: 跳转到文件开头
  • F: 进入tail -f模式,实时滚动。按Ctrl+C退出此模式回到普通less模式。

三、性能与资源监控:洞察系统状态

1. top的交互模式详解

运行top后,它是一个交互式界面:

  • 1: 展开显示所有CPU核心的详细使用情况。
  • c: 切换显示完整的命令行(COMMAND列),对于识别具体的Java应用非常有用。
  • x: 高亮显示排序的列。
  • Shift + >Shift + <: 向右或向左移动排序字段。比如按了M(内存排序)后,可以用这个移动高亮条。
  • u -> 输入用户名: 只显示特定用户的进程。

2. 磁盘空间分析的实战

du命令的巧妙用法:

# 找出当前目录下最大的10个文件/目录
du -ah . | sort -rh | head -n 10

# 分析日志目录,按大小排序,只显示一级子目录
du -h --max-depth=1 /app/logs/ | sort -hr

# 查找并删除7天前的“.log”文件(危险操作,务必先echo确认)
find /app/logs/ -name "*.log" -mtime +7 -exec echo rm -f {} \;
# 确认输出文件列表无误后,去掉`echo`执行真正的删除
find /app/logs/ -name "*.log" -mtime +7 -exec rm -f {} \;

四、网络与调试:连通性保障

1. 端口占用排查

# 查看8080端口被哪个进程监听
netstat -tunlp | grep :8080
# 或者用更现代的ss
ss -tunlp | grep :8080

# 如果你怀疑端口被占用但服务没起来,可能是TIME_WAIT状态的连接,用这个
ss -tunlp | grep LISTEN

2. 远程调试端口转发

当你在本地IDE需要远程调试服务器上的Java应用时(应用启动参数需加-agentlib:jdwp=...),需要使用SSH隧道:

# 将服务器的5005调试端口映射到本地的5005端口
ssh -L 5005:localhost:5005 user@your-server-ip -N

然后在IDE中连接localhost:5005即可。

五、文件与文本处理:效率提升的关键

1. find命令的-exec魔力

find的强大之处在于它能对找到的文件执行操作。

# 找到5天前的日志文件并打包压缩(节省空间)
find /app/logs/ -name "*.log" -mtime +5 -exec gzip {} \;

# 找到所有的Jar包,并列出它们的详细属性
find . -name "*.jar" -exec ls -l {} \;

# 在多个Jar包中查找某个类(常用于排查类冲突)
find . -name "*.jar" -exec jar -tf {} \; | grep "MyClassName"

2. awk - 文本提取利器

虽然awk是一门语言,但掌握几个简单用法就能极大提升效率。

# 提取日志中的时间戳和日志级别(假设格式为 "时间 级别 信息")
tail -100 application.log | awk '{print $1, $2, $3}'

# 统计每种HTTP状态码出现的次数(假设日志中包含 "HTTP/1.1" 200")
grep "HTTP/1.1" access.log | awk '{print $NF}' | sort | uniq -c | sort -nr
# 解释:awk '{print $NF}' 打印最后一列(状态码),uniq -c 计数,sort -nr 按计数倒序排列。

总结:养成好习惯

  1. 使用tmuxscreen: 在远程服务器上执行长时间任务时,用它们来保持会话,防止网络中断导致任务失败。
  2. 命令别名: 在~/.bashrc中设置别名,例如 alias tailf='tail -F', alias ll='ls -lht'
  3. 脚本化: 将复杂的排查步骤(如检查进程、端口、日志错误)写成一个Shell脚本,下次一键执行。

Linux命令的学习是一个持续的过程。不要试图一次性记住所有参数,而是从解决实际问题出发,每次掌握一两个新技巧,久而久之,你就会发现这个黑色窗口为你打开了一个全新的、充满控制力的世界。

版权声明 ▶ 本网站名称:黄磊的博客
▶ 本文标题:Java程序员的Linux生存指南:从入门到精通的生产力手册
▶ 本文链接:https://www.huangleicole.com/linux/73.html
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

如果觉得我的文章对你有用,请随意赞赏