I am starting a Java code from Bash script called start.sh. The Bash script fires up the Java code and then the Java code runs. At the end of the Java program, I want to send a signal back to the Bash script to terminate. Keep in mind that the Bash script runs with PID = 1. And I have to kill the PID 1 process.
I have the bash script set up such that it runs in an infinite loop and waits for a termination signal:
#!/bin/bash
# Run the java code here..
# Listen for an exit command.
trap 'exit 0' SIGTERM
while true; do :; done
I am using Docker instances and the signal is sigterm. I am following this tutorial: https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/ which explains how to send a sigterm from command line. I want to automate this process and close/kill the docker instance from inside as soon as the Java program ends.
How do I send the signal back to the bash script that started the Java code in the first place?
Should I follow
this method to send a signal as arguments to the bash script? Or will it start another bash script with a different PID (not 1).
Help needed!
Write 'set -e' in second line in bash script.
Dont use trap and while. Replace it by
'exec your_java_code_run'.
By this way docker get SIGTERM after java code run end.
Exemple:
#!/usr/bin/env bash
set -e
someOtherCodeIfNeed
exec your_java_code_run
Related
I have inherited an extract job program which is a Java program that connects to a database and produces a file from a Unix shell script. At times, I can see the Java program is terminated abnormally and starts executing the remainder of the Unix script by zipping the extract. This is causing a lot of reconciliation issues.
The code is structured as follows:
INSTANCE_NAME=1
PROCESS_NAME=benefitpayment
cd utils
FAIL=0
sh benefitpaymentprocesswithdates.sh $PROCESS_NAME $INSTANCE_NUMBER $1 $2
for job in $dPidLst
do
wait $job || let "FAIL+=1"
done
echo $FAIL
if [ "$FAIL" == "0" ];
then
echo "About to secure file..."
zip -P <password> export.txt secure.zip
...
...
else
echo "FAIL! ($FAIL)"
fi
The $dPidLst is set in the inner Unix script(benefitpaymentprocesswithdates.sh) to call a Java wrapper and is set as:
java program called to generate a file
dPidLst=`jobs -p`
In either of the successful or failure cases, this "dPidLst" is always NULL.
The dPidLst is not exported in the inner script. The script was designed in that manner.
Should dPidLst be exported back to this main program? How do I make this script fool proof in the sense, if the Java program terminates abnormally, it should not execute the remainder of the Shell script? of zipping the file.
The value of dPidLst that you set in benefitpaymentprocesswithdates.sh will not be visible in your calling script.
When you run the benefitpaymentprocesswithdates script, it runs in its own process, and that process gets its own variables.
To pass the process id list back to your script, you need to use a mechanism other than shell variables or environment variables
e.g. at the end of benefitpaymentprocesswithdates.sh, do
echo $dPidList
And when you call it instead of
sh benefitpaymentprocesswithdates.sh
do
dPidList=$(sh benefitpaymentprocesswithdates.sh)
If all it is doing is calling jobs -p, there's no reason to have it in a separate script, of course.
A bat file to execute multiple commands, the previous command to complete, to execute the next command, how to write?
The contents of the batch file are as follows:
java -jar module_eureka-1.0-SNAPSHOT.jar
java -jar module_config-1.0-SNAPSHOT.jar
java -jar module_gateway-1.0-SNAPSHOT.jar
java -jar module_uaa-1.0-SNAPSHOT.jar
java -jar module_user-1.0-SNAPSHOT.jar
java -jar module_news-1.0-SNAPSHOT.jar
If these are web processes, then you will need some way to know if the server is up and running. You could build out a health check api and use that to know if you should try and start the next server
java -jar module_eureka-1.0-SNAPSHOT.jar & \ # start server in background
sleep 15 && \ # wait for it to start
curl -I http://localhost:8080/api/health && # check if server is up
java -jar module_config-1.0-SNAPSHOT.jar & # start next server in background
... etc.
This is not great logic, because how do you know that the health check will always be good or bad after 15 seconds? You should probably just hit the health check api and keep retrying for a given amount of time
Able to call and execute the shell script when executed in an individual Java Program. But there is no output when called from a Floodlight controller program
The Floodlight controller is executed using java -jar target/floodlight.jar. The command to execute the shell script is provided in one of the source files. When ever the condition matches and code gets executed, the terminal screen appears for a second and vanishes. But this is not the case when I execute the same shell script with Java in an individual program.
Process proc = Runtime.getRuntime().exec(new String[]{"path to shell script", arg1});
Can anybody please comment on this ?
Executing with sudo or in root mode is the culprit.
Ran in user mode, worked perfectly.
So I'm using the coproc command in a script to run a java program and to feed input to it, as follows:
#!/bin/bash
echo Script started.
coproc java -jar MultiThreadedFileProcessor.jar
echo start >&${COPROC[1]}
echo Script terminated.
I'd like to be able to write another script which can pass more input to this program (e.g. a command which will tell the program to run termination routines).
Is there any way that I can access the stdin of the coprocess from another script? My current attempt at a termination script is as follows:
#!/bin/bash
echo Script started.
echo terminate >&${COPROC[1]}
echo close >&${COPROC[1]}
echo Script terminated.
This gives me an ambiguous redirect error however, I'm guessing because COPROC[1] is only defined in the script that creates the coproc.
How else, if at all, can I write a script that will accomplish my goal of passing a line to the java program?
COPROC is an array local to the first script - you will never be able to access that from another script.
On Linux, you could access /proc/$pid/fd/$n with $pid being the pid of the first script and $n being the fd stored in ${COPROC[1]}. Both have to be communicated somewhere (a pid file and likewise an "fd file"), but in that case you might better be off creating a named pipe (mkfifo) and use that instead of creating a coproc in the first place. Something like this (not tested) codes:
Script 1:
mkfifo fifoname
exec 5>fifoname
java <fifoname &
echo close >&5
Script 2:
exec 5>fifoname
echo terminate >&5
echo close >&5
What is the close command supposed to do? The java program will see
close
terminate
close
Does that make sense to the java program?
I am running a minecraft server for my son, i'm new at minecraft servers, anyway it seems it keeps dying as it cant keep up? ok so its a VM and i will be assigning more resources to it at some point but my question is as follows
I initiate the server to load up via a script
bukkit.sh is the script an inside it has
#!/bin/bash
java -Xmx1024M -jar /minecraftserver/bukkitserver/craftbukkit-1.7.1.jar -o true
now at somepoint during the day or night it will die as it cant keep up, is there a way i can have some other script run alongside it and see that the process has died and to run that script again to start the server.
when i run top i can see that java is at the top using all the resources so im 100% thats the minecraft java. Does the PID stay the same each time it loads up?
Would be great if someone could let a hand on this ...
I assume the java process remains in the foreground once it's launched? Is there any reason you can't just do:
while :
do
java -Xmx1024M -jar /minecraftserver/bukkitserver/craftbukkit-1.7.1.jar -o true
done
Then any time the java exits, the script will simply restart it.
EDIT:
You could create a script, lets call it craftbukkit.sh
Make sure it is execute by using: chmod +x craftbukkit.sh
Then inside the script you would write:
#!/bin/sh
ps auxw | grep craftbukkit-1.7.1.jar| grep -v grep > /dev/null
if [ $? != 0 ]
then
/path/to/your/bukkit.sh
fi
Change /path/to/your/bukkit.sh to wherever that minecraft startup script is.
Then you need to add this script to your crontab, this is accomplished by entering the crontab editor: crontab -e
If you want the script to run every 5 minutes, add a line that looks like this:
*/5 * * * * /path/to/craftbukkit.sh
Note that you must change the /path/to to point to where you have created the craftbukkit.sh script.