Change process groups on Runtime.getRuntime().exec processes - java

I need to be able to start and stop an external program from inside java. I have the starting working just fine but when I stop it, it kills its parent. It turns out that the process I'm starting is killing its entire process group with a kill 0. Does anyone know how to make it so that my java process is not in the process group of the child program?

So I guess there are two answers:
1) Create your child process as the group leader of a new process group. In Linux I can do this on the command line by using
bash -c "command <args>"
Then you can check that the process group of the new process is different from the terminal you ran the command in with the command:
ps -efj
The 'j' option shows the process group id (PGID).
I will warn you that you may have to escape things weirdly to have it run correctly from Java because the quotes are required for commands with arguments that are passed to the 'bash' command with the '-c' option. So in Java I would guess it would look something like this:
Process processWithNewProcessGroup = Runtime.getRuntime().
exec("bash -c \"sleep 60\"");
2) Change your child process so it doesn't kill everything in its process group.

Related

Backup MySQL via Java

I am making a program to automatically backup a MySQL database from within java using MysqlDump. I want to get the file created and zip it. However, I am having an issue with the MySQLDump.
I am using the following to create a MySQLDump:
Process pr = Runtime.getRuntime().exec(
"mysqldump -u "+user+" --password='"+password+"' "+database+" > /root/moltres/backups/sql/"+database+".sql"
);
I have a while loop after this which remains in the loop if pr.isAlive(). I thought this would work, but it appears that when the command is executed, the process instantly becomes no longer alive. I could make the thread sleep, but for how long? How can I make the same SQL backup, but detect when the mysqldump command has completed?
The command is exiting immediately all right. It is failing, because the redirection isn't being understood by mysqldump.
This is not how you use Process. You need to:
Use ProcessBuilder.
Merge the output and error streams.
Add sh -c or cmd /c as appropriate to the beginning of the command line to handle the redirection.
Start the process.
Consume the output stream and log it, reading until end of stream.
Call Process.waitFor().
Get the process's exit code and log that.
Why you're using Java for this at all is a mystery. It's just a shell script. Indeed you can get MySQL to schedule its own backups automatically, without even needing a script.

Doubts with command: pkill -INT -f '^php test_program.php$'

QUESTION: What does each element of the command:
pkill -INT -f '^php test_program.php$'
do when I run it in the linux terminal? I already know that the command kills the process called test_program.php, but I don't know what all the different elements of the command are doing. Please explain in as simple terminology as possible! I am new to linux commands and I prefer baby lingo to tech lingo at the moment :)
MY RESEARCH: By running man pkill in the linux terminal, a manual appears with the following pkill definition:
signal processs based on their name or other attributes.
which leads me to believe that pkill doesn't only kill a process, but rather can send a lot of different signals, one of which might kill the process. The structure/synopsis of the pkill command was displayed as: pkill [option] pattern
From the list of options in the same manual, -f, -full had the following definition:
The pattern is normally only matched against the process name. When -f is set, the full command line is used.
I didn't completely understand what that meant. Also, there is a -INT before the -f in the command, so that leads me to believe that more than one option can be joined together, however -INT was not displayed in the manual.
The other parts of the command seem to be identifying the program that is running: '^php test_program.php$', but why isn't that part of the command just 'test_program.php'? What does ^php at the beginning and $ and the end do?
You are looking at a Regular Expression. This expression looks for the string test_program.php anywhere in the process name. So if the process name would be something like
/var/php -runcommand test_program.php
it would find the process and kill it.
This also explains the -f, -full option. Not using a Regular Expression, you would have to take the full process name (the preceeding line) to match the process.
Finally, the -INT is usually used to send a runlevel to the task.
EDIT
I was wrong, the -INT option is not used for runlevels (which are for the Linux kernel) but to send signals to a task. This could be something like Term (terminate), Stop (shut down) or Cont (continue process). pkill sends by default the terminate signal to the process.
The /var/php -runcommand test_program.php was an example for a process. If you use the command ps ax, you get a list of all processes and which programs execute them. So I just assumed that the php interpreter resides in /var/php/ and the execution of the php file is a command.

Running a batch from Java where the cmd prompt goes away

I was able to use an amalgamation of SO questions to get a line of code that would:
Run a batch file from within a Java application
Include an argument located in the same directory as the batch file
The argument & batch file are in a directory unrelated to the JAR/java app
So I used this:
Runtime.getRuntime().exec("cmd /c start batchfile.bat argument.js", null, new File( path ));
This works well except that it leaves the cmd prompt open after it has finished executing the batch file. I've looked around and it seems like having the /c flag should make it close after running, but for me it has been staying open. I tried removing 'start' but this meant that the cmd prompt never opened up at all.
Is it because I'm combining having an argument and using a different path that it's not causing the cmd prompt to open and then close after completion like most examples on SO?
Calling both cmd.exe and start in that order is creating a separate window but it doesn't seem like the command shell is terminating based on what you described. I was able to replicate this behavior in a simple batch script. If you want to leave your Java call as it is, check to make sure your batch script includes an exit statement. Preferably exit based on a success or failure condition within your batch script (i.e.: exit 0 or exit 1, etc...)
:: batchfile.bat
...
exit 0
Assuming you are not firing up any new shells within your batch script or prompting for input, adding an explicit exit to your existing batch script should cause the window to close. You can also try to leave your batch script as is, and as others have suggested in comments, change the order of your command text slightly.
Use this instead
start cmd.exe /c ...
Where you call start first and then call cmd.exe /c after followed by your parameters as needed. I tried both options here and either worked fine to cause the batch window to close as expected.
Pass the below command to Runtime to execute.
taskkill /F /IM (processName)
Runtime.getRuntime().exec("taskkill /F /IM "+pProcessName);

Open a new terminal window and execute command in it by java without using bash script

For examples, this is my bash script
osascript -e 'tell app "Terminal"
do script "./process1"
end tell'
osascript -e 'tell app "Terminal"
do script "./process2"
end tell'
Basically, it will open two different terminal windows (on mac) and execute defined commands. I try to do this in java by
process1 = Runtime.getRuntime().exec(new String[]{"process1"});
process2 = Runtime.getRuntime().exec(new String[]{"process2"});
The problem is it seems that there is only one terminal is opened (and not visible - it runs in background) and then two command process1 and process2 are executed. But because the process 1 will keep that terminal busy thus process2 cannot run. That's why I want to open different terminal to execute those commands.
Create a thread for each one of them. and give a time space "sleep(for some time thread 1 or 2)" and this will run both depending on you operating system.

Starting and killing java app with shell script (Debian)

I'm new to UNIX. I want to start my java app with a script like so:
#!/bin/sh
java -jar /usr/ScriptCheck.jar &
echo $! > /var/run/ScriptCheck.pid
This is supposedly working. It does run the app and it does write the pid file. But when I try to stop the process with a different script which contains this:
#!/bin/sh
kill -9 /var/run/ScriptCheck.pid
the console gives me this error:
bash: kill: /var/run/ScriptCheck.pid: arguments must be process or job IDs
My best guess is that I'm not writing the right code in the stop script, maybe not giving the right command to open the .pid file.
Any help will be very appreciated.
You're passing a file name as an argument to kill when it expects a (proces id) number, so just read the process id from that file and pass it to kill:
#!/bin/sh
PID=$(cat /var/run/ScriptCheck.pid)
kill -9 $PID
A quick and dirty method would be :
kill -9 $(cat /var/run/ScriptCheck.pid)
Your syntax is wrong, kill takes a process id, not a file. You also should not be using kill -9 unless you absolutely know what you are doing.
kill $(cat /var/run/ScriptCheck.pid)
or
xargs kill </var/run/ScriptCheck.pid
I think you need to read in the contents of the ScriptCheck.pid file (which I'm assuming has only one entry with the PID of the process in the first row).
#!/bin/sh
procID=0;
while read line
do
procID="$line";
done </var/run/ScriptCheck.pid
kill -9 procID
I've never had to create my own pid; your question was interesting.
Here is a bash code snippet I found:
#!/bin/bash
PROGRAM=/path/to/myprog
$PROGRAM &
PID=$!
echo $PID > /path/to/pid/file.pid
You would have to have root privileges to put your file.pid into /var/run --referenced by a lot of articles -- which is why daemons have root privileges.
In this case, you need to put your pid some agreed upon place, known to your start and stop scripts. You can use the fact a pid file exists, for example, not to allow a second identical process to run.
The $PROGRAM & puts the script into background "batch" mode.
If you want the program to hang around after your script exits, I suggest launching it with nohup, which means the program won't die, when your script logs out.
I just checked. The PID is returned with a nohup.

Categories