在Linux上作为服务运行Java应用程序
我已经编写了一个Java服务器应用程序,它运行在一个标准的虚拟托管Linux解决方案上。应用程序一直在运行,监听套接字连接并为其创建新的处理程序。它是客户机-服务器应用程序的服务器端实现 我启动它的方式是将它包含在服务器的startup rc.local脚本中。但是,一旦启动,我不知道如何访问它来停止它,如果我想安装更新,所以我必须重新启动服务器才能重新启动应用程序 在windows PC上,对于这种类型的应用程序,我可以创建一个windows服务,然后根据需要停止和启动它。Linux机器上是否有类似的东西,这样如果我启动这个应用程序,我就可以停止并重新启动它,而无需完全重新启动服务器 我的应用程序名为WebServer.exe。它是在服务器启动时通过将其包含在my rc.local中启动的,如下所示:在Linux上作为服务运行Java应用程序,java,linux,service,Java,Linux,Service,我已经编写了一个Java服务器应用程序,它运行在一个标准的虚拟托管Linux解决方案上。应用程序一直在运行,监听套接字连接并为其创建新的处理程序。它是客户机-服务器应用程序的服务器端实现 我启动它的方式是将它包含在服务器的startup rc.local脚本中。但是,一旦启动,我不知道如何访问它来停止它,如果我想安装更新,所以我必须重新启动服务器才能重新启动应用程序 在windows PC上,对于这种类型的应用程序,我可以创建一个windows服务,然后根据需要停止和启动它。Linux机器上是否
我在Linux上有点不修边幅,所以任何文章中的例子都会受到欢迎。但是,我有SSH和完全的FTP访问权,可以安装任何更新,也可以访问Plesk面板。另一种选择,也是非常流行的是。这在OSS社区中也非常流行 然而,一旦开始,我不知道如何访问它来阻止它 您可以编写一个简单的停止脚本,用于greps您的java进程、提取PID并对其调用kill。这不是幻想,而是直截了当的。 这样的事情可能会有帮助:
#!/bin/bash
PID = ps ax | grep "name of your app" | cut -d ' ' -f 1
kill $PID
Linux服务初始化脚本存储在
/etc/init.d
中。您可以复制和自定义/etc/init.d/skeleton
文件,然后调用
service [yourservice] start|stop|restart
看。它适用于Debian(也适用于Ubuntu),但更适合发行版。一个简单的解决方案是创建一个脚本start.sh,通过nohup运行Java,然后将PID存储到一个文件中:
nohup java -jar myapplication.jar > log.txt 2> errors.txt < /dev/null &
PID=$!
echo $PID > pid.txt
当然,我省略了一些细节,比如检查进程是否存在,如果完成了,则删除
pid.txt
。您可以使用Java服务或与Java服务通信。我在这里编写了另一个简单的包装:
#!/bin/sh
SERVICE_NAME=MyService
PATH_TO_JAR=/usr/local/MyProject/MyJar.jar
PID_PATH_NAME=/tmp/MyService-pid
case $1 in
start)
echo "Starting $SERVICE_NAME ..."
if [ ! -f $PID_PATH_NAME ]; then
nohup java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
echo $! > $PID_PATH_NAME
echo "$SERVICE_NAME started ..."
else
echo "$SERVICE_NAME is already running ..."
fi
;;
stop)
if [ -f $PID_PATH_NAME ]; then
PID=$(cat $PID_PATH_NAME);
echo "$SERVICE_NAME stoping ..."
kill $PID;
echo "$SERVICE_NAME stopped ..."
rm $PID_PATH_NAME
else
echo "$SERVICE_NAME is not running ..."
fi
;;
restart)
if [ -f $PID_PATH_NAME ]; then
PID=$(cat $PID_PATH_NAME);
echo "$SERVICE_NAME stopping ...";
kill $PID;
echo "$SERVICE_NAME stopped ...";
rm $PID_PATH_NAME
echo "$SERVICE_NAME starting ..."
nohup java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
echo $! > $PID_PATH_NAME
echo "$SERVICE_NAME started ..."
else
echo "$SERVICE_NAME is not running ..."
fi
;;
esac
您可以阅读init.d和systemd(ubuntu 16+)的完整教程
如果需要输出日志,请更换2
nohup java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
排队等候
nohup java -jar $PATH_TO_JAR >> myService.out 2>&1&
从中,我可以推荐基于Python的
supervisord
应用程序。有关更多信息,请参阅堆栈溢出问题。它的设置非常简单。可能不是最好的开发运营解决方案,但适合于局域网或类似组织的服务器的一般使用
使用screen
在中运行服务器,然后在注销前分离,这将保持进程运行,然后您可以随时重新连接
工作流:
启动屏幕:屏幕
启动您的服务器:java-jar minecraft server.jar
按分离:Ctl-a
,d
重新连接:屏幕-r
这里有更多信息:也指的是,我会选择
systemd
版本,因为它是最简单、最不冗长、最适合集成到现代发行版(甚至是CentOS 7.x等不太现代的发行版)中的版本。最简单的方法是使用supervisords
。详情请参阅:
更多信息:
其他答案可以根据您的平台提供自定义脚本和设置。除此之外,以下是我所知道的成熟的特殊用途项目:
- 来自TanukiSoftware的JSW
- 是上面的开源克隆。它是用Java编写的,是一个保姆进程,根据配置管理子进程(您的代码)。适用于windows/linux
- 是本机应用程序。它也是一个保姆流程,但它通过JNI调用您的子应用程序,而不是作为子流程
- 这是一个示例shell脚本(请确保用应用程序的名称替换数学名称):
要将Java代码作为守护进程(服务)运行,您可以编写基于JNI的存根 对于基于JNI的示例代码。在本例中,您将作为Java启动的代码守护,主循环用C执行。但也可以将主、守护程序的服务循环放在Java中 享受JNI带来的乐趣 来自 作为init.d服务安装(SystemV) 只需将jar符号链接到
init.d
,即可支持标准的启动
、停止
、重启
和状态
命令。
假设您在/var/myapp中安装了Spring引导应用程序,要将Spring引导应用程序作为init.d服务安装,只需创建一个符号链接:
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
安装后,您可以按常规方式启动和停止服务。例如,在基于Debian的系统上:
$ service myapp start
如果应用程序无法启动,请检查写入/var/log/的日志文件,以了解如何保护已部署的服务
按照所写的方式执行后,我发现我的服务无法启动,日志中有以下错误消息:。我通过创建一个包含以下内容的配置文件/var/myapp/myapp.conf
来修复它
USE_START_STOP_DAEMON=false
可以将war作为Linux服务运行,您可能希望在打包之前强制输入pom.xml文件,因为某些发行版可能无法在自动模式下识别。为此,在SpringBootMaven插件中添加以下属性
<embeddedLaunchScriptProperties>
<mode>service</mode>
</embeddedLaunchScriptProperties>
你就能跑了
service myapp start|stop|restart
您还可以在中找到许多其他选项,包括Windows服务。我有Netty java应用程序,我想将其作为systemd的服务运行。不幸的是,无论我使用的是哪种类型,应用程序都会停止。最后,我在屏幕中包装了java start。以下是配置文件:
服务
[Unit]
Description=Netty service
After=network.target
[Service]
User=user
Type=forking
WorkingDirectory=/home/user/app
ExecStart=/home/user/app/start.sh
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
开始
#/垃圾箱/垃圾箱
/usr/bin/screen-L-dmS netty_app java-cp app.jar类路径
从
<embeddedLaunchScriptProperties>
<mode>service</mode>
</embeddedLaunchScriptProperties>
ln -s myapp.war /etc/init.d/myapp
service myapp start|stop|restart
[Unit]
Description=Netty service
After=network.target
[Service]
User=user
Type=forking
WorkingDirectory=/home/user/app
ExecStart=/home/user/app/start.sh
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target