使用jsvc启动java进程

使用jsvc启动java进程

apache commons daemon,apache的一个子项目。
它的说明文档很简单,它的实际用法也是。

推荐直接去官网查看它的文档。
项目地址为:
https://commons.apache.org/proper/commons-daemon/index.html

一、启动、关闭java进程时遇到的一些需求

在启动或是关闭java进程时,有时会对这些操作和进程运行状态信息提出一些要求。

1. 在查看java进程信息时,希望能隐藏部分classpath。

如果引用的jar文件比较多,那么进程信息中显示的classpath就很长,这个对查看进程信息就很不友好,尤其是在一次要查看多个java进程的情况下。

2. 有时希望能以类似同步阻塞调用的方式来启动和关闭java进程。

只有进程在完全初始化或退出后,执行调用的脚本或命令才返回。

二、相关概念

commons-daemon可以看成是一个独立的jar文件,需要引入到项目的classpath中来配合使用。
jsvc是一个可以在类Unix上运行的可执行文件。

实际使用时,需要联合commons-daemon和jsvc一起使用。
通过它们,可以使在类Unix系统上运行java进程更加容易。

比如下面的命令,使用jsvc来启动一个java进程。

jsvc -user xxx -cwd xxx -procname xxx -pidfile xxx -cp xxx ... JVM_OPTS APP_MAIN_CLASS

可以看出它和普通的java命令类似,但是多了一些前面的参数配置。

三、初识jsvc

大约在2013年或更早的时候,项目使用jsvc来启动java进程。
当初不知道是谁率先引入的jsvc,也不知道他引入jsvc是为了解决什么样的问题,反正这种方式就这么被传承下来了。

但从那时起,使用jsvc的体验就不太好。
因为每次启动时会产生两个进程,每个进程的信息中都包含了大量的classpath信息。
而且没有用到jsvc的其它功能,因此也就没有感觉到使用jsvc带来的优势。

新人可能会对这两个进程产生疑惑,到底哪个是真正的java进程。
而且每次使用ps查看进程时,会发现进程信息占据了大部分的屏幕空间。

比如下面的这个截图。
虽然只查看了某一个具体的网关进程信息,但是大部分屏幕空间都被这些信息占据了,更不用说当要同时查找多个不同功能的进程时所造成的困扰。
没有隐藏classpath
如果是使用jsvc方式启动的java进程,在使用jps -l时,是看不到启动类的fqn或jar的完整路径的。

四、jsvc基本使用

先说明一下,本人使用的类Unix系统都是Linux,比如CentOS、Ubuntu,没有实际使用过Unix系统。

1. 在Linux上安装jsvc命令。

jsvc命令需要通过手动编译源码来构建,官网没有提供现成的下载文件来直接使用。

然而jsvc的构建过程超级简单。

  1. 下载commons-daemon-1.2.2-src.tar.gz,解压后进入src/native/unix。
  2. 运行如下命令(文档页上也有这些步骤):
./configure --with-java=dir         #设置属性
make                                #生成jsvc命令
sudo cp jsvc /usr/bin/              #将jsvc拷贝到某个path目录下

2. 在项目中引入commons-daemon。

  1. 在项目中引入jar。
  2. 启动类实现Daemon接口;或是启动类不实现Daemon接口,但是拥有Daemon接口指定的4个方法。

3. 编写相应的使用脚本

最终使用如下方式调用jsvc命令。
APP_MAIN_CLASS就是实现了Daemon接口的类,或是有Daemon接口的4个方法的类。

启动java进程:
jsvc -cwd xxx -user xxx -procname -xxx -pidfile xxx … -cp JVM_OPTS APP_MAIN_CLASS

关闭java进程:
jsvc -stop -pidfile xxx APP_MAIN_CLASS

五、jsvc进阶

这么多年来,一直没有理解为什么会选择使用jsvc来启动java进程。
目前所在的项目组,也是使用了jsvc,然而也没有用好它,文章中的截图就是来自于这个项目组的一个进程 - 网关。
他们虽然引入了jsvc,但是没有使用到jsvc提供的一些好用的功能,反而造成了一些困扰。

后来自己在寻求简化classpath信息的过程中,偶然使用-debug选项输出了很多调试信息。
根据这些信息猜测,jsvc应该是提供了某些核心功能。
于是去官网看了一下它的文档和api,写一些测试代码试了一下,发现了一些从未有使用过的功能。

1. 隐藏classpath信息。

使用jsvc命令启动java进程后,会产生两个进程,如果java项目本身引入的jar文件比较多,这些进程信息就会比较长。

如果使用nohupjava &这两种方式启动java进程,很多人都会选择在打包阶段将引入jar的classpath信息放到META-INF/MANIFEST.MF文件中,这样就可以隐藏这些classpath。

见过好几个项目使用jsvc(包括现在的),但是它们都没有能解决这个问题。
其实在使用jsvc这种方式中,也可以隐藏掉这些classpath,也是将classpath写到META-INF/MANIFEST.MF文件中。

这是隐藏classpath后的进程信息。
隐藏classpath后的进程信息

2. 只有在java应用初始化完成后,执行启动操作的脚本或命令才返回(类似于同步阻塞调用方式)。

这种需求也是很常见的,比如脚本在成功启动java进程后,再做一些其它操作,这两个动作是有先后依赖关系的。
之前就尝试在java代码中实现这样的功能,但是没有成功。

如果单纯的使用nohupjava &这两种方式,就不能实现这样的效果。

jsvc可以通过-wait选项来满足这个需求。
如果不使用-wait选项,jsvc命令会立即返回(类似异步调用),也就没法知道java进程是否会初始化成功。
如果使用-wait选项,当start方法耗时超过wait指定的耗时后,jsvc命令才会返回。

3. 只有在java进程退出后,执行关闭操作的脚本或命令才返回。

jsvc默认就使用了这种方式。
比如要重启进程,得先确认进程被关闭后,再启动进程。

如果使用nohupjava &这两种方式,也是没法直接做到这一点的。
这时大家结束进程的方式有几种:发送SIGTERM(kill -15)信号给进程,或是在代码中预埋触发System.exit(0)的逻辑。
但这些操作都是类似于异步操作,因此只能在脚本中循环检查进程状态,来判断进程是否结束。

4. 捕获自定义信号。

有些人使用捕获信号(比如-15、-12)的方式来做一些特定操作。
jsvc默认屏蔽了-12的信号,给它发送-12的信号是没有任何作用的。
如果给一个普通的java进程发送-12信号,如果它没有捕获这个信号的逻辑,这个进程是会crash的。

jsvc支持捕获-12的信号

5. 进程在crash后会自动重新启动。

比如不小心使用kill -9终止java进程后,守护进程会自动重启java进程。
这个是之前同事告诉我的。

会输出如下信息:
Service killed by signal 9
Waiting 60 s to prevent looping

之前遇到过这种情况:
在内存不足时,java进程会启动失败,但是jsvc的后台进程会不断的去重启java进程进行重试。

6. perform some privileged operations as root

Jsvc is a daemon process so it should be started as root and the -user parameter allows to downgrade to an unprivilegded user.

Daemon的init方法可以执行一些特权操作。
Daemon.init(DaemonContext context) throws DaemonInitException, Exception

摘选自init方法的部分说明
Under certain operating systems (typically Unix based operating systems) and if the native invocation framework is configured to do so, this method might be called with super-user privileges.

For example, it might be wise to create ServerSocket instances within the scope of this method, and perform all operations requiring super-user privileges in the underlying operating system.

这种方式没有使用过,之前都是以某个普通账号来启动进程。
但是把启动阶段分成init和start,这种对于设计会带来一些思考。
并且被启动的两个进程的所属用户可以是两个不同的用户(比如root和user),这样在查找、管理进程时是否会带来优势?

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值