Java and Bash shell - java

I was hoping someone will be able to give me some advice. I am running a program in java and need to include a function that has already been written in bash. I honestly am not sure where to begin.
I have file that I process to some extent with my java program (I take out duplicates, sort names, etc). I end up with several paths to other files.
for(String go:parsun){
pathed="/home/S/Data/"+go+"/Ana/lysis/"+go+"/file.vcf";
System.out.println("Pathed: " + pathed);
}
I need to take these paths and put them through a bash program which takes the contents of the files and does some math-ish things to their innards.
I have seen around the internet that you could do something like this to run a bash script in java:
Process pro=Runtime.getRuntime().exec("shellfilepath");
BufferedReader read=new BufferedReader(new InputStreamReader(pro.getInputStream());
But I am not sure I understand how that works, or how I would go about passing my file paths to it. Also, another consideration is that I will have to slightly modify the bash script to allow it to take in these paths. Previously the paths were hardcoded before hand. I will also need some suggestions on that front.
Is this the best way to have bash and Java work together? Is there another technique? If not, could someone help me with understanding how to use Runtime?
Thanks

You could use:
Process process = Runtime.getRuntime().exec("bash_command " + pathed);
The pathed filename will be passed in as the $1 argument.

The following looks like a pretty good intro into running shell scripts from java:
http://obscuredclarity.blogspot.com/2011/07/executing-shell-script-from-java.html
It shows how to modify your shell script to accept arguments, and how to use Runtime.exec() to call the script and pass arguments to it.
Also see the API for the Runtime class: http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html

Runtime.exec(String) is a good way to do this, but you need to be careful about whether or not the path to your script contains spaces. A better approach would be to use Runtime.exec(String[]). This will make sure that Java treats your script path as one command parameter instead of trying to split it on spaces.
Process process = Runtime.exec(new String[] {shellFilePath});
Also, make sure to include #!/bin/bash at the top of your script.

You have two choices:
Rewrite the logic from the bash script in Java. This will execute faster and be less brittle, but if the bash script is large and complex or legacy code that nobody left understands, it may be more work than you want to do.
Execute the bash script using ProcessBuilder; you can pass command-line arguments to it. This comes with its own set of issues having to do with coordinating between two processes. If the bash script does not expect any input things are a little simpler, but in general you need to start the script, run input and output handlers on separate threads, and then wait for termination. This is a little difficult to get right if you've never done it, although there are good examples on the web.

Related

Managing Powershell Sessions Using Java

I want to be able to manage Powershell PSSessions using Java. For example I want to have separate Java methods for starting sessions and ending them. Is there an easy way to have these methods? I'm thinking there could be a Powershell API, or stuff like that.
Quick answer: No.
Longer answer: You could create one yourself, but you should try and avoid this.
PowerShell is a set of .NET types (the various System.Management.Automation namespaces), there is not even a C API. But you could wrap enough of the PowerShell types in something you could call from Java and then use that. However as you cannot run Java in the same process part of that adapter/proxy layer will need to perform inter-process communications this is not going to be an easy task.
If your requirements were to just be able to run a PSH script then you can launch a PowerShell process with the right command line, eg. to run script.ps1
%windir%\System32\WindowsPowershell\v1.0\Powershell.exe -file path-to-script.ps1
By reading from standard input in the script, and controlling standard input of the child process you could pass commands to a coöperating script:
while (($in = [console]::in.ReadLine()) -ne $null) {
Write-Debug "Input: '$in'"
if ($in -match '^\s*exit\s*$') { break; }
}

Calling shell script from java program and passing arguments to a shell script from java for loop

Does anyone know if it is possible to call a shell script from within Java program and also pass an argument to that shell script from the for loop of that java class? In my shell script I am setting MySQL system variables to different values to see if those values affect the performance of the database application. I could have set those values through JDBC, but as I am working with MySQL, it is not possible to restart the database from JDBC, after each query execution.
Yes it is possible. For something like this you would probably be better off just using a batch file or something to do it though.
If you really do need to use java try:
How to run Unix shell script from Java code?
Runtime.exec() is what you are looking for.
Runtime.getRuntime().exec("theScript.sh param1 param2);
..modulo exception handling.
You may want to look into Apache Commons

invoking an ant command via make

I'm trying to do soemthing which may not be done that often. It's part of our test code which uses a wide variety tools: java, ant, make, and xml.
Our java testing tool parses XML. It gets an argument via an XML tag from a file:
<TAG>-Darg1="argument1" -Darg2="argument2"</TAG>
Within the java code, I'm calling the make command. The make command is invoked from java (via ProcessBuilder).
In the makefile, I am calling ant where the -Darg="argument1" -Darg2="argument2" args should be passed.
But it's not working.
Anyways, it seems that the -D from the -Darg1= ... part is not compatible with make, so I'm trying to enclose that in a variable that I can pass through make to ant. Within ant it's taking the variable "RULES_ARG" and treating that as one argument, instead of two.
I've tried various quoting mechanisms in xml: "-Darg1=argument1 -Darg2=argument2", "-Darg1="argument1" -Darg2="argument2""
and also where it's invoked in java: "RULES_ARGS="+RulesArgs+" ", "RULES_ARGS=\""+RulesArgs+"\" " (in combination with the xml part).
etc. all with no desirable result.
I was wondering if anyone has tried to do something similar, and the working approach to the problem?
Thanks in advance.
Are you saying you're trying to run make with -D options? That won't work because make doesn't support -D.
If you're trying to pass some flags through the make command line to be used on the ant invocation, then you should do something like this: when you run make set a variable on the make command line:
make ANTFLAGS='-DFOO -DBAR -DBAZ'
Then inside your makefile, when you run ant, pass that variable:
runant:
ant $(ANTFLAGS) ...
If that's not what you're trying to do please clarify your question. For example, you say it's not working and no desirable result, but you don't give any details about what errors or incorrect behavior you see. Such error messages would go a long way towards clarifying exactly what's going on.

Create an environment variable programmatically

I have an external program that I'm running.
for some reason, the code owner didn't give me the code or and good documentation, I know how to run this code but it was written originaly to be executed from command line and not from JAVA.
the effect on me is that this application uses an ENV variable and relay on its value (a path on the computer for the output).
I want to change that value, how can it be done without running it from a batch file?
I assume you are executing this program using one of the Runtime.exec() methods in Java code to create a Process.
Note that some of those methods allows you to pass environment variables to the process you are creating, for example exec(String[] cmd, String[] envp).
Alternatively, the Map returned by ProcessBuilder.environment() can be manipulated for the same effect.
how can it be done without running it from a batch file
Just set global environment variable. All new processes will see it (excluding those inheriting environment from old parent process).
See also How do I set environment variables from Java?.
This answers the question's title. Which doesn't match the question's body, btw. ;)
See this post. It usually helps to first start a search here before posting a question. If you already tried that solution, it really helps the Helpers to let them know that you tried it and what went wrong.
In your command prompt first set the required variable
set FILELOCATION=<PATH TO FILE>
java MyProgram
In this case the FILELOCATION will be available till you close the program.
Not setting variable will be dependent on OS.
For Linux or Solaris you can do :
export FILELOCATION=<PATH TO FILE>
In case you are looking for command line parameters then you can use something like this:
java MyProgram PathToFile
There is a better way of doing this java -DFILELOCATION=<PATH_TO_FILE> MyProgram
Edit: As per comment.
Just use ProcessBuilder to set ENV variable in Java code.

Passing an entire file to JVM arguments

I have several systems that all need to load the same properties to the JVM. I can use the -D flag to load one property at a time, but i am looking for something that will load all the properties in an entire file at one time. For instance:
I could just add --options-file=blah.properties to all jvms on my network, once, and from then on only change the properties file, which could be a single central file over a network share.
Thank you,
EDIT: Any arguments or commands must also work in a windows environment. Therefore any bash or scripting hacks specific to unix will not work.
That's roughly how we do it:
java $(tr '\n' ' ' < options_file) other args...
Here options_file contains ready -Dsomething or -Xsomething values, one per line. The tr command just replaces every newline with a space.
I don't think you can do that via the command line (without some bash hacks, perhaps), but you definitely can do that programatically:
Simply set one property -DmyPropertiesFile=/your/properties/file.properties and then read that with one of the Properties.load() overloads. After that, System.setProperties(yourProps) should do what you expect.
Of course, this requires that you can hook this code early enough so that your properties will be available when needed (For instance, if the main() method is yours, this is perfect).
Some options:
Wrap your properties in your .jar file and then get your processes to read that properties file from getClass().getResourceAsStream()
Write a batch file to execute your Java processes, and either explicitly list the -D options, or create the command line dynamically.
I solve this problem normally by using Spring (used for other reasons too) and a PropertyPlaceholderConfigurer. That allows me to specify one or more locations for property files and modifies the Spring configuration in-place.
If you use Ant to lanuch the Java process, 9000's answer (plus his windows comment) will work, and you can have the launcher deal with the OS difference.
There is a StackOverflow thread here which describes how to determine the OS from ant

Categories

Resources