Java Runtime exec() with mysqldump - java

I'm a little curious about the behaviour of Runtime's exec() method when I run mysqldump. I'm running the following command:
mysqldump --user=root --hex-blob [database name] -r [path to sql file]
What I'm wondering is, where does Runtime search for the program mysqldump.exe?
I see that some people supply the whole file path to mysqldump.exe when executing it using Runtime. Why is this?
The reason why I'm curious is because I have two scenarios:
On one windows machine, if I open run and type "cmd" it will open a command window with the default location C:/. Running the mysqldump command on this machine works.
On another windows machine, if I open run and type "cmd" it will open a command window with the default location H:/. Running the mysqldump command on this machine fails. Java's Runtime cannot find the file mysqldump.exe.
Is it possible that the two windows machines have different default drives and if I don't supply the full path to mysqldump.exe, the system will look in the default driver?
Thanks in advance!

As mentioned in the documentation:
Starting an operating system process is highly system-dependent. Among the many things that can go wrong are:
The operating system program file was not found.
Access to the program file was denied
The working directory does not exist.
What I would suggest is starting with a ProcessBuilder, something like:
ProcessBuilder pb = new ProcessBuilder("mysqldump ...");
Map<String, String> env = pb.environment();
env.put("PATH", env.get("PATH") + ";Path/to/mysqldump");
try {
Process process = pb.start();
//some code
} catch(IOException e){
}
This way you ensure the environment variable is correctly set.

Related

Psql not found in cmd Lauched through Java

I know that this question looks a bit similar to this, but mine relates to Windows and in a crucial way. I have the following piece of code:
public static void main(String[] args) {
//String command = "\"psql --version\"";
String psqlPath = "\"C:\\Program Files\\PostgreSQL\\10\\bin\\psql.exe\"";
String command = "\""+psqlPath+" --version \"";
runPostgresqlTableCreator("start cmd.exe /k "+command);
}
private static void runPostgresqlTableCreator(String command) {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("cmd.exe", "/c", command);
try {
Process process = processBuilder.start();
process.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
}
This code works using psqlPath whereby it launches a cmd and prints the PostgresQL version as psql (PostgreSQL) 10.7. However, with using psql --version, it says 'psql' is not recognized as an internal or external command,
operable program or batch file. Running psql --version on a cmd launched by me prints out the version as well. The environment variables are also set properly. From the link provided, the answer states that Java seems to have a problem recognizing the psql path from environment variables (though String command = "\"java -version\"" displays the Java version).
For Linux, it is an okay thing to put the full path of /usr/local/bin/psql, because in most cases, this will always be the path. However, in Windows, users can decide to install PostgresQL in any directory and in any disk volume, making it difficult to get the full path to psql.exe. In my desktop application project using JavaFX, I need to run some psql commands but for something else and not version. I do not wish to set a place where clients can put the path to psql.exe on the interface.
My question is thus, is there a workaround to making psql work without using full path? (Please note that it is not the Postgresql version that I am interested in).
You can use psql without using the full path every time by adding the full path to psql to your system variables. You can do this by going to the control panel, opening the Advanced system settings, clicking on "Environmental Variables" in system variables, and editing the environmental variables. Once this is done, psql can be referenced by simply typing "psql" as the path.
Note: do not delete the other variables. Add the path to psql to the list of environmental variables.
Here is a java document explaining adding to the path as well:
https://www.java.com/en/download/help/path.xml
Once the environmental variable is set you can read it using the System.getenv(String name) method to access a specific variable. You can also use System.getenv() to return a map of all the environmental variables
System.getenv() JavaDoc:https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getenv--

Shell script working fine on linux system but not running on windows machine

I am running a java project on windows machine which reads shell script file for getting the authorization token but getting following error :
java.io.IOException: Cannot run program "./token.sh": CreateProcess error=193, %1 is not a valid Win32 application
Java program for reading the shell script:
private static String execCommand(String username){
String line;
Process p = Runtime.getRuntime().exec("./token.sh -u " + username + " -p password123");
BufferedReader input = new BufferedReader(new
InputStreamReader(p.getInputStream()));
StringBuilder output = new StringBuilder();
while ((line = input.readLine()) != null) {
output.append(line);
}
How can i run the same code on windows machine.
It will not. You see the commands used in Windows CMD and Shell are different since they are completely different platforms. Even-though you use java to execute, it will not execute due to underlying fundamental difference. It is quite clear from the exception you are getting.
What can you do?
Read through the token.sh. Most probably the internal implementation
can be implemented in Windows. Then create an if condition which
checks System.getProperty("os.name") Then if its windows then
call the bat file and if the OS is unix based call the sh file. For
every other OS throw a valid exception.
Other probable way is that, if the token generated in machine
independent, you can use SSH(JSch or similar) to remote connect to a
UNIX server and get the token. If the token is machine dependent (if
its an auth token, then probably is), try using Cygwin interpreter
,which itself does not assure you the every shell file will run in
it.
Change the sh file and its implementation to python or ruby.Then respective interpreter may be installed on machines (which it might actually have,except for production machines).
Write the sh logic in Java itself rather than keeping a script file, since platform independence is actually a requirement here and you already has JRE up and running in both machines.
You cannot do that since the commands that the Linux bash script requires is a lot different than the windows commands.
For example -
To list the contents in a directory in Linux ls
To list the contents in a directory in Windows dir
You have to write a machine/architecture/OS independent code to run across all the operating systems.
Maybe, you can try using Python scripting for that.
Or else, you can ssh from windows machine to Linux machine and run that script from windows in Linux server.
You have to make a Windows specific implementation as well of this script. The most common and easy approach would be to use powershell.
If you want a version that works on both Windows and Unix, perhaps you should look into python.

Can't run exe file using ProcessBuilder depending of computer

I have come across a problem while working with Process and ProcessBuilder in Java.
I have a line of code looking like this :
Process process = new ProcessBuilder("des.exe", String... params);
It works fine on my personal computer, but not on my testing server and I can't figure out why.
The ErrorStream give me this:
des.exe: MZ����#���: not found
des.exe: Syntax error: "(" unexpected
Both computers are on Ubuntu 16.04.4 LTS with java 1.8.
Any idea where it might come from?
The most likely reason for the difference is that the file format of windows executables is not registered with the binfmt_misc handler in the kernel, which allows the kernel to execute various programs through helpers transparently. The error Syntax error: "(" unexpected typically means that the file got handed off to /bin/sh, instead of to wine.
So, check if the binfmt_misc file system is mounted (most modern linuxes do this automatically):
grep binfmt_misc /proc/self/mountinfo
should return some entries (might be autofs, might be binfmt_misc depends on the distro).
if it isn't then mount it:
sudo mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
you can tell what's registered by looking at the content of this directory. To register for running dos executables with wine you need to register it:
echo ':DOSWin:M::MZ::/usr/bin/wine:' | sudo tee /proc/sys/fs/binfmt_misc/register
Once registered, executing the binary should happen transparently, and it should succeed through the ProcessBuilder.
Configuring this for the server at boot time is left as an exercise to the user.
If you want to skip this entire mess, then you can change the execution from des.exe to wine with the first argument of des.exe.

How to add the environment variables to the android Runtime.getRuntime().exec command?

There's an issue when I run the android Runtime.getRuntime().exec method.
I have a native binary file to be run on android and I start it with the java method Runtime.getRuntime().exec. But running this native binary file requires the addition of an environment variable. So I execute this command:
envSetCmd = {"sh", "-c", "export LD_LIBRARY_PATH="+excBinFilepath+":$LD_LIBRARY_PATH"}.
It doesn't work when I check the environment variable with the command:
sh, -c, echo $LD_LIBRARY_PATH.
I think the reason is that when I set the environment variables I start a shell and when I check it with the command "echo" another shell was started. So the environment variables didn't work in the shell I check it.
I think there are two ways to solve this issue. The one is that running two commands in one shell. So I tried to use the command:
{"sh", "-c", "export LD_LIBRARY_PATH="+excBinFilepath+":$LD_LIBRARY_PATH", "-c", "echo $LD_LIBRARY_PATH"}.
Unfortunately it is illegal. The other is that I add the environment variables to the android user startup files. I tried to echo the $PATH, and I see the /system/bin/ and other path was loaded at the startup of android.
So I think there must be a file just like the ~/.bashrc in linux which could set the users' environment.
Any one could give me some clues about the ways I listed above? By the way, I shouldn't root the phone!
try to execute whatever you need to execute with env:
{"env", "LD_LIBRARY_PATH="+excBinFilepath, "yourCmd"}

Tomcat on Windows server woes

Synopsis: When calling an executable that links to shared libraries from Java code on Tomcat, I get errors on Windows 2003 whereas the executable works great on a command prompt.
I wanted to do this in Linux, but, alas, got outvoted and have to implement it using Windows Server 2003. Here it goes,
I have a simple Java code running on Tomcat which, when it receives a "start" signal from another server has to run an external executable (written in C++, using shared library DLLs from OpenCV and ffmpeg) like so
String cmd = "c:\\workspace\\process_video.exe -video " + filename;
// Execute the command
Process proc = null;
try {
proc = rt.exec(cmd);
} catch (Exception e) {
System.out.println("VA-> Exception thrown in running the command!");
errorOut.append(e.getStackTrace().toString());
}
Now, when I run the command in process_video from a DOS command prompt, it works (doesn't matter which directory it's issued from). However, when it is run through the Tomcat->my Java code->rt.exec() chain, cmd doesn't get executed, although the exception doesn't get thrown. When I examine Windows event logs, I see an APPCHRASH event for process_video with Fault Module Name cv110.dll, which is one of the OpenCV DLLs I link from cmd.
One solution would be to stuff all the DLLs used in process_video into the tomcat\lib directory, but this hurts my programmatic sensibilities, so I want to know if there is a better way to solve this issue. What user does Tomcat use when running executables on Windows? Maybe I can give more privileges to that user? Should I add the DLL paths to Tomcat's configuration file?
Any help will be much appreciated,
Thanks!
Cuneyt
Add an entry in the PATH evironment variable that points to where your DLLs are. If this doesn't work for your app, you can try adding the entry to Tomcat's PATH. You have to modify the PATH variable of the process that will be loading the executable. Since your Java code probably shares a JVM (and hence a process) with the Tomcat executable, that will dictate which environment the PATH variable will need to be updated.
This is a Windows problem, not a Tomcat problem.
By default, Windows looks in %Path% for DLLs, which may not include the directory of the EXE file.
You can fix this by creating an empty file called process_video.exe.local in the same direcotry as the EXE ( i.e. c:\workspace )
You can also create a .manifest file, but this is a bit more complicated.

Categories