I have developed a Java socket server connection which is working fine.
When started from a terminal, it starts from listening from client. But when I close the terminal it stops listening.
I need to continue even though the terminal closed by user from where jar file was started.
How can I run Java server socket application in Linux as background process?
There are several ways you can achieve such a thing:
nohup java -server myApplication.jar > /log.txt - this is pretty straight forward. It will just put the application in the background. This will work but it's just not a very good way to do so.
Use a shell wrapper and the above OR daemon app. This approach is used by many open source projects and it's quite good for most of the scenarios. Additionally it can be included in init.d and required run level with regular start, stop and status commands. I can provide an example if needed.
Build your own daemon server using either Java Service Wrapper or Apache Jakarta Commons Daemon. Again - both are extremely popular, well tested and reliable. And available for both Linux and Windows! The one from Apache Commons is used by Tomcat server! Additionally there is Akuma.
Personally I would go with solution 2 or 3 if you need to use this server in the future and/or distribute it to clients, end users, etc. nohup is good if you need to run something and have no time to develop more complex solution for the problem.
Ad 2:
The best scripts, used by many projects, can be found here.
For Debian/Ubuntu one can use a very simple script based on start-stop-daemon. If in doubt there is /etc/init.d/skeleton one can modify.
#!/bin/sh
DESC="Description"
NAME=YOUR_NAME
PIDFILE=/var/run/$NAME.pid
RUN_AS=USER_TO_RUN
COMMAND=/usr/bin/java -- -jar YOUR_JAR
d_start() {
start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --chuid $RUN_AS --exec $COMMAND
}
d_stop() {
start-stop-daemon --stop --quiet --pidfile $PIDFILE
if [ -e $PIDFILE ]
then rm $PIDFILE
fi
}
case $1 in
start)
echo -n "Starting $DESC: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
restart)
echo -n "Restarting $DESC: $NAME"
d_stop
sleep 1
d_start
echo "."
;;
*)
echo "usage: $NAME {start|stop|restart}"
exit 1
;;
esac
exit 0
There's one crucial thing you need to do after adding a & at the end of the command. The process is still linked to the terminal. You need to run disown after running the java command.
java -jar yourApp.jar > log.txt &
disown
Now, you can close the terminal.
The key phrase you need here is "daemonizing a process". Ever wondered why system server processes often end in 'd' on Linux / Unix? The 'd' stands for "daemon", for historical reasons.
So, the process of detaching and becoming a true server process is called "daemonization".
It's completely general, and not limited to just Java processes.
There are several tasks that you need to do in order to become a truly independent daemon process. They're listed on the Wikipedia page.
The two main things you need to worry about are:
Detach from parent process
Detach from the tty that created the process
If you google the phrase "daemonizing a process", you'll find a bunch of ways to accomplish this, and some more detail as to why it's necessary.
Most people would just use a little shell script to start up the java process, and then finish the java command with an '&' to start up in background mode. Then, when the startup script process exits, the java process is still running and will be detached from the now-dead script process.
try,
java -jar yourApp.jar &
& will start new process thread,I have not tested this, but if still it not works then twite it in script file and start i with &
Did you try putting & at the end of the command line?
For example:
java -jar mySocketApp.jar &
You can also use bg and fg commands to send a process to background and foreground. You can pause the running process by CTRL+Z.
Check it out this article: http://lowfatlinux.com/linux-processes.html
Step 1.
To create new screen
screen -RD screenname
Step 2.
To enter into screen terminal
press Enter
Step 3.
Run your command or script (to run in the background) in the newly opened terminal
Step 4.
To come out of screen terminal
ctrl + A + D
Step 5.
To list screen terminals
screen -ls
that will print something like below
There is a screen on:
994.screenname (12/10/2018 09:24:31 AM) (Detached)
1 Socket in /run/screen/S-contact.
Step 6.
To login to the background process
screen -rd 994.screenname
for quite terminal and this process still working background. for me, the simple and fast way to run the process in the background is using the &! at end of the command:
if this app is built for X server: (eg: Firefox,Zathura,Gimp...)
$ java -jar yourApp.jar &!
if this app is cli (work on the terminal)
# st is my terminal like kitty alacritty
$ st -e bash -c "lookatme --style one-dark --one $1" &!
Related
I have a shell script on a remote linux machine which contains the following:
#!/bin/sh
for i in $(seq 1 10);
do
echo "CREATE TABLE ben$i (id NUMBER NOT NULL);
! sleep 30
select * from ben$i;
! sleep 30
DROP TABLE ben$i;" | sqlplus system/password &
done
wait
The name of this script is ben.sh.
In java, i want to execute this script and keep the script doing what it does in background.
I have a command that execute the script successfully:
sshshell.execute("su - oracle -c './ben.sh'");
I want the script to still run on the remote linux machine and i want to close the ssh connection right after i execute the command above, without interfering the script.
I thought if i put an & at the end of this command like so:
sshshell.execute("su - oracle -c './ben.sh' &");
But still the java program stuck and waits for the script to finish
Very important note: I don't want to use Threads OR any additional ssh connections.
What are my options here?
Use nohup and & to run the script in the background.
sshshell.execute("nohup su - oracle -c './ben.sh' &");
Nohup is short for “No Hangups". Nohup is a supplemental command that tells the Linux system not to stop another command once it has started. That means it’ll keep running until it’s done, even if the user that started it logs out. The syntax for nohup is as follows:
nohup sh your-script.sh &
The & at the end moves the command to the background, freeing up the terminal that you’re working in.
So, you canuse Nohup or Disown commands. With nohup system will avoid exit signals propagating to child processes.
nohup cmd &
Or you can use Disown to deatach it from child proceses.
cmd & disown
I'm trying to optimize some experiments with a Java application. The same application is on many machines. I want to run all of them via a bash script with ssh.
I have a bash script that has a while loop to run the application. Like this
while [ $COUNTER -lt $WORKERS ]
do
ssh ubuntu#host "java java-app.jar" > /data/some-logs.log
((COUNTER++))
((IP_BEGINS++))
done
However when I run the script I have to wait a moment and press Ctrl+C for every machine. How can I run every aplication on background?
prefix with nohup and append a & to the command, that will run it in the background.
while [ $COUNTER -lt $WORKERS ]
do
ssh ubuntu#host "nohup java -jar java-app.jar > /data/some-logs.log 2>&1 &"
((COUNTER++))
((IP_BEGINS++))
done
You might need to muck around with the quotes and placements of the & to make sure the remote ssh command gets backgrounded and not your local ssh
EDIT - I fixed the answer based on your comment. Also added the stderr redirect to the same log file, that might help when things go wrong
I am running a script that basically runs a bunch of servers for local testing.
These jars are run in different screens because they need to all independently accept keyboard input. To do this I used screen.
command1="java -jar $fullPath"
screen -d -m -S "${screenName[$i]}" bash -c "$command1"
It worked great!
then I needed a way to kill all of the servers
so I wrote a script that does that
for session in $(screen -ls | grep -o "[0-9]*\.${screenName[$i]}")
do
screen -X -S "$session" quit
echo "killing screen $session"
done
It works great the screens are killed.
BUT the second I do that java all of a sudden take up 100% of my CPU.
Before I use the quit screen command
After I use the quit screen command
They also take forever to kill through the gui using force quit
Other info:
The servers are using Jetty which run on one java thread. and then another thread just sits and waits for keyboard input.
Obviously this is running on mac and the script is in bash so I would like a bash solution that works for mac and linux.
Also they are built using java 7 but run using java 8
because the servers are accepting keyboard input all commands sent to screen are ingested by the servers.
They do have input that quits them but I don't want to trust the servers to quit.
So my questions are:
Is there a way to have a screen terminate all running processes in it when it terminates?
if not is there a way to send the ctrl-c to a specific screen?
If not is there a way to see what the running process of a certain screen is without running commands in the screen itself? (then I can just use kill)
tl;dr when I kill screen the running process starts using all my cpu and does not terminate. I want it to terminate.
Made the solution myself.
In a nutshell it finds the screen process and finds all java processes then looks for a java process whose grandparent process is a screen.
It is extremely inefficient as it loops through the array for every screen. So basically O(n^2) but there are very few so it works for me!
Code:
length=$(expr ${#screenName[#]} - 1)
# gets all of the java processes and their grand parents
# the reason is that the screen makes 2 processes one is the java process and the other is the parent process
# I can't grab a children in mac for some reason BUT i can grab the parent process
javaPs=()
javaGpPs=()
for javaId in $(pgrep java)
do
#echo
#echo $javaId
#echo $(ps -o ppid= $javaId)
#echo $(ps -o ppid= $(ps -o ppid= $javaId))
javaPs+=($javaId)
javaGpPs+=($(ps -o ppid= $(ps -o ppid= $javaId)))
done
echo "Child procressed followed by screen processes"
echo ${javaPs[#]}
echo ${javaGpPs[#]}
#gets the index of an element in an array
#search term is first followed by the array
#note that becuase it returns by echo you can not add any debug statements into this function
search() {
local i=1;
searchTerm="${1}"
shift #moves over the argument looking
array=("${#}") #grabs the rest of the args as an array (which is an array)
for str in ${array[#]}; do
if [ "$str" = "$searchTerm" ]; then
echo $((i - 1)) #should reference the correct index (0 to something)
return
else
((i++))
fi
done
echo "-1"
}
for (( i=0; i<=$length; i++ ))
do
#looks to see if there are multiple screens with the same name
for session in $(screen -ls | grep -o "[0-9]*\.${screenName[$i]}")
do
echo
echo "killing screen $session"
IFS='.' read -ra ADDR <<< "$session" #splits the id from the name
pid=${ADDR[0]}
screen -X -S "$session" quit # exit session
# now we kill the still running java process (because it will not exist for some reason)
itemIndex=$(echo $(search "${pid}" "${javaGpPs[#]}"))
javaId=${javaPs[$itemIndex]}
# the process that is being killed
echo "killing java process"
echo $(ps -p $javaId)
kill -9 $javaId
sleep 1
done
done
echo
echo "All process should now be dead doing extra clean up now"
screen -wipe #remove all dead screens
I have a Java application executed from a ([ba]sh) shell script and unfortunately sometimes the people responsible for deploying it and starting it fail to switch to the appropriate user before starting the application. In this situation I'd like the application to not run at the very least, and ideally issue a warning not to do that. I thought about trying to alias java or change the path for root to include a fake java which does so, but this might have undesirable side effects and isn't going to be effective easily since the shell script specifies the full path to the java binary.
So, is there a standard idiom in shell scripts for 'don't run if I'm root'?
Example in bash:
if [ `id -u` = 0 ]; then
echo "You are root, go away!"
exit 1
fi
In BASH, you can take the output of whoami and compare it to root.
I use something like this at the beginning of scripts that I want to
be run under a service account:
LUSER='my-service'
if [ `id -un` != $LUSER ]; then
exec su $LUSER -s $SHELL -c "$0 $#"
fi
# actual script commands here.
If run as the correct user, execution will continue as planned. If run
as root, privileges are dropped to the wanted user-id. Other users
will get a password prompt which should tell them that something is
wrong.
su -s $SHELL ... is used to override the shell set in /etc/passwrd
-- it may be set to /bin/false for the service account.
I have used this on Debian systems, using bash and dash. Feel free
to comment if portability can be improved.
Hi I am using 64bit Fedora 10 linux. I have created a sample java application. Now I want to write init script for that application. so that my application should start on bootup.
How to write init script to start on bootup.
Thanks
Sunil Kumar Sahoo
There's quite a good guide here:
http://www.novell.com/coolsolutions/feature/15380.html
I'd suggest taking a look at the tomcat startup.sh and shutdown.sh scripts, and then modifying the following init.d script:
#!/bin/bash
#
# tomcat
#
# chkconfig:
# description: Start up the Tomcat servlet engine.
# Source function library.
. /etc/init.d/functions
RETVAL=$?
CATALINA_HOME="/usr/apps/apache/tomcat/jakarta-tomcat-4.0.4"
case "$1" in
start)
if [ -f $CATALINA_HOME/bin/startup.sh ];
then
echo $"Starting Tomcat"
/bin/su tomcat $CATALINA_HOME/bin/startup.sh
fi
;;
stop)
if [ -f $CATALINA_HOME/bin/shutdown.sh ];
then
echo $"Stopping Tomcat"
/bin/su tomcat $CATALINA_HOME/bin/shutdown.sh
fi
;;
*)
echo $"Usage: $0 {start|stop}"
exit 1
;;
esac
The above script is missing much of the stuff to make it fully Linux Standard Base compliant. You may want to copy an existing init.d script from your distro. A slightly better script can be found here: http://blog.valotas.com/2011/05/tomcat-initd-script.html
I usually just take one of the smaller init scripts from /etc/init.d and modify it.
Edit
The easiest thing to do is just add your program to the /etc/rc.local file. It will be the last start script executed. You won't have to mess around with the "start" and "stop" stuff.
However, if you're interested in being able to start and stop your program at will, you'll need to write a script.
Some of the other answers here will get you started.
Many distributions come with a skeleton script you can use as a template for your own init script, in /etc/init.d/skeleton or /etc/init.d/skel.
Some of the best java applications that I have seen tend to use the tanuki wrapper for this.
It standardises startup scripts across different OS's, i.e. can be used to configure a *nix daemon or a windows service.
It provides a standard command line interface for stopping, starting, restarting and checking the status - running or not.
I appreciate seeing it used more and more, as I don't have to learn it again, learn it once and reuse it again and again.
By using this service library, your application can benefit from future enhancements.