Im trying to implement a scenario using threads to execute concurrent commands on a server. The commands just send requests to a service running on the server and in return get the required output.
The commands are generated based on reading a file, whose path the user gives as input to the application.
Based every line that is in the aforementioned file, a command is generated and run on the server.
Im running these commands by invoking an instance of the bash process on the linux box.
A brief pseudo implementation of the above is as follows.
Class A {
public static void main(blah blah)
//take all user inputs, one of which is the location of the file that is to be read.
try {
Runnable runnable =new bckwork(//pass the inputs taken from the user//);
thread = new Thread(runnable);
thread.start();
}
catch (Exception e) {
e.printStackTrace();
}
}
and the class that does the actual work --
public class bckwork implements Runnable {
bckwork(//takes in all input that the other class passes on) {
//assigns to local variables
}
public void run() {
// TODO Auto-generated method stub
try{
Process proc = null;
proc = Runtime.getRuntime().exec("/bin/bash", null, dir);
if (proc != null) {
String cmd="";
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
BufferedReader br = new BufferedReader(blah blah blah);//reads every line in the file that was passed onto this class.
String strLine;
while ((strLine = br.readLine()) != null) {
cmd=blah+blah+blah//the command is generated,whatever is read off the file is a part of the command.
out.println(cmd);
String line;
while ((line = in.readLine()).length()>1) {
line = in.readLine();
System.out.println(line);
proc.waitFor();
in.close();
out.close();
proc.destroy();
}
}
}
}catch(Exception e){}
}
}
The problem with the above pieces of code is that they run only for the first line in the file that is being read and then the executions goes into some kind of deadlock. Im guessing that the next line from the file is never being read.My intention was to kick of a thread for every line that was being read or essentially every command that was being constructed.
Any pointers on how this bug can be corrected would be greatly appreciated.
In
while ((line = in.readLine()).length()>1)
in.readLine waits for enter and freezes the entire application.
Related
I have a java program that opens up a .exe file. What i want to do is,
1)Run the .exe file when the java program is executed - Runs perfectly
2) When running the same code again, I want to reopen the previously executed exe.I dont want the .exe file to execute again.
EDIT:
Is there a way to do the above? My only concern is the 2nd question. I have made the 1st question to work
On the request of Luffy. This is the code that i had used to get the list of running process and check whether a particular exe is running or not. Hope it helps for others.
try
{
String line;
String pidInfo = "";
Process proc = Runtime.getRuntime().exec("wmic.exe");
BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
OutputStreamWriter oStream = new OutputStreamWriter(proc.getOutputStream());
oStream .write("process where name='test.exe'");
oStream .flush();
oStream .close();
while ((line = input.readLine()) != null) {
pidInfo+=line;
}
input.close();
if(pidInfo.contains("test.exe"))
{
System.out.println("exe already running");
}
else
{
System.out.println("exe not running");
Process p = Runtime.getRuntime().exec(new String[] {"C:\\Program Files (x86)\\ToTestEXE\\test.exe"});
}
}
catch (IOException e)
{
e.printStackTrace();
}
I am writing a Java application in IntelliJ IDE. The application used Rserve package to connect to R and perform some functions. When I want to run my code for the first time, I have to launch R in the command line and start the Rserve as a daemon, which looks something like this:
R
library(Rserve)
Rserve()
After doing this, I can easily access all the function in R without any errors. However, since this Java code would be bundled as an executable file, so is there a way that Rserve() is invoked automatically as soon as the code is run so that I have to skip this manual step of starting Rserve using the command line?
Here is the code for the Class I wrote to get Rserve working from Java
public class InvokeRserve {
public static void invoke() {
String s;
try {
// run the Unix ""R CMD RServe --vanilla"" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("R CMD RServe --vanilla");
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);
}
}
}
I know this question has been asked a long back . I think You have the answer. But the below answer may help others. That's why I am posting my answer.
answer:- Instead of going again and again to the R console to start Rserve. One thing you can do is you can write a java program to start Rserve.
Below code you can use in a java program to start Rserve.
https://www.sitepoint.com/community/t/call-linux-command-from-java-application/3751. This is the link where you will get the code to run a linux command from java.I have changed the command only and posting below.
package javaapplication13;
import java.io.*;
public class linux_java {
public static void main(String[] args) {
try {
String command ="R CMD Rserve";
BufferedWriter out = new BufferedWriter(new FileWriter(
new File(
"/home/jayshree/Desktop/testqavhourly.tab"), true));
final Process process = Runtime.getRuntime().exec(command);
BufferedReader buf = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line;
while ((line = buf.readLine()) != null) {
out.write(line);
out.newLine();
}
buf.close();
out.close();
int returnCode = process.waitFor();
System.out.println("Return code = " + returnCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'm writing a Java program with multiple threads. One of the threads is responsible for reading lines from the standard input and parsing them.
Everything works well when running normally, but when the program is run in the background (in Linux) using:
$ java -jar my_jar_file &
my program hangs (at least until brought to foreground).
When running in the background I don't really need the standard input, but I also don't want my program to hang.
I searched for a way to programatically determine if the process is running in the background but could not find it.
Here's the code that reads from standard input:
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = null;
try {
while ((line = br.readLine()) != null) {
parseInputLine(line, br);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
As far as I can tell, the program hangs when it reaches the br.readLine() command.
I would guess the reader is blocking waiting for input you might be able to pipe in your input from the command line
readLine is a blocking call. So it is obviously waiting for input. If you want it to run in the background, then pass to it input from a file like this
java TakeInput < test.txt &
This where the class is as below and test.txt also shown below:
public class TakeInput
{
public static void main(String[] args)
{
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = null;
try {
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
write a text file as test.txt which has say
test1
test2
test3
I don't believe a Java program can determine if it's running in foreground or background.
I tried System.console(), with the following results:
Linux - returns null if stdin is redirected from a file, independent of foreground/background status
Windows - same thing;
Cygwin - seems to always return null
I suspect you will need to invoke the program from the command line as
java -cp ... ClassName < /dev/null
Try using .ready() function.
try {
if (stdError.ready())
{
while((line= stdError.readLine()) != null){
logger.error(line);
}
}
}
Do the same for the stdout.
To understand the situation, I try to describe what I'm trying to achieve:
I would like to create a java program that starts another java program (a minecraft server), monitors it's output, and sends commands to it's input accordingly.
I was able to start the jar program from my code, and I was also able to write an output listener for it, that currently only prints the jar program's output to the console.
The jar program I'm running from my code has a gui with a text output panel, where it shows messages, and an input field (textarea) where I can give commands. My problem is that when I start my code and it starts the program everything works fine until I want to write directly into the program's input field. If I type any letter into the input field, the gui freezes.
What do I wrong?
Here's my code:
public static void main(String[] args) {
try {
System.out.println("Starting.");
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java -jar \"D:\\Program Files\\mc\\minecraft_server.jar\"");
// output both stdout and stderr data from proc to stdout of this process
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream());
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream());
errorGobbler.start();
outputGobbler.start();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
The output reader:
public class StreamGobbler extends Thread {
InputStream is;
// reads everything from is until empty.
StreamGobbler(InputStream is) {
this.is = is;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
System.out.println(line);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Thanks in advance! :)
First of all, instead of using the stream gobbler, just inherit the process's io:
final ProcessBuilder p1 = new ProcessBuilder(command).inheritIO();
p1.start();
If you don't care about stdin/out, use this to direct everything to NUL (windows version of /dev/null):
p1.redirectInput(Redirect.from(new File("NUL"))).redirectOutput(Redirect.to(new File("NUL")))
.redirectError(Redirect.to(new File("NUL")));
Does the program still crash?
Can someone help me in the below scenario,
I need to call a perl script from my java code. The perl script is an interactive code, which gets the input from the user during its execution and continues further to end. So, the example I have used is, the perl script when executed asks for the age by printing in the console "How old are you?", when the user enter some value say '26'. Then it prints "WOW! You are 26 years old!".
When I tried calling this script from my java code, the process waits till I give the value as 26 in the outputstream, while in the inputstream there is no value. Then finally when again I read the inputstream, i get the entire output of the script together. So, here can't I make it interactive?
I have went through many forums and blogs, but couldn't locate any, which exactly target my requirement.
Here is the java code
import java.io.*;
public class InvokePerlScript {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Process process;
try
{
process = Runtime.getRuntime().exec("cmd /c perl D:\\sudarsan\\eclips~1\\FirstProject\\Command.pl");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
out.write("23");
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
process.waitFor();
if(process.exitValue() == 0)
{
System.out.println("Command Successful");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
else
{
System.out.println("Command Failure");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
catch(Exception e)
{
System.out.println("Exception: "+ e.toString());
}
}
}
Perl code is as below
$| = 1;
print "How old are you? \n";
$age = <>;
print "WOW! You are $age years old!";
Thanks in advance,
Sudarsan
Are you calling flush() on the OutputStream in Java after writing the values? If you don't, there's a good chance they'll just be held in the stream's buffer within the Java process, and so never make it to Perl (with the result that both processes end up waiting for the other's IO.)
(Depending on the implementation of the stream this may or may not be necessary, but it certainly wouldn't hurt - and I've been bitten by this in the past. Usually one doesn't need to be as careful, since flushing happens implicitly when close() is called, but here you can't close the stream after you've finished writing.)
It looks like you're trying to read a full line in this code:
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
...
However, in your perl code, you are not printing an endline character, so readLine never returns (as per the documentation).