Running an interactive Python GUI (Matplotlib) from Java Process - java

I have done quite a bit of research on this, and unfortunately have been unable to find an answer that is suitable to the problem I'm currently having.
My question isn't as simple as "how do I run a python script from Java," to which there exists at least 10 threads all containing the same answer. I understand how to do that. My problem is as follows:
I have a .py file (gui.py) which looks something like this:
#!/usr/bin/env python
import matplotlib.pyplot as plt
import copy
import math
import numpy as np
class GUI(object):
...
...
...
if __name__ == '__main__':
GUI.run()
This gui is an interactive matplotlib plot on which users draw stuff. Details aren't important - bottom line is the script runs for as long as the matplotlib window is open.
Now, I'm building a Java app on the side, and there's a button which when clicked creates a Java Process object which will call the script. I know from reading other posts that PIPE cannot be called from the java runtime, so I've created a .sh file which wraps around this python script.
shell.sh:
#!/bin/sh
python /mypath/to/the/gui.py
The Java to call the shell script:
view.getLaunchGuiButton().addActionListener((e) -> {
try {
String[] prcArgs = new String[] { "/mypath/to/shell.sh" };
Process proc = Runtime.getRuntime().exec(prcArgs);
} catch (IOException e1 ) {
e1.printStackTrace();
}
});
The shell script is correct - when I run it from the terminal correctly everything functions as normal.
I know that the Java is indeed executing the shell script, and calling the python script. There are no errors. I didn't set up any BufferedReader because there's nothing to read - I just need to GUI to open. I believe that the problem is that once the shell is executed, the "terminal" so-to-speak which is opened by the Runtime is immediately closed, hence it kills the python script and therefore the GUI.
My question is, how do I keep the Runtime from simply running and immediately killing the python script (AKA closing the terminal)?
Things I've already done:
chmod +x ../../shell.sh
Tried using nohup /call/python/here & in the shell script. Didn't work.
Tried using Java's ProcessBuilder instead of the Runtime. No difference.
Any ideas? Thank you all in advance.

From the Java Button listner I exec-ed xterm:
try {
Process p = Runtime.getRuntime().exec("xterm");
Thread.sleep(1500);
} catch (IOException e1 ) {
e1.printStackTrace();
}
In ~/.bashrc I added my command which starts my Python script with GUI:
if [[ -z "$XTERM_ONCE" ]]
then
export XTERM_ONCE=$(date)
cd /home/qswadey/path/to/py/script/
python3 pyscript_with_GUI.py
fi
The Python GUI shows up and continues...
The idea of running a command on xterm startup, for all xterm is sourced from this thread: How to run a command on the startup of an xterm?
The Thread.sleep is just for holding the xterm for some time to see output of short command, however the xterm remains running in interactive mode

Related

Crontab not running a Processing script

I have a python script that I am running from the command line that does three things
1.) Kills all Processing programs currently running
2.) Runs a new Processing program
3.) Shut downs Raspberry Pi
When running this command from the command line, it works flawlessly. Yet, when calling this Python script using crontab, only the 1st and 3rd processes run correctly. What I want to know is why the 2nd command (running a new Processing program) works when I run the Python script from the command line, but not from a crontab?
Here is my Python script
import os # Use operating system
import subprocess # Use subprocess calls
from time import sleep # Use sleep
from subprocess import call
os.system('sudo killall java')
sleep(5)
child = subprocess.Popen('sudo processing-java --sketch=/home/pi/Desktop/LaserCannonProcessing/LCshutdown --run', shell=True) #
sleep(15)
call("sudo poweroff", shell = True)
and here is my crontab
50 20 * * * sudo /usr/bin/python3 /home/pi/Desktop/Shutdown.py
Does anyone know why crontab can not successfully run the command to run a processing program? If so, is there any way I can fix this and make crontab run that line? Thanks
The cron daemon automatically sets several environment variables. The default path is set to PATH=/usr/bin:/bin.
So if the processing-java command is not present in the cron specified path, you should either use the absolute path to the command or change the cron $PATH variable.
Using shell=True is masking the problem...
E.g.
In [7]: child = subprocess.Popen('bla', shell=True)
/bin/sh: bla: command not found
In [8]: child
Out[8]: <subprocess.Popen at 0x107ac8c50>
You can add some debugging to your script to find out the real issue:
try-except around the subprocess call and shell=True
print the os.environ["PATH"]
check permissions on files (if your process needs to read/write to files)

Running shell script(containing wget) from Java [duplicate]

This question already has answers here:
How to run Unix shell script from Java code?
(17 answers)
Closed 7 years ago.
I'm trying to execute a shell script from Java.The script is supposed to download the file from the URL using wget.Here goes my code.
public class RunShellScriptFromJava {
public static void main(String a[]) {
try {
ProcessBuilder pb = new ProcessBuilder("/bin/sh","script.sh");
Process p = pb.start();
p.waitFor();
System.out.println("Success");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Content of script.sh
echo "start"
wget http://alex.smola.org/drafts/thebook.pdf
echo "end"
My Question:
Is this the right way doing it?If not please point me in the right direction.It doesn't throw any exception but I see that the file is not getting downloaded.Any lead/help is appreciated.
Thanks.
PS:I have given execute permission for the script
The code sample in the question lacks error handling around the usage of ProcessBuilder, so it's likely that some kind of error happened, but you aren't getting visibility into it.
The return code of Process#waitFor is being ignored. The returned value is the exit code of the spawned process. I recommend checking to see if this value is non-zero.
There is also no handling of stdout or stderr, so you won't know if the spawned process is writing any output that explains what happened. You can access stdout and stderr by using Process#getInputStream and Process#getErrorStream respectively.
Note also that it is possible for your process to hang if it fails to fully consume the streams, or at least redirect them. I've noticed this problem is particularly common on Windows. A standard technique is to spawn background threads to consume the streams. This previous question discusses that technique and others.
Java ProcessBuilder: Resultant Process Hangs
After the error handling in the Java code is enhanced like this, I expect you'll have a better chance of diagnosing what went wrong with the script.
The right way to do this is to use Java to download the file instead of the shell script. The problem with shell scripts is that they are system dependent. By using them you lose one of the main benefits of java which is system independence. There are a number of libraries in Java that will accomplish that functionality. The following will work for you using the FileUtils class from apache IO Commons.
URL url = new URL("http://alex.smola.org/drafts/thebook.pdf");
File download = new File('.');
FileUtils.copyURLToFile(url, download);
This script and java example works, perhaps specify the full path to wget to ensure you know where the pdf is being saved.
$ javac RunShellScriptFromJava.java
$ java RunShellScriptFromJava
Success
$ ls
RunShellScriptFromJava.java thebook.pdf RunShellScriptFromJava.class script.sh
Example/updated script:
wget -O /home/MYSER/test.pdf http://alex.smola.org/drafts/thebook.pdf

How to run matlab on the background?

I'm currently using an external editor of Matlab .m files, with a custom build system that calls Matlab from the command line to run the Matlab script (with the -nosplash and -nodesktop). However this creates two problems:
1) Matlab closes right after running the script: any windows or plots I call in the script are closed right after running the script, which obviously happens in a matter of seconds.
2) There is a slight delay every time I run the script because Matlab is effectively being started from scratch.
So I was wondering if would be possible to have Matlab running in the background, and just running the scripts whenever I want?
I'm running Linux 64bits, Matlab 2013a, and Sublime Text 3.
EDIT: I've testing the setup with a basic script:
a=5;
figure
plot(a);
EDIT2: I'm calling Matlab through a Sublime Text build system that runs:
matlab -nosplash -nodesktop <[script].m
There is no way to have Matlab running in the background and "just running the scripts whenever you want" without having an interactive session open somewhere.
Suppose that your system has a custom wrapper matlab-wrapper that is used to submit scripts in the background. You would call your script like this:
$ matlab-wrapper myscript.m
Likely, matlab-wrapper is doing something like this:
#!/bin/bash
/apps/matlab14a/bin/matlab -nodesktop -nosplash -r run\ "$1",exit
Or even more, submitting the above script to a scheduler via qsub or some other command.
The key would be modify the wrapper script to find the part where the Matlab binary is actually invoked. If your system allows, you could copy the wrapper script and modify it. (Either by simply removing the -r run\ "$1" text or something more complicated.) Then, you should be able to launch an interactive version of Matlab per the custom configuration on your system, and call your scripts from the Matlab command window.

restart java app in ubuntu

What's the best way to restart a java app in ubuntu? I know u can run commands like this one from the terminal, but it doesnt seem to be working...
String restartArgs = "java -jar \'/home/fdqadmin/NetBeansProjects/dbConvert2/dist/dbConvert2.jar\' --Terminal=true";
Process restart = Runtime.getRuntime().exec(restartArgs);
System.exit(1);
You are killing the parent process with System.exit(1), so its child process is destroyed as well.
To restart you would typically provide a shell script wrapper to launch the actual Java app.
#!/bin/sh
restartCode="1"; # predefined restart signal code
java -jar '/home/fdqadmin/NetBeansProjects/dbConvert2/dist/dbConvert2.jar' --Terminal=true; # run java program
if [ $? -eq restartCode ] # if exit code is equal to predefined restart signal code
then
$0; # restart script
fi
exit $?;
Note the above code is a rough, crude outline. Typical wrappers are far more complex to deal with commandline arguments passed to the startup script itself etc. etc. Plus, my sh-skills are not infallible.
try providing full path for JAVA_HOME (e.g /usr/lib/jvm/java-6-sun/bin/java instead of java). The exec does not have Shell enironment variables.
also use
restart.waitFor(); //wait until process finishes
to make sure Java does not exit before the process finishes.
If you do want to run in shell (and use shell specific stuffs like pipe and ls) do this:
List<String> commands = new ArrayList<String>();
commands.add("/bin/sh");
commands.add("-c");
commands.add("java -jar /home/fdqadmin/NetBeansProjects/dbConvert2/dist/dbConvert2.jar");
SystemCommandExecutor commandExecutor = new SystemCommandExecutor(commands);
int result = commandExecutor.executeCommand();
commandExecutor.waitFor(); //wait until process finishes

How to Daemonize a Java Program?

I have a Java program that I'd like to daemonize on a linux system. In other words, I want to start running it in a shell and have it continue running after I've logged out. I also want to be able to stop the program cleanly.
I found this article which uses a combination of shell scripting and Java code to do the trick. It looks good, but I'd like something simpler, if possible.
What's your preferred method to daemonize a Java program on a Linux system?
Apache Commons Daemon will run your Java program as Linux daemon or WinNT Service.
If you can't rely on Java Service Wrapper cited elsewhere (for instance, if you are running on Ubuntu, which has no packaged version of SW) you probably want to do it the old fashioned way: have your program write its PID in /var/run/$progname.pid, and write a standard SysV init script (use for instance the one for ntpd as an example, it's simple) around it. Preferably, make it LSB-compliant, too.
Essentially, the start function tests if the program is already running (by testing if /var/run/$progname.pid exists, and the contents of that file is the PID of a running process), and if not run
logfile=/var/log/$progname.log
pidfile=/var/run/$progname.pid
nohup java -Dpidfile=$pidfile $jopts $mainClass </dev/null > $logfile 2>&1
The stop function checks on /var/run/$progname.pid, tests if that file is the PID of a running process, verifies that it is a Java VM (so as not to kill a process that simply reused the PID from a dead instance of my Java daemon) and then kills that process.
When called, my main() method will start by writing its PID in the file defined in System.getProperty("pidfile").
One major hurdle, though: in Java, there is no simple and standard way to get the PID of the process the JVM runs in.
Here is what I have come up with:
private static String getPid() {
File proc_self = new File("/proc/self");
if(proc_self.exists()) try {
return proc_self.getCanonicalFile().getName();
}
catch(Exception e) {
/// Continue on fall-back
}
File bash = new File("/bin/bash");
if(bash.exists()) {
ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c","echo $PPID");
try {
Process p = pb.start();
BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()));
return rd.readLine();
}
catch(IOException e) {
return String.valueOf(Thread.currentThread().getId());
}
}
// This is a cop-out to return something when we don't have BASH
return String.valueOf(Thread.currentThread().getId());
}
I frequently find myself writing scripts or command lines which essentially look like this, if I want to:
Run a program that is immune to sighups
That is completely disconnected from the shell which spawns it, and
Produces a log file from stderr and stdout the contents of which are displayed as well, but
Allows me to stop viewing the log in progress and do other stuff without disrupting the running process
Enjoy.
nohup java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
I prefer the nohup command. The blog post says there are better ways, but I don't think they're enough better.
You could try Java Service Wrapper, the community edition is free and meets your needs.
My preferred way on Ubuntu is to use the libslack 'daemon' utility. This is what Jenkins uses on Ubuntu (which is where I got the idea.) I've used it for my Jetty-based server applications and it works well.
When you stop the daemon process it will signal the JVM to shutdown. You can execute shutdown/cleanup code at this point by registering a shutdown hook with Runtime.addShutdownHook().
That depends. If it's just a one-time thing, I want to daemonize it and then go home, but usually I wait for the results, I might do:
nohup java com.me.MyProgram &
at the command line. To kill it cleanly, you have a lot of options. You might have a listener for SIGKILL, or listen on a port and shutdown when a connection is made, periodically check a file. Difference approaches have different weaknesses. If it's for use in production, I'd give it more thought, and probably throw a script into /etc/init.d that nohups it, and have a more sophisticated shutdown, such as what tomcat has.
DaemonTools :- A cleaner way to manage services at UNIX https://cr.yp.to/daemontools.html
Install daemon tools from the url https://cr.yp.to/daemontools/install.html
follow the instruction mentioned there,for any issues please try instructions https://gist.github.com/rizkyabdilah/8516303
Create a file at /etc/init/svscan.conf and add the below lines.(only required for cent-os-6.7)
start on runlevel [12345]
stop on runlevel [^12345]
respawn
exec /command/svscanboot
Create a new script named run inside /service/vm/ folder and add the below lines.
#!/bin/bash
echo starting VM
exec java -jar
/root/learning-/daemon-java/vm.jar
Note:
replace the Jar with your own Jar file. or any java class file.
Reboot the system
svstat /service/vm should be up and running now !.
svc -d /service/vm should bring vm down now !.
svc -u /service/vm should bring vm up now !.
This question is about daemonizing an arbitrary program (not java-specific) so some of the answers may apply to your case:
Take a look here:
http://jnicookbook.owsiak.org/recipe-no-022/
for a sample code that is based on JNI. In this case you daemonize the code that was started as Java and main loop is executed in C. But it is also possible to put main, daemon's, service loop inside Java.
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo029
Have fun with JNI!
nohup java -jar {{your-jar.jar}} > /dev/null &
This may do the trick.

Categories