I have a linux daemon that starts a java instance for each user that is logged on the system.
I use the followig command to start the java application for each user:
cd /home/user/java_path/ && sudo -u user /opt/jdk1.7.0_17/java -jar software.jar &
The java application monitors a folder and opens a frame for authentication when a new document is create. Each java application reads only the users files (by a name pattern). When tries to open a frame, but I get this error (on a log):
No X11 DISPLAY variable was set, but this program performed an operation which requires it.
java.awt.HeadlessException: ...
When I execute the java application in a regular command line (terminal), this works well.
I saw also the export variables, using export -p command and the display variable is ok for all users logged.
Some java classes depend on having i.e. display device and if you don't have any(running without X-server), they fail with the error you're getting.
Run java with following parameter:
-Djava.awt.headless=true
More info here:
http://www.oracle.com/technetwork/articles/javase/headless-136834.html
The code worked. To resolve that, I had need to export java variables and then starts the java application, in a sequence, like that: cd path && export DISPLAY=:0.0 && export USERNAME= user && sudo -u user javapath/java -jar app.jar >/dev/null 2>&1
Use System.setProperty("java.awt.headless", "true"); or -Djava.awt.headless=true JVM arg
Related
I'm learning to deploy Spring Boot apps on AWS EC2. And I know how to automate app launch, when I start the EC2 instance, I don't need to manually use the command java -jar java-service.jar, I just add this command in the /etc/rc.local file and that is all. But I have 2 microservice, and I want to start both of them automatically, but if I try to add both commands in the /etc/rc.local it's not working, only the first service will start, the second service will not start.
So I have the commands added like this:
And after I start the EC2 instance only the first service is started:
Thank you!
I am not a unix expert, but I see the only issue in running 2 java commands from terminal is that unless the first command returns, the next command is not executed. So, I think the solution would be run the 1st command in some interactive mode so that the other commands can be executed simultaneously.
There are ways in unix shell to run a command in background. I found this useful link - https://www.maketecheasier.com/run-bash-commands-background-linux/
In bash terminal, a command can be made to run in background by appending it with &. So, I think you should be able to start both jars if you do something like -
java -jar /home/ec2-user/first.jar &
java -jar /home/ec2-user/second.jar
I recommend to use Systemd.
Create a Systemd unit file for every microservice, save it in /etc/systemd/system/my-app.service. Something like that:
[Unit]
Description=My Java app
After=syslog.target network.target
[Service]
EnvironmentFile=/etc/sysconfig/my-app-env
WorkingDirectory=/my/app/home
ExecStart=/usr/bin/java $JAVA_OPTS -jar my-app.jar
KillMode=process
User=my-app-user
Restart=on-failure
[Install]
WantedBy=multi-user.target
Then, run:
systemctl daemon-reload
systemctl enable --now my-app
After that, you can use:
systemctl status my-app
systemctl stop my-app
systemctl start my-app
Another solution is to bundle your jars into Docker images. This of course requires Docker runtime and adds an overhead, but it also has some benefits:
Complete separation of jar files. Easily use different java versions.
No need to worry about differences of local and ec2 environment.
Easily scale to 3 or more jars.
Use Docker Cli to build and start containers. Works great in a Devops Pipeline.
You can read here to learn how to create Spring Boot Docker images. After you build an image. You start it like this.:
docker run -p 8080:8080 springio/gs-spring-boot-docker
You can run as many docker run commands you need, one after another.
I am not sure which system you are using in starting application:
For linux base system, you can use crontab to schedule the task when the server reboot.
Follow this steps:
Download crontab
#apt-get install cron
Edit the file file to enable the task
crontab -e
(Choose Vim or nano to edit the task)
Add this code to your server
#reboot /usr/bin/java -jar XXXXX.jar
Save your file
Check the result
crontab -l
#systemctl status cron
This method works in my Debian system. For more details, you can refer to
How to automatically run program on Linux startup
If you are running from bash, then join two jar commands with "&" like below.
java -jar /home/ec2-user/first.jar&java -jar /home/ec2-user/second.jar
coupon service
Run the command 'java -jar /home/ec2-user/coupon-service-0.0.1-SNAPSHOT.JAR'
Press CTRL+Z, type bg, press Enter, type disown, press Enter.
product service
Run the command 'java -jar /home/ec2-user/product-service-0.0.1-SNAPSHOT.JAR'
Press CTRL+Z, type bg, press Enter, type disown, press Enter.
NOTE: Both services should have different ports.
So when I run code runner (using java) it asks for javac
so I have to set up a path, but on the computer that I'm using doesn't allow permanent path so, I've been using:
set path=C:\Program Files\Java\jdk1.8.0_241\bin for cmd
or
$env:Path = "C:\Program Files\Java\jdk1.8.0_241\bin"; for powershell
I'm using the VS Code run in terminal so it gives me the .class (yes I know that if I run it in F5 it has no problems but I don't like the text mess on the terminal XD)
So the question is how can I make a custom command so it sets up the path (be it at startup or every time)
Or, Do I have to modify the default settings? (if so where is the file location)
To set the default path on Windows, go to Control Panel, System, Advanced System Settings, Environment Variables.
For cmd:
1.open a cmd and run the commands:
reg add "HKCU\Software\Microsoft\Command Processor" /v AutoRun ^ /t REG_EXPAND_SZ /d "%"USERPROFILE"%\init.cmd" /f
2.create a file in your USERPROFILE(likes:C:\Users\UserName) folder named "init.cmd" and then you can set the commands which you want to run automatically when the Command Prompt is launched.
I have azure-cli installed in my mac and I can successfully execute all azure commands from cli. I want to do the same from a java application. I have seen examples of using REST endpoints and azure-sdk-for-java. But what I want is to execute the azure-cli commands directly from java.
I tried running 'azure login' from a java program, but I got the following error.
Cannot run program "azure": error=2, No such file or directory
The problem is in a lack of your PATH variable. If you want to enjoy the same "find the command" capabilities that you have on the command line, you need to set it somehow within your Java program: import the PATH variable from the environment, set it within the code you're writing, or whatever mixture covers your needs.
Giving the absolute (full) path is the surest way, but you may not want to read such long command names in your source codes.
#harshithabt Per my experience, the issue was caused by the command azure could not be searched in the directories listed in PATH. There are two ways to solve the issue for running commands in Java, please see below.
Setting up the environment variable PATH for the current shell session or the configuration files ~/.profile(or ~/.bashrc).
If you command export PATH=<your-node-path>/bin:$PATH in a shell session, you only run the Java program with azure command in the current shell session, even run via the Java IDE which must be opened in the current shell session (it means you should open Eclipse via command <your-ide-path>/eclipse).
If you configure the files ~/.profile or ~/bashrc to add the node runtime as below, please make sure the configuration files have been reloaded via command source ~/.profile in a current session or restart sessions via logout & login or reboot.
A simple way is that adding the command links into the dirs listed in PATH, such as /bin. You just need to run the commands below.
sudo ln -s /bin/node /bin/node
sudo ln -s /bin/azure /bin/azure
Then you can run azure-cli command from Java successfully.
I have a runnable jar file produced from clojure code that I am running on an embedded system (udoo - http://www.udoo.org/), which is running a version of Ubuntu for its OS (udoobuntu - http://www.udoo.org/udoobuntu-the-official-udoo-linux-operating-system/).
The jar file contains a clojure library I wrote, that includes a some Java swing stuff.
Running the jar manually via the command line using:
sudo java -jar myjar.jar
works fine. The sudo is needed for certain usb device permissions.
My problem arises when I try to start the jar using an upstart script called testjob. The relevant part of /etc/init/testjob.conf looks like:
start on (desktop-session-start)
expect fork
script
exec ./home/ubuntu/start > /home/ubuntu/boot-jar.log 2>&1 &
end script
Where /home/ubuntu/start is the following shell script:
#!/bin/sh
sudo java -jar /home/ubuntu/myjar.jar
exit 0
When this runs, either manually via:
sudo start testjob
or automatically by rebooting the system, I get the following output to the log file:
Exception in thread "main" java.lang.ExceptionInInitializerError
... <bunch of meaningless classloading stuff>
Caused by: java.awt.HeadlessException:
No X11 DISPLAY variable was set, but this program performed an operation which requires it.
at sun.awt.HeadlessToolkit.getMenuShortcutKeyMask(HeadlessToolkit.java:236)
at seesaw.keystroke$preprocess_descriptor.invoke(keystroke.clj:25)
at seesaw.keystroke$keystroke.invoke(keystroke.clj:50)
at seesaw.keystroke$keystroke.invoke(keystroke.clj:49)
at seesaw.keymap$map_key.doInvoke(keymap.clj:107)
at clojure.lang.RestFn.invoke(RestFn.java:445)
at seesaw.widgets.log_window$log_window.doInvoke(log_window.clj:88)
at clojure.lang.RestFn.invoke(RestFn.java:457)
at physicloud.utils__init.load(Unknown Source)
at physicloud.utils__init.<clinit>(Unknown Source)
... 52 more
I don't actually make any UI calls, but the run fails on classloading of the library. I know that a simple fix would be to remove the Java Swing code from the library, but the library is generalized to allow ui output to capable machines, and therefore I am looking for a workaround. It doesn't make sense to me why the jar will run via java -jar but not in the script.
I tried different cases for the upstart script's "start on" condition, all of which produced the same result.
I tried setting the $DISPLAY environment variable in the upstart script before executing the jar, but to no avail.
I also tried scheduling the start script using crontab #reboot, but the error was the same.
Anyone have suggestions?
You can pass -Djava.awt.headless=true to java to allow running non-GUI applications that happen to depend on some UI libraries.
For example,
java -Djava.awt.headless=true -jar something.jar
I have written a java program with jar file. The java program is to update status of linux server so it need to keep running, but the linux server is in data center, so I need to remote to server to open the program. I use ssh to login linux server. Use command of "java -jar file.jar" to run the program.
However, the java program of the linux server will close if I close the terminal in my computer. Since I cannot keep opening my computer, I wanna know how to open the java programming without holding my computer terminal.
you need to use nohup to keep the program running after you log out.:
server:~name$> nohup java -jar file.jar &
this will keep your program running
Two ways
One
nohup java -jar file.jar &
Another
java -jar file.jar &
In both cases your process will go in background however the process will terminate in the second approach when shell terminates in second case.
If this program is intended to be running on all your machines for monitoring purposes, you should be running it as a service from your server's init system (systemd for most systems these days). You can use the Java Service Wrapper or jsvc or write your own init script.
Another solution apart from the proposed one:
screen -d -m java -jar your.jar
You will then have a detached screen with your java command in it. List with screen -l, reattach with screen -D -RR <screenid_obtained_via_screen_-ls>