把本地jar包部署到linux服务器,核心操作就是三步:上传jar包、配置Java环境、用命令启动并保持后台运行。这个过程本身不复杂,但很多新手会在权限、端口、日志这些细节上翻车,下面按实际部署顺序,把每一步该做什么、用什么命令、踩坑点在哪,一次性讲清楚。
部署前先确认这三件事
动手之前别急着敲命令,先花两分钟确认环境,能省掉后面一大半麻烦。
- 服务器有Java环境吗:用
java -version查一下,没有就装,CentOS用yum install java-1.8.0-openjdk,Ubuntu用apt install openjdk-8-jdk,版本别搞错,jar包编译用的Java 8,服务器也得是Java 8,版本不一致会直接报UnsupportedClassVersionError。 - 端口被占了吗:你的jar包要监听哪个端口,先确认这个端口是空的,用
netstat -tlnp | grep 8080查,有输出说明被占了,要么换端口,要么把占用进程停掉。 - 服务器配置够用吗:jar包启动后内存占用多少,取决于你
-Xmx参数怎么设,如果服务器只有2G内存,你非给JVM分1.5G,那系统光跑个Tomcat都费劲,先看下free -h,心里有个底。
区域选择和部署方式怎么定
很多朋友会纠结一个问题:jar包部署到国内服务器还是海外服务器?这直接影响上传速度和访问延迟。
- 国内服务器:访问快,但域名要备案,上传jar包用scp命令一般能跑满带宽。
- 海外服务器:免备案,但跨洋传输速度看运气,有时候传一个100MB的jar包得等半天。
行业共识认为,只要你的用户主要在国内,老老实实用国内云厂商的服务器就好,至于价格,入门级2核4G的云服务器,主流厂商一年几百块钱,跑单个jar包完全够用。
文件传输:jar包怎么弄到服务器上
本地jar包传到服务器,主流有三种方式,按使用场景选。
scp命令直接传
这是最省事的方式,适合一次性部署。
scp /本地路径/app.jar root@服务器IP:/opt/app/
回车后输入密码,等进度条走完就行,文件多了或者想传整个目录,加个-r参数。
借助SFTP工具
如果你习惯图形界面,用FileZilla、WinSCP这类工具也行,左边本地目录,右边服务器目录,直接拖拽上传,好处是能断点续传,网络不稳的时候比scp靠谱。
先压缩再传
一个jar包动辄几十上百MB,传之前先tar -czvf app.tar.gz app.jar压缩一下,体积能小不少,传输时间缩短,传到服务器后再解压,注意解压完要检查一下文件完整性,md5sum对比一下本地和服务器的校验值,防止传输损坏。
部署jar包到linux服务器的详细步骤
目录规划
别把jar包随便丢在root目录或者/tmp下面,乱放后面自己都找不到,建议建一个规范点的目录结构:
/opt/app/ ├── bin/ # 存放启动脚本 ├── logs/ # 日志输出目录 ├── conf/ # 配置文件 └── lib/ # 依赖jar包
把你打包好的jar放到/opt/app/bin/下面,后续日志统一输出到/opt/app/logs/。
启动命令
前台启动和后台运行是两码事,直接java -jar app.jar的话,命令行一关服务就死了,正确的启动姿势见下面的后台运行部分,这里先说参数配置。
一个完整的启动命令长这样:
java -server -Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=prod -jar /opt/app/bin/app.jar --server.port=8080
逐段拆解一下:
-Xms512m -Xmx1024m:堆内存最小值和最大值,生产环境这两个值通常设成一样,避免运行时动态扩容导致性能抖动。-Dspring.profiles.active=prod:指定激活的配置文件,你的Spring Boot项目里如果有多套环境配置,用这个参数切换。--server.port=8080:临时指定端口,优先级高于配置文件。
把日志存下来
前端启动的话,日志直接刷在屏幕上,关了就没了,正确做法是把标准输出和错误输出都重定向到文件:
nohup java -jar /opt/app/bin/app.jar > /opt/app/logs/app.log 2>&1 &
nohup保证进程不受终端关闭影响,> /opt/app/logs/app.log把输出写入指定文件,2>&1把错误信息也合并到同一个日志文件,最后的&表示后台运行。
jar包后台运行用什么方式更靠谱
这是部署jar包时最常被问到的问题之一:nohup和systemd到底选哪个。
| 对比项 | nohup | systemd |
|---|---|---|
| 上手难度 | 一行命令搞定 | 需要写unit文件 |
| 开机自启 | 不支持 | 完美支持 |
| 崩溃自动重启 | 不支持 | 支持 |
| 日志管理 | 手动重定向 | journalctl统一管理 |
如果你只是临时部署,比如测试环境验证个功能,nohup完全够用,简单直接。
如果是生产环境,强烈建议用systemd管理,开机自启和崩溃恢复这两个能力,生产环境一定用得上,创建一个服务文件:
vim /etc/systemd/system/app.service
写入:
[Unit] Description=My Java App After=network.target [Service] Type=simple User=root ExecStart=/usr/bin/java -Xms512m -Xmx1024m -jar /opt/app/bin/app.jar SuccessExitStatus=143 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
然后依次执行:
systemctl daemon-reload systemctl enable app.service systemctl start app.service
之后管理服务只需要:
systemctl status app.service # 查看状态 systemctl restart app.service # 重启 journalctl -u app.service -f # 实时看日志
比nohup好用多了。
启动失败怎么排查
jar包部署到linux服务器上,最容易出问题的地方就那么几个,按照下面这个顺序排查,多数情况下几分钟能定位到问题。
先看进程和端口
ps -ef | grep java # 进程在不在 netstat -tlnp | grep 8080 # 端口有没有监听
进程不在,说明启动就失败了,去看日志,进程在但端口没监听,说明应用启动到一半挂了或者端口配置错了。
再看日志报什么错
用tail -100f /opt/app/logs/app.log看日志尾部,常见报错就那几类:
Port already in use:端口被占,换个端口或者杀掉占用进程。Caused by: java.lang.ClassNotFoundException:缺依赖,打包的时候没把依赖打进去,检查pom.xml或build.gradle。OutOfMemoryError:内存不够,调大-Xmx,或者检查代码有没有内存泄漏。Error creating bean with name:Spring容器初始化失败,配置类扫描不到、数据库连不上,根据后面的具体异常处理。
检查防火墙和云安全组
环境全对、程序也在跑,但外部就是访问不到,大概率是防火墙或者安全组拦截了。
firewall-cmd --list-ports # CentOS 7+查看放行端口
如果端口没放行,加一下:
firewall-cmd --add-port=8080/tcp --permanent firewall-cmd --reload
云服务器的话,登录控制台,去安全组规则里确认入方向放通了8080端口。
数据库连接问题
如果jar包启动后一连串报错都是连接数据库超时,先确认服务器能访问到数据库地址。telnet 数据库IP 3306通不通,不通就是网络问题或者数据库白名单没把服务器IP加进去。
常见问题解答
jar包在本地能跑,到服务器上就报错怎么回事
本地和服务器环境有差异,最常见的两个因素:JDK版本不一致、配置文件中硬编码了本地路径或地址,逐一验证,把JAVA_HOME指向的JDK版本统一,配置项改用环境变量注入。
部署jar包应该用jdk还是jre
如果只是运行普通Spring Boot可执行jar包,jre就够了,但很多依赖库需要jdk的编译工具,强烈建议直接装jdk,省那几十MB磁盘空间,后面遇到奇怪问题排查起来更浪费时间。
服务器重启后jar包自动消失了
确认你的启动方式用了nohup但没配守护进程,用systemd方案就能解决,按上文写个service文件,systemctl enable让服务开机自启,以后服务器重启后服务自动拉起,不用再手动操作。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/793480.html


