Java ProcessBuilder to start multiple java processes - java

Can I spawn multiple different JVMs given the same Main.class, arguments and VM options?
Is it possible to do it with the ProcessBuilder?

Here is a basic example using Process that starts 10 different JVM process:
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
public void run() {
try {
//start a new jvm with 256m of memory with the MyClass passing 2 parameters
String cmd = "java -Xmx256M -cp myjar.jar com.mymainclass.MyClass par1 par2";
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = br.readLine();
while (line != null) {
line = br.readLine();
}
br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
line = br.readLine();
while (line != null) {
line = br.readLine();
}
} catch (IOException e) {
}
}
}).start();
}

Related

java getRuntime().exec() does not work for running basic cmd commands

I am trying to run cmd commands using getRuntime().exec(). The problem is that it works only if my command string is ipconfig, whereas if I try to run commands like java -version or time, it then throws the error :
java.io.IOException: Cannot run program "time": CreateProcess error=2, The system cannot find the file specified
String command = "time";
Process p;
try {
p = Runtime.getRuntime().exec(command);
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
//System.out.println(line);
textField_1.setText(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I solved this issue by using ProcessBuilder. I still don't know why the earlier code didn't work for all the commands. But by using ProcessBuilder, I was able to perform any cmdquery.
Here's the code for reference:
String command_ping = "ping " + host_name;
try {
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", command_ping);
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuffer buffer = new StringBuffer();
String line = "";
while (true)
{
buffer.append(line).append("\n");
line = r.readLine();
if (line == null) { break; }
}
message_ping= buffer.toString();
p.waitFor();
r.close();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}

Run multiple system commands

I have been playing with java processes for a while and am stuck. What i want to do is run multiple system commands at the same time and print their output to console.
For example, ls -l ; cat someFile ; quit ; grep foo someOtherFile should all be running at the same time. I have read somewhere that the output of these commands should be intermixed. In addition, if there's a quit command anywhere in the string, continue executing other commands and then exit.
Right now, they are executing sequentially. How do I run them concurrently and print their output as it arrive.
String st = "ls -l ; cat someFile ; quit ; grep foo someOtherFile";
String[] rows = st.split(";");
String[][] strArray = new String[rows.length][];
int index = 0;
for(int i = 0; i < rows.length; i++) {
rows[index] = rows[index].trim();
strArray[index] = rows[index].split(" ");
index++;
}
for(int i = 0; i < strArray.length; i++) {
if(rows[i].equalsIgnoreCase("quit")) {
System.out.println("Abort");
break;
}
if(rows[i].equals("")) {
continue;
}
ProcessBuilder pb = new ProcessBuilder(strArray[i]);
pb.redirectErrorStream(true);
Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ( (line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
Just put the guts of your loop inside the run() function of a new thread, and each iteration of the loop will run in a separate thread:
new Thread() {
public void run() {
// loop guts go here
}
}.start();
You may have to declare a few variables as finals in order to access them inside this anonymous inner class.
You can try code similar to this:
// command list
String st = "ls -la; cat someFile";
String[] commands = st.split(";");
for (int i = 0; i < commands.length; i++) {
String currentCommand = commands[i].trim();
System.out.println("Command: " + currentCommand);
Thread thread = new Thread(() -> {
try {
ProcessBuilder command = new ProcessBuilder(currentCommand);
Process process = command.start();
InputStream is = process.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
});
thread.start();
}
Disclaimer: not tested on a Linux machine. Windows machines will probably not work. See this link regarding Windows command line process execution.
You should look to some documentation about concurrency, threads an such http://docs.oracle.com/javase/tutorial/essential/concurrency/.
Here an edit to your code that may work, not tested.
String st = "ls -l ; cat someFile ; quit ; grep foo someOtherFile";
String[] rows = st.split(";");
String[][] strArray = new String[rows.length][];
int index = 0;
for(int i = 0; i < rows.length; i++) {
rows[index] = rows[index].trim();
strArray[index] = rows[index].split(" ");
index++;
}
List<Thread> threads = new ArrayList<Thread>();
for(int i = 0; i < strArray.length; i++) {
if(rows[i].equalsIgnoreCase("quit")) {
System.out.println("Abort");
break;
}
if(rows[i].equals("")) {
continue;
}
final int iForThread = i;
Thread thread = new Thread() {
public void run(){
try{
ProcessBuilder pb = new ProcessBuilder(strArray[iForThread]);
pb.redirectErrorStream(true);
Process process = pb.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ( (line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}catch(IOException e){
//Log some awesome error
//Clean up
//Do whatever
}
}
};
threads.add(thread);
}
final CyclicBarrier gate = new CyclicBarrier(threads.size() + 1); //+1 is a tip from other post
for(Thread thread : threads){
thread.start();
}
try {
gate.await();
System.out.println("all threads started");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
/* RONALDO OF ERROS
* MESSI OF HANDLERS*/
}
}
It creates an tread and executed it at the spot.
I if you are just messing around I think this enough.
Edit: Added start threads at "same time"
Based on: How to start two threads at "exactly" the same time
See:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html

Running Grep command from java

I want to run grep command from java.
Here is what I had tried. Please let me know, why it is not displaying ouput.
public static void main(String args[]) throws IOException{
Runtime rt = Runtime.getRuntime();
String[] cmd = { "/bin/sh", "-c", "grep 'Report Process started' server.log|wc -l" };
Process proc = rt.exec(cmd);
BufferedReader is = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}
System.out.println("Done");
}
You don't need to pipe grep's output to wc -l. Just use grep -c like this:
String[] cmd = {"/bin/sh", "-c", "grep -c 'Report Process started' /path/to/server.log"};
Though I must say that doing this right inside Java is much cleaner. Consider code like this:
String logdata = new Scanner(new File("/path/to/server.log")).useDelimiter("\\Z").next();
final String needle = "Report Process started";
int occurrences = 0;
int index = 0;
while (index < logdata.length() && (index = logdata.indexOf(needle, index)) >= 0) {
occurrences++;
index += needle.length();
}
You must check for any errors.
private static void printStream(InputStream in) throws IOException {
BufferedReader is = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}
}
public static void main(String args[]) {
try {
Runtime rt = Runtime.getRuntime();
String[] cmd = {"/bin/sh", "-c", "grep 'Report Process started' server.log|wc -l"};
Process proc = rt.exec(cmd);
printStream(proc.getInputStream());
System.out.println("Error : ");
printStream(proc.getErrorStream());
} catch (Exception ex) {
ex.printStackTrace();
}
}

Fetch and store output from a subprocess in Java

I'm working on something that requires me to start to subprocess(command prompt) and execute some commands on it. I need to fetch the output from the subprocess and store it in a file or String.
here's what I have done so far, and it doesn't work:
public static void main(String args[])
{
try
{
Runtime RT = Runtime.getRuntime();
String command = "cmd /c start javap java.lang.String";
File file = new File("write.txt");
Writer output = new BufferedWriter(new FileWriter(file));
BufferedReader br = new(BufferedReader(newInputStreamReader(RT.exec(command).getInputStream()));
String temp = br.readLine();
while(!temp.equals(null))
{
output.write(temp);
temp = br.readLine();
}
output.close();
RT.exec("exit");
}
catch(Exception e)
{
System.out.println(e);
}
}
Start changing this:
new(BufferedReader(newInputStreamReader(
To:
new BufferedReader(new InputStreamReader(
Compile and see if you still have the problem
edit
Also, there is a good reason why you shouldn't catch Exception, you also catch programming errors like a NullPointerException
while( !temp.equals(null)) { //Throws NullPointerExceptin when temp is null
Change it with:
while( temp != null ) { //!temp.equals(null)) {
Finally you don't have to "exit" since you're not inside the cmd really.
Corrected version
This version runs as you intend:
import java.io.*;
class Rt {
public static void main(String args[]) throws Exception {
Runtime RT = Runtime.getRuntime();
String command = "javap java.lang.String" ;
File file = new File("write.txt");
Writer output = new BufferedWriter(new FileWriter(file));
BufferedReader br = new BufferedReader(new InputStreamReader(RT.exec(command).getInputStream()));
String temp = br.readLine();
while( temp != null ) { //!temp.equals(null)) {
output.write(temp);
temp = br.readLine();
}
output.close();
//RT.exec("exit");
}
}
edit
Final remarks:
Since Java 1.5 the preferred way to invoke a command is using ProcessBuilder and it is better if you use an array of strings instead of a single string ( or varargs ).
When you're building your output you can get rid of the file object and pass the file name directly to the filewriter.
While reading the line you can assign and evaluate in the condition.
Java's coding conventions suggest to use the opening brace in the same like.
This would be my version of your code:
class Rt {
public static void main(String args[]) throws Exception {
Writer output = new BufferedWriter(new FileWriter ( "write.txt"));
InputStream in = new ProcessBuilder("javap", "java.lang.String").start().getInputStream();
BufferedReader br = new BufferedReader( new InputStreamReader(in));
String line = null;
while( ( line = br.readLine() ) != null ) {
output.write( line );
}
output.close();
}
}
It might need still some work, but I hope it helps you.
Here is an example which should work:
StringBuffer outStream = new StringBuffer();
StringBuffer errStream = new StringBuffer();
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = runtime.exec(command);
} catch (IOException ex) {
ex.printStackTrace();
return;
}
InputStream outIs = process.getInputStream();
MonitorOutputThread sout = new MonitorOutputThread(outIs, outStream);
sout.run();
InputStream errIs = process.getErrorStream();
MonitorOutputThread serr = new MonitorOutputThread(errIs, errStream);
serr.run();
while (sout.isAlive() || serr.isAlive()) {
try {
sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
// ignore
}
}
And the code for MonitorOutputThread
private class MonitorOutputThread extends Thread {
private final InputStream is;
private final StringBuffer output;
public MonitorOutputThread(InputStream is, StringBuffer output) {
this.is = is;
this.output = output;
}
#Override
public void run() {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
try {
while ((line = br.readLine()) != null) {
output.append(line);
output.append(LINE_SEPARATOR);
}
if (output.length() >= 1) {
char lastChar = output.charAt(output.length() - 1);
if (lastChar == '\n') {
output.deleteCharAt(output.length() - 1);
}
}
} catch (IOException ex) {
ex.printStackTrace();
return;
}
}
}
This should catch both the standard output and standard error of the command.
DevDaily has a simple example of how to work with Process class.
See the snippet:
import java.io.*;
public class JavaRunCommand {
public static void main(String args[]) {
String s = null;
try {
// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("ps -ef");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}
or even check this code I've writen some time ago

Once I have the name of a SQLServer, how do I list its databases in java?

I am trying to populate a drop down list of SQLServers on a network using the osql -L command through Java. The user will then choose a server and type in a username and password. I also need to populate another list with the databases on that server. Any ideas on how I can implement that using java? If possible, please give java code.
Thank you.
public class SQL implements ActionListener{
public static void main(String[] args) throws Exception{
String[] str = new String[] {"cmd.exe", "/c", "osql", "-L" };
Runtime rt = Runtime.getRuntime();
try{
Process p = rt.exec(str);
InputStream is =p.getInputStream();
InputStream err = p.getErrorStream();
InputStreamReader in = new InputStreamReader(is);
StringBuffer sb = new StringBuffer();
BufferedReader buff = new BufferedReader(in);
//clearing away white space and "Servers"
buff.readLine();
buff.readLine();
String line = buff.readLine();
JComboBox servers = new JComboBox();
while (line != null){
servers.addItem(line.trim());
line =buff.readLine();
}
SQL sql = new SQL();
servers.addActionListener(sql);
JOptionPane.showMessageDialog(null, servers);
}catch( Exception ex )
{
ex.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String ser = (String)cb.getSelectedItem();
}
}
This website helped a lot.
http://www.cyberciti.biz/faq/howto-ms-sql-list-tables-and-database/
public static void main(String[] args) {
String[] str = new String[] {"cmd.exe", "/c", "sqlcmd -U abc -P abc -q sp_databases"};
Runtime rt = Runtime.getRuntime();
try{
String ss = null;
Process p = rt.exec(str);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//obj.exec(ss);
System.out.println("Here is the standard output of the command:\n");
while ((ss = stdInput.readLine()) != null) {
System.out.println(ss);
}
System.out.println("Here is the standard error of the command (if any):\n");
while ((ss = stdError.readLine()) != null) {
System.out.println(ss);
}
}catch( Exception ex )
{
ex.printStackTrace();
}
}

Categories

Resources