How to run .jar continually and automatically on Debian server? - java

I have a .jar file I want to run all the time on a Debian server.
Currently I have figured out how to access the server via ssh on Cygwin and start the .jar. But when I close the Cygwin window on my development machine, it kills the process on the server (I think, as it's not responding any longer).
Currently I start it like this:
java -jar myjar.jar packageName.fileNameOfFileWithMainMethod
I need to make this file run automatically and continually on the server (it is an integral part of the system I am developing).
Unfortunately I know next to nothing about server management, or non-windows operating systems in general (wasn't me who chose or made the server), so I really don't know what to do, nor what to search for (apparently, since my searching gave no usable results).
I have read (and edited because the text was a mess) this question, but although I feel it might be hinting in the right direction, I didn't get much help from it. I also tried my best googlefu, but it got me a lot of only tangentially related results.
I guess I'll have to make some kind of script (possibly containing the code line above), do some stuff to it and put it somewhere specific on the server to accomplish what I want to do.
Would someone be so kind as to explain how this is done?

Shell hooks are good for configuring user environment variables.
Cron is for scheduled jobs, mostly related maintenance, such as creating backups, managing log-files etc ...
Background processes with nohup as advised by Николай Митропольский, or ssh with "screen" application (which let you detach/reattach to a "session"), will be useful in development time.
But can not handle server shutdown cleanups, or respond to restarts.
Init scripts mentioned above is the standard way to start/stop services.
There is an application named init, which is the first application started when a Unix-like system boots.
Init, according to runlevel, starts some scripts, and those scripts manages daemons (services in Windows).
So for services, you write "hooks" for runlevels,
In Debian, /etc/init.d/ where you put your init scripts,
you can read the scripts inside this folder to get the idea,
they are text files (bash scripts).
Those scripts are called with an argument
(a standard keywords, such as "start", "stop" etc..).
/etc/rc?.d/ (where ? is one of runlevels), where the init finds the scripts to run.
But those scripts are just "automatically created" symbolic links to the scripts in /etc/init.d/.
You do not need to touch anything inside /etc/rc?.d/ folder.
*After putting your script into /etc/init.d/,
you only need to call to create symbolic links *:
sudo update-rc.d "your-scripts-name" defaults
As you see there are some prefixes attached to names of scripts;
for example /etc/rc1.d/K10apache2 which is a symbolic link to /etc/init.d/apache2.
So a simple "ordered by name execution" is possible here.
Automatically creating those prefixes (so the execution order),
dependency information is required.
So init scripts includes this information.
Also information required when (at which runlevel) those scripts should be called (with "start" or "stop").
This dependency information is placed as comments in those scripts.
Forexample apache server init script (/etc/init.d/apache2) includes those lines;
# Provides: apache2
# Required-Start: $local_fs $remote_fs $network $syslog $named
# Required-Stop: $local_fs $remote_fs $network $syslog $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
Detailed information exists in Debian policy;
https://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit
also this will be usefull;
https://refspecs.linuxbase.org/LSB_2.1.0/LSB-generic/LSB-generic/iniscrptfunc.html
NOTE:
There is a huge transition and debates/fragmentations in Unix world.
Init and init scripts, tradationally used in Unix/Unix-like systems, nowadays becoming obsolete on many systems.
https://en.wikipedia.org/wiki/Init#Replacements_for_init
Debian currently uses systemd, but init scripts still works with systemd (systemd provides the compatibility).

One simple suggestion would be to run the jar file using Linux's CRON.
This article from unix stack exchange should get you going the correct direction for running a jar file using cron.
Alternatively, this article from mkyong.com is also clear and concise.
For example:
Connect using Cygwin
Run crontab -e
Enter 0 * * * * java -jar myjar.jar packageName.fileNameOfFileWithMainMethod to run the jar file every hour at the top of the hour. Or, to start it once on server startup enter #reboot java -jar myjar.jar packageName.fileNameOfFileWithMainMethod

Simplest solution is to detach process by using nohup with &:
nohup java -jar myjar.jar packageName.fileNameOfFileWithMainMethod &
to stop process will be possible with kill <process-id> command
process id could be found by ps -ef | grep packageName.fileNameOfFileWithMainMethod
But if you are developing serious application that is long-running on server you have to deal with initialization system like systemd, upstart or something like that.

Related

Ansible issue when trying to execute java command from playbook

I'm in the middle of automating some processes in a VM, we are currently using java 17 and have updated out jettys to jetty-11. Since in jetty-11 both home and base are separate it's important to initialize the jetty-base folder. I need to do it from ansible
I worked out a solution in local shell but trying that in ansible it's not working
- name: "Run initialization command"
shell: "nohup java -jar '{{ jetty_home }}'/start.jar jetty.base='{{ jetty_install_dir }}' --add-module=server,http,deploy,annotations,logging-jetty,jsp &"
There are no obvious errors when I run the playbook, just
TASK [jetty-distribution : initialize jetty-base] **************************************************************************************************************************
changed: [****************************] (cutting the vm name off)
Is there any solutions to this issue ? Thanks in advance
You most definately should be using 2 separate directories.
(repeated here for others that see this question in the future)
The jetty.home directory.
This is for the jetty distribution (or the more modern jetty-home tarball/zip).
The jetty.home directory is sacred, don't edit/change/remove/add/modify ANYTHING in this directory. You don't need to, for any possible configuration you can come up with (trust me).
The jetty.base directory.
This is the directory for your configuration, or instance of Jetty.
Make sure this directory does not nest inside/outside of the jetty.home directory, you'll just make your life needless complicated when it's time to upgrade (or even downgrade) your Jetty version.
Next, when it comes to initialization, turn off nuhup, that just hides any errors you might have during initialization. The --add-module command is terminal anyway and will do what it needs and then exit, it's not a daemon and keeps running. If you don't want to see the output, at least redirect it to an output file you can interrogate if there's issues.
Don't put it in the background either (the & at the end), the exit code will be useful to you if an error occurs.
aka
java -jar /path/to/jetty-home/start.jar \
jetty.home=/path/to/jetty-home \
jetty.base=/path/to/my-jetty-base \
--add-module=http,deploy,annotations,logging-jetty,jsp \
2>&1 > /path/to/my-jetty-base/jetty-init.log
Keep in mind that some modules, when added, require user interaction (to accept licenses). This can be handled in scripts by using the --approve-all-licenses option on start.jar.
Lastly, are you sure ansible supports the "Jakarta Big Bang" namespace changes that Jetty 11 implements?
See past answer on this: https://stackoverflow.com/a/66368511/775715
If ansible has updated to Jakarta EE 9, then go ahead and use Jetty 11, if they haven't, then stick with Jetty 10 (which is on Jakarta EE 8) until such time that ansible catches up with the rest of the world.

Jmeter linux shell cannot start server

Situation:
I have installed Jasper Reports Library (V6.5.1) on my local Linux server which generates PDF reports (Data is dumped in a temp Oracle DB table for the reporting engine).
It then serves this PDF back to the website from which I kick off the process.
Goal:
Install Jmeter to analyse performance / possible bottlenecks of "Jasper Reports Library" (aka Report Generation) on my local linux server (I cannot access this server via GUI, only shell).
I understand I have to connect my local Windows 10 machine (running same Jmeter 4.0) with this local server. On the server I have to start Jmeter 4.0 Server (via jmeter-server command) however I get an error and am stuck (have not found anything online or even people with the same goal unfortunately...)
Steps I have taken:
Download latest (4.0) bin from here
Extracted on local linux server in /opt/dlins/apache-jmeter-4.0bin
Trying to start server with /usr/lib/jvm/jdk1.8.0_102/bin/java jmeter-server (the default java version is 6 so through this I can run this app with java 8) - Instructions found here
-> Getting error: "Error: Could not find or load main class jmeter-server"
Any help regarding above or even any other tool you may use are appreciated (Maybe there is a preferable way to test performance for the above scenario)
There are 2 aspects related to your issue and screenshot:
1) Using java 8 instead of 6 - This can be done in several ways, depending on your needs and restrictions, such as the need to have Java 6 globally available for other applications and using 8 just to run JMeter, or just replacing 6 with 8 entirely. For the sake of brevity, I'll assume the first scenario, but there's documentation available for both and Dmitri T has partially explained it already.
Anyway, the same JMeter doc link you used, describes (just scroll down a few times) how to create a setenv.sh script in the bin directory and configure JAVA_HOME or JRE_HOME depending on your needs.
To set those variables permanently, you can place them in a file called setenv.sh in the bin directory. This file will be sourced when running JMeter by calling the jmeter script.
You seem to be wanting a JDK, so create the script and add inside JAVA_HOME=/usr/lib/jvm/jdk1.8.0_102, save and exit.
2) Running JMeter - To clarify a minor confusion, java MyCompiledClass instructs java to load and execute the "program" defined in MyCompiledClass, which is not what you want to do, because jmeter-server is a shell script. If you open it, you'll see that it calls the jmeter shell script which will do some configuration, end eventually call (in short) java -jar ApacheJMeter.jar with some arguments and options.
So, to run JMeter make sure your scripts are executable with chmod, and simply run from command line ./jmeter-server. From the same link:
Un*x script files; should work on most Linux/Unix systems:
jmeter - run JMeter (in GUI mode by default). Defines some JVM settings which may not work for all JVMs.
jmeter-server - start JMeter in server mode (calls jmeter script with appropriate parameters)
jmeter.sh - very basic JMeter script (You may need to adapt JVM options like memory settings).
mirror-server.sh - runs the JMeter Mirror Server in non-GUI mode
shutdown.sh - Run the Shutdown client to stop a non-GUI instance gracefully
stoptest.sh - Run the Shutdown client to stop a non-GUI instance abruptly
Amend your PATH environment variable so Java 8 bin would be before Java 6 bin like:
PATH=/usr/lib/jvm/jdk1.8.0_102/bin:$PATH && export PATH
Once done you should be able to just launch the jmeter-server script like
pushd /opt/dlins/apache-jmeter-4.0bin/bin && ./jmeter-server
More information:
Remote Testing
JMeter Distributed Testing Step-by-step
How to Get Started With JMeter: Part 1 - Installation & Test Plans

using javaw to run jars in batch files results in more than one java processes in process explorer - XYNTService

I have a somewhat strange issue. I have a java application that installs few services that run as Jars. Previously I used installed Java to run these Jars. There are four services and all will be instantiated from a single batch file with sequential call to each other. Something like this,
start %JAVA_HOME% commandtoruntjarfile
would work and all four services will run in the background and only one java.exe visible in process explorer. So I had another service installed as windows service which would start stop these services by calling the run bat or shutdown bat.
Now the customer requirement changed to using an internalized version of java. I extract java to a location, make our own environment variable name "ABC_HOME" and the required syntax in batch changes to
%ABC_HOME%\javaw commandtorunjarfile
When its run it works. but there is no stopping these. When I go to process explorer I see 4 java.exe running each for the four run commands in the batch file. If I stop the windows service all the four keep working. If I restart the windows service the number of java.exe in process explorer goes to eight and keeps going up until windows has had enough of it.
How do I get around it? I think the solution should be to have the one java process in process explorer but I cant seem to find any solution for that.
[EDIT]
The four sub services are actually XYNT processes. In the normal scenario it would be something like this
[Process1]
CommandLine = java -Xrs -DasService=yes -cp jarfiles
WorkingDir = c: bin scache
PauseStart = 1000
PauseEnd = 1000
UserInterface = No
Restart = Yes
For using java from a specific location the following change was needed
CommandLine = %JAVA_PATH%\bin\java.exe -Xrs -DasService=yes -cp jarfiles
but this wouldn't work as it would not accept the path variable in XYNT.ini file. so I called a batch file here and in that batch file I used the above code. So here is what the change looks like,
CommandLine = batchfile.bat
and in batchfile.bat
%JAVA_PATH%\bin\java.exe -Xrs -DasService=yes -cp jarfiles
Usually, every Java program run on your system has its own virtual machine running, which means: one java.exe/javaw.exe per instance of your program.
I can not tell why it "worked" from your point of view with java.exe like you described first, but the behaviour you described for javaw.exe (having 4 java processes in the process explorer) would be what I'd have expected.
For me the question is not why you're seeing 4 vs. 1 java processes, but how you can start/stop the "services". Killing the Java VM externally doesn't seem a very good solution. I'd consider building some IPC into the Java services that allow you to gracefully terminate the processes.

Java running as a Unix service [duplicate]

This question already has answers here:
How to Daemonize a Java Program?
(11 answers)
Closed 7 years ago.
I have built a little daemon in Java and I would like to run it as a service under Unix (e.g. Debian 5). I have read that there is a possibility of using a Java wrapper, but isn't there any other option which is easier to implement? Can't I just use a Unix command such as xxx java -jar program.jar?
Well, if you want to run your java program even when you exit out of your shell, the following is the most simple way:
$nohup java -jar program.jar &
You need to create an appropriate script in /etc/init.d and link it to /etc/rcX.d directories. The script should support at least start, stop, and status parameters. During start it should run java command with appropriate arguments, probably via nohup java <arguments> &. Then you should save PID of your newly-started process to file /var/run/yourservice.pid. stop command should read this PID file and kill this service.
The details vary from distribution to distribution, most distributions provide some macros to make whole job easier. It's best to look at examples of other services in /etc/init.d for your distribution.
Additionally:
If your service isn't accessed from other computers from the network, but it opens some port, make it unavailable with firewall.
If your service processes some 'delicate' data, it's good to add another user and invoke an appropriate sudo command in your /etc/init.d file.
You can start it as:
java -jar program.jar
Unix daemons are normally started by init or started by a script in /etc/init.d or /etc/rc.d, and started at specific runlevels - normally by soft links in /etc/rcX.d. (where X is the intended "runlevel" which is normally 3.
I think debian are moving to using "upstart", a init-replacement. It uses config files in /etc/init to define jobs, and they are quite easy to write. Check that out.
Daemons traditionally closes stdin, sdtout and stderr, and does a "double fork" when starting, in order to detach from the session and also to signal that they are ready to handle whatever they should handle. This is not really necessary, as long as the daemon is not started from the terminal.
If you want a simple shell wrapper to start you program; you just need to write a small shell script:
#!/bin/sh
/full/path/to/java -jar /full/path/to/program.jar
... and make it executable (chmod 755 )
This article contains a few useful tricks for running a Java application as a daemon:
http://barelyenough.org/blog/2005/03/java-daemon/
Alternatively, you can have a look at the Apache Commons Daemon project, although this requires native code (Unix and Win32 supported):
http://commons.apache.org/daemon/
You can use a cron job to schedule your program. You can also check out this article for details on how to run scripts on startup. You can write a script that runs your java program and run it on startup as mentioned in the article.

How to create windows service from java jar?

I have an executable JAR file. Is it possible to create a Windows service of that JAR? Actually, I just want to run that on startup, but I don't want to place that JAR file in my startup folder, neither in the registry.
The easiest solution I found for this so far is the Non-Sucking Service Manager
Usage would be
nssm install <servicename> "C:\Program Files\Java\jre7\java.exe" "-jar <path-to-jar-file>"
Use nssm.exe but remember to set the AppDirectory or any required libraries or resources will not be accessible. By default nssm set the current working directory to the that of the application, java.exe, not the jar.
So do this to create a batch script:
pushd <path-to-jar>
nssm.exe install "<service-name>" "<path-to-java.exe>" "-jar <name-of-jar>"
nssm.exe set "<service-name>" AppDirectory "<path-to-jar>"
This should fix the service paused issue.
I've been experimenting with Apache Commons Daemon. It's supports windows (Procrun) and unix (Jsvc). Advanced Installer has a Java Service tutorial with an example project to download. If you get their javaservice.jar running as a windows service you can test it by using "telnet 4444". I used their example because my focus was on getting a java windows service running, not writing java.
Tanuki changed license of jsw some time ago, if I was to begin a project, I would use Yet Another Java Service Wrapper, http://yajsw.sourceforge.net/ that is more or less an open source implementation that mimics JWS, and then builds on it and improves it even further.
EDIT: I have been using YAJSW for several years on several platorms (Windows, several linuxes...) and it is great, development is ongoing.
With procrun you need to copy prunsrv to the application directory (download), and create an install.bat like this:
set PR_PATH=%CD%
SET PR_SERVICE_NAME=MyService
SET PR_JAR=MyService.jar
SET START_CLASS=org.my.Main
SET START_METHOD=main
SET STOP_CLASS=java.lang.System
SET STOP_METHOD=exit
rem ; separated values
SET STOP_PARAMS=0
rem ; separated values
SET JVM_OPTIONS=-Dapp.home=%PR_PATH%
prunsrv.exe //IS//%PR_SERVICE_NAME% --Install="%PR_PATH%\prunsrv.exe" --Jvm=auto --Startup=auto --StartMode=jvm --StartClass=%START_CLASS% --StartMethod=%START_METHOD% --StopMode=jvm --StopClass=%STOP_CLASS% --StopMethod=%STOP_METHOD% ++StopParams=%STOP_PARAMS% --Classpath="%PR_PATH%\%PR_JAR%" --DisplayName="%PR_SERVICE_NAME%" ++JvmOptions=%JVM_OPTIONS%
I presume to
run this from the same directory where the jar and prunsrv.exe is
the jar has its working MANIFEST.MF
and you have shutdown hooks registered into JVM (for example with context.registerShutdownHook() in Spring)...
not using relative paths for files outside the jar (for example log4j should be used with log4j.appender.X.File=${app.home}/logs/my.log or something alike)
Check the procrun manual and this tutorial for more information.
Another option is winsw: https://github.com/kohsuke/winsw/
Configure an xml file to specify the service name, what to execute, any arguments etc. And use the exe to install. Example xml: https://github.com/kohsuke/winsw/tree/master/examples
I prefer this to nssm, because it is one lightweight exe; and the config xml is easy to share/commit to source code.
PS the service is installed by running your-service.exe install
[2020 Update]
Actually, after spending some times trying the different option provided here which are quite old, I found that the easiest way to do it was to use a small paid tool built for that purpose : FireDaemon Pro. I was trying to run Selenium standalone server as a service and none of the free option worked instantly.
The tool is quite cheap (50 USD one-time-licence, 30 days trial) and it took me 5 minutes to set up the server service instead of a half a day of reading/troubleshooting. So far, it works like a charm.
I have absolutely no link with FusionPro, this is a pure disinterested advice, but feel free to delete if it violates forum rules.

Categories

Resources