资讯动态

Java程序员必备的Linux命令实战指南

发布时间:2026/10/19 13:47:54 来源:尧图企业网站定制
正文直接从 ## 1 开始。1. 先解决一个问题Java程序员为什么总觉得命令记不住我见过不少Java开发同学写业务代码挺顺手一到了Linux服务器上就手足无措。不是他们不努力是学习姿势不太对。今天这篇“命令篇”不打算把所有的Linux命令都给你过一遍而是换个思路从Java应用部署、运行、排障的完整链路里挑出那些真正值得记、重复用、能救命的命令讲清楚它们什么时候用、为什么这么用、用完之后下一步该怎么办。1.1 命令不是字典而是“动作的组合”很多人学命令的方式是打开一个命令大全从ls、cd开始背背到管道、重定向就放弃了。这种做法的最大问题在于命令脱离了场景就像你把一本词典背了一遍真到了写邮件的时候还是憋不出几句话。我的建议是把命令当成动词来记把参数当成副词把文件路径、进程PID、端口号当成宾语。比如“我想看这个Java进程的资源消耗”对应的是top -Hp pid而不是孤立地记一个top。比如“我想从日志里把异常信息捞出来”对应的是tail -f app.log | grep --line-buffered Exception而不是单纯记grep的某个参数。一旦你接受了“命令是动作组合”这个思路就不会再去纠结要不要把几百个命令都背下来而是会主动问自己我现在要做什么完成这个动作需要哪几个命令拼接。还有一点很重要Java程序员有JVM这套工具兜底jps、jstack、jmap、jstat这些命令虽然不是Linux原生命令但它们经常要和ps、top、grep组合使用。所以说Linux命令从来不是孤立的知识点而是和你的Java技能树长在一起的。1.2 先画一条Java应用的生命周期线我习惯把学习路径切成几个阶段打包上传、解压部署、启动服务、运行观察、日志监控、故障排查、归档清理。每个阶段都有自己最常用的几组命令。比如打包上传阶段最少不了的是tar、scp、rsync解压部署阶段用到tar -zxvf、ln -s、chmod启动服务阶段需要nohup、sh、ps运行观察阶段靠top、df、ss日志监控阶段是tail、grep、awk的主场故障排查阶段要调出jstack、jmap、curl最后的归档清理则交给find、du、rm来处理。你不需要一次性掌握所有命令只需要在对应阶段反复使用自然就会形成肌肉记忆。下面几个章节我就按照这条生命周期线把最值得Java程序员学习的命令逐一拆开来说。2. 进程排查组合拳定位Java故障的第一反应线上Java服务出问题通常两类表现最明显CPU飙高、内存异常。遇到这类问题很多人的第一反应是去看监控面板看图表然后猜测哪个接口出了问题。但监控只能告诉你“坏了”不能告诉你“哪一行代码坏了”。真正要把问题钉死靠的是进程排查这套组合拳。2.1 先看进程再看线程ps与top的正确用法一般我们先用ps -ef | grep java确认Java进程是否还在以及启动参数是什么。注意命令里的grep java有可能会把这条grep命令本身也匹配出来所以很多有经验的人会写ps -ef | grep java | grep -v grep或者直接用pgrep -f java。这一步不是炫技是为了避免你看错PID后续所有操作全偏。服务还在但CPU不对劲就要用top看整体负载。top默认按CPU使用率排序你能在一堆进程里一眼看到哪个进程最吃CPU。但光看到PID还不够Java是一个多线程进程一个PID下面挂着几十上百个线程你得进一步看是哪个线程在狂转CPU。此时用top -Hp PID。-H表示线程模式-p指定进程PID这样屏幕上显示的是这个进程内部的每个线程的CPU占用。记下CPU占用最高的线程PID比如是17342然后用printf %x\n 17342把它转成十六进制得到43be之类的结果。为什么要转十六进制因为jstack输出的线程ID都是十六进制形式比如nid0x43be你拿十进制的线程号去对怎么都对不上。这个小细节卡住了不少新手。注意top -Hp只能看当前线程的瞬时CPU占用如果要连续观察几次建议加-n 1 -b做批处理采集或者用top -H -p PID -n 2 -d 1多刷几帧。2.2 jstack与jmap联动把堆栈和堆状态钉死拿到十六进制线程号0x43be之后执行jstack PID | grep -A 30 nid0x43be就能看到这个线程当前在执行什么代码。如果某个线程的堆栈停在你的业务代码里并且CPU占用一直很高大概率是死循环或长时间阻塞。我曾经在一个对外接口上遇到过类似情况一个while循环里没有break条件数据量一旦变大就直接把CPU顶满。用这套命令五分钟定位到具体行号比翻半天代码快得多。内存问题则是另一套玩法。先用jmap -heap PID看一眼新生代、老年代的使用情况判断是堆不够还是可能存在内存泄漏。如果要进一步分析可以导出堆转储文件jmap -dump:formatb,file/tmp/heap.hprof PID。导出的.hprof文件可以用分析工具打开看哪些对象占用了大量内存。但这里要提醒一句jmap -dump会暂停应用一小段时间堆越大暂停越明显在高峰期执行这一操作要谨慎最好先低峰演练一次。还有两个和进程退出相关的命令值得说明。kill -3 PID会向Java进程发送SIGQUIT信号JVM收到后会主动打出一份线程转储到标准输出经常用来在服务“卡死”时获取现场。kill -9 PID是强制终止除非已经无法优雅停机否则尽量别用因为Spring Boot应用有优雅停机机制kill -15默认的kill就是15能让应用有机会做收尾处理。命令本身没有好坏但用错时机就会造成数据不一致或者文件没刷新。最后给个简单的命令对照表方便你快速回忆命令主要作用Java场景ps -ef | grep java查看Java进程及启动参数确认PID、是否启动top -Hp PID查看进程内线程CPU占用定位高CPU线程jstack PID打印线程堆栈定位死循环、锁等待jmap -heap PID查看堆内存使用判断内存异常jmap -dump:formatb,filexx.hprof PID导出堆转储文件离线分析内存泄漏kill -3 / kill -15 / kill -9发信号给进程优雅停机或强制终止3. 日志文件里找线索文本处理命令的实战套路Java应用跑起来之后日志是唯一能够完整记录“内部发生了什么”的线索。但现实中的日志文件动不动就几百MB甚至几个G用编辑器打开等于自杀这时候必须借力命令行文本处理工具。这一章节我重点讲几个高频组合帮你从日志里快速找到有价值的信息。3.1 tail与grep配合别再用编辑器打开几百MB日志我见过一些同学排查问题第一件事就是vim app.log然后发现文件太大打开很慢或者打开之后半天找不到想要的内容。正确做法是先明确目标再用命令精准锁定。tail -f app.log是实时跟踪日志适合在测试环境观察启动过程或请求日志。tail -n 200 app.log只看最后200行适合看崩溃前后发生了什么。配合grep就更强了比如grep -n ERROR app.log会把所有包含ERROR的行打印出来并带上行号grep -C 5 NullPointerException会打印匹配行前后各5行帮你看到异常发生时的上下文grep -E ERROR|WARN用正则同时匹配多个关键词。最常用的实时筛选组合是tail -f app.log | grep --line-buffered Exception。这里有个细节管道默认是有缓冲的不加--line-bufferedgrep可能会攒一批输出才显示实时性就很差。加上之后日志一行出现就立刻过滤出来。这条命令在我排查线上问题时几乎每天都用。3.2 awk/sed/sort/uniq从日志里统计出规律只看单条日志还不够很多时候需要统计规律。举个例子某天线上接口突然变慢日志里每一行都有耗时字段我想知道平均耗时是多少哪些请求最慢。假设日志格式类似2025-06-01 10:00:00.123 INFO [http-nio-8080-exec-1] com.example.order.OrderService - query order cost: 234ms想提取耗时数字可以用sed把前缀剥掉只保留耗时再用awk求和并算平均值。比如grep query order cost app.log | sed s/.*cost: \([0-9]*\)ms/\1/ | awk {sum$1; count} END {print avg:, sum/count, ms, total:, count}这里sed用了后向引用把cost: 234ms里的234提取出来awk负责累加和计数。很多第一次看到这条命令的同学会觉得眼花其实拆开看就是“先用正则抓取目标列再做聚合统计”和你在Excel里先抽取一列再求和是同一个道理。再看另一个高频场景统计日志里出现次数最多的异常类型。先利用日志中固定的字段位置用awk切列比如级别在最前面类名在中间异常类型在末尾。假设格式统一就可以用grep ERROR app.log | awk {print $7} | sort | uniq -c | sort -rn | head -20awk {print $7}按空格拆分取出第7列sort排序让相同的值相邻uniq -c计数再sort -rn按次数降序最后head -20只看前20。这一串管道拼起来就是一个最小的日志统计任务。刚开始可能会被管道绕晕你只要记住每个命令都是一个处理节点前一个命令的输出就是后一个命令的输入多看几次就顺了。提示日志格式如果不固定不要盲目用列号切分尤其接口输出里可能夹杂着空格。这种情况下建议先用grep缩小范围再用sed精确提取最后再聚合。4. 部署与归档文件系统里的Java生存法则Java程序跟文件系统打交道的地方很多从部署目录的结构设计到日志归档、配置文件版本切换每一步都绕不开文件、磁盘、链接相关命令。这一章讲的是把一个Spring Boot应用“收拾”得井井有条的日常操作。4.1 磁盘和目录管理find/du/df的使用时机先说排查磁盘满了的经典流程。当服务突然写不进去日志时第一反应是df -h看/、/home、/var这些挂载点是否已满。磁盘满之后应用可能还能跑但日志、临时文件都没法写表现非常诡异。确认磁盘占用高后用du -sh /opt/app/*或du -sh *一层层往下找大目录。注意du默认会列出子目录大小如果目录特别多可以加--max-depth1避免输出爆炸。找到日志目录后就能用find做精确清理比如删除一周前的.log文件find /opt/app/logs -name *.log -mtime 7 -delete这条命令要谨慎建议先用find /opt/app/logs -name *.log -mtime 7看一眼匹配到了哪些文件再补上-delete免得把正在使用的日志误删了。find的表面作用是“找文件”实际上它最强大的能力是“按条件批量操作”比如按时间、大小、类型筛选后执行删除或打包。Java程序员经常需要找某个jar或class文件用find / -name *.jar 2/dev/null配合错误输出重定向是个很好用的招。4.2 tar与ln打包部署和软链接管理打包发布很少有人直接cp一堆文件一般都会打成tar.gz再传输。解压命令是tar -zxvf app-1.4.0.tar.gz -C /opt/app/-C指定解压到目标目录避免把文件散落到当前目录。反过来备份整个应用目录用tar -czvf backup.tar.gz /opt/app/把目录归档成一个文件。这里我想强调一个习惯部署版本目录 软链接指向当前版本。比如每个版本目录叫/opt/app/releases/app-1.4.0同时建一个软链接/opt/app/current指向当前运行的版本ln -s /opt/app/releases/app-1.4.0 /opt/app/current启动脚本固定写/opt/app/current/bin/start.sh要升级时解压新版本目录替换软链接指向一条命令就能切换版本。回滚也很快把软链接指回上一个目录即可。这个方案我用了很久比每次覆盖同一个目录安全得多至少不会出现“配置被新包覆盖了还得翻历史文件”的情况。顺便提一句ln -s的坑如果你已经建了一个软链接再执行ln -s /path /link可能会报“file exists”需要先rm旧链接或者直接用ln -snf /path /link强制覆盖。软链接在Java应用里的另一个常见用途是把日志目录放到磁盘大的挂载点避免日志把系统盘塞满。5. 端口、连接与调试网络类命令的Java视角网络问题对Java程序员来说比纯代码问题更头疼因为一涉及网络本地能跑、线上连不上、别人能访问你不能访问各种诡异情况都冒出来了。网络类的Linux命令不算多但每个都能派上大用场。5.1 服务起不来先看端口和监听状态Spring Boot应用默认监听8080端口最常见的问题是端口被占用。启动日志会报“Port already in use”这时候不要瞎猜执行ss -lntp | grep 8080ss是现在Linux系统推荐使用的套接字查看命令比传统的netstat更快而且很多新操作系统默认不再安装net-tools。-l只看监听端口-n不解析域名-t只显示TCP-p显示进程信息。输出里能看到占用8080的PID和进程名直接定位到是谁抢了你的端口。如果你想查某个进程到底监听了哪些端口可以用lsof -p PID或者lsof -i :8080。lsof不是所有系统都自带需要先安装但在排查“文件被谁占用”“端口被谁占用”时特别好用。注意ss和lsof结果中的进程信息可能需要对应权限才能看到非root用户有时候只能看到端口状态看不到进程名这时候加sudo。5.2 接口通不通curl、telnet与TCP状态测HTTP接口最方便的就是curl。本地起了个服务先在本机探一下curl -v http://localhost:8080/health加了-v可以看到完整的请求和响应头如果服务没起来连接被拒绝的表现和响应超时的表现完全不同这本身就是一条非常重要的区分线索。需要发POST请求时curl -X POST -H Content-Type: application/json -d {id: 123} http://localhost:8080/api/order如果服务之间互相访问不通curl帮不了你判断中间网络有没有丢包这时候用ping做基础的连通性检查用telnet IP 端口测试TCP端口是否可达。有些最小化系统没装telnet可以用bash自带的方式timeout 3 bash -c cat /dev/null /dev/tcp/10.0.0.5/3306 echo open || echo closed这个利用的是bash的虚拟设备/dev/tcp同样能测端口通不通。再说一个容易忽略的细节明明服务监听了端口但外部访问不到有可能是防火墙规则拦截。先查本机防火墙是否放行再确认云安全组这个排查顺序能省很多时间。网络命令不需要学很多掌握“端口有没有监听、端口通不通、连接建立到哪一步”这几个维度就已经能覆盖绝大多数Java应用的网络排查场景。如果真到了需要看报文内容的地步再去碰tcpdump但那是后话不是普通开发每天的标配。6. 把重复劳动交给脚本Shell与定时任务命令一个个敲着玩没问题但同一个动作如果每周都要做一次那就不如写个脚本固化下来。Java程序员经常要做的事情无非是重启服务、清理日志、写一个简单的监控告警。这几个场景用Shell脚本加crontab就能撑起来。6.1 一个通用的服务重启脚本长什么样手工重启Java服务的基本流程是找到PID、杀进程、等几秒、检查进程是否退出、启动新进程、确认端口监听。每一步都有坑漏一步就可能留一个僵尸进程或者没等端口起来就误判成功。我习惯把这一套写成脚本#!/bin/bash APP_HOME/opt/app/current APP_NAMEapp-1.4.0.jar LOG_FILE/opt/app/logs/start.log # 找到旧进程 PID$(pgrep -f $APP_NAME) if [ -n $PID ]; then echo stop old process: $PID kill $PID # 等待进程退出最多等30秒 for i in $(seq 1 30); do if kill -0 $PID 2/dev/null; then sleep 1 else break fi done fi # 启动新进程 nohup java -Xms512m -Xmx512m -jar $APP_HOME/$APP_NAME $LOG_FILE 21 echo new pid: $!这个脚本里有几个关键点。第一pgrep -f通过完整命令行匹配进程比pgrep java更能精确定位到特定应用避免同一个服务器上多个Java进程互相误杀。第二kill -0不是真的发信号而是检测进程是否存在循环里用它可以优雅等待旧进程退出。第三启动后立刻打印$!这是后台进程的PID方便你后续确认。第四nohup配合让Java进程脱离当前Shell独立运行即使断开SSH也不会被终止。脚本执行前记得chmod x restart.sh否则还得bash restart.sh。这个小细节经常被忽视权限不对脚本永远执行不了。6.2 crontab的典型用法日志清理与定时告警服务跑起来之后日志每天都在增长磁盘终究会报警。与其等到磁盘满不如直接挂一个定时任务定期清理。用crontab -e编辑当前用户的任务表添加一行0 2 * * * find /opt/app/logs -name *.log -mtime 7 -delete /tmp/log-clean.log 21含义是每天凌晨2点删除/opt/app/logs下7天前的.log文件。前面五个字段依次是分、时、日、月、周0 2 * * *就是每天2点整。把标准输出和错误输出重定向到日志文件里下次想确认有没有执行成功直接看那个文件。除了清理日志还可以用crontab配合Shell做最简单的资源监控。比如想每5分钟检查一下某个Java进程CPU占用是否超过阈值#!/bin/bash JAVA_PID$(pgrep -f app-1.4.0.jar) CPU$(top -b -n 1 -p $JAVA_PID | tail -1 | awk {print $9}) if [ $(echo $CPU 90 | bc) -eq 1 ]; then echo $(date) CPU high: $CPU% /opt/app/logs/cpu-alarm.log fi这里会用到bc做浮点数比较因为top输出的CPU占用可能是小数。这类脚本不必写得很复杂关键是让系统自动发现问题而不是等你人工发现磁盘满了再去救火。关于crontab还有个大坑定时任务执行时的环境变量和交互式Shell不一样你手动敲java -version没问题但cron里可能找不到java命令。解决办法是在脚本开头显式导出环境变量比如export JAVA_HOME/opt/jdkexport PATH$JAVA_HOME/bin:$PATH或者直接写命令的绝对路径。不要以为什么命令都能在cron里拿到这是新手最容易栽跟头的地方。再分享一个我自己的习惯每学一条命令我都会用man或--help过一遍参数然后在本子上记一个“什么时候用它”的场景标题而不是抄一堆命令解释。几个月下来真正记住的不是命令本身而是那条从报错到定位的排查路径。对Java程序员来说我们的内存本来就塞满了语言、框架、中间件的细节能用一条管道把排查动作串起来比背二十个孤立命令有价值得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑