firing a command through terminal in Ubuntu using Java Runtime.exec - java

This is fairly simple in Windows, but a little tricky in Linux. I am using
Runtime.getRuntime().exec(new String[] { "/bin/bash", "-c", "java -classpath /home/4/byz/Orc" });
where Orc is the class file with a main function.
But nothing happens. Are there any settings ? Am I doing something wrong ?
I wish the java program to run in the terminal.
EDIT
Here is the solution:
String[] cmdArray = {"gnome-terminal","java -classpath /home/r/byz/ Orchestrator"};
try {
Runtime.getRuntime().exec(cmdArray);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
So basically, we have to use gnome-terminal ..

I believe this is already resolved, however I'll post an answer:
How to Run:
executeCommand(new String[]{"/bin/bash", "-c", "java -classpath /home/4/byz/Orc"});
Method:
public String executeCommand(String[] cmd) {
StringBuffer theRun = null;
try {
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
theRun = output.append(buffer, 0, read);
}
reader.close();
process.waitFor();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return theRun.toString().trim();
}
Let me know if this helps!

Related

Obtaining process CPU usage

I have a program that loads a text file holding some information and based on that information it runs multiple thread. Each thread is a process. Here is my code:
public class runMultiClient {
public static void main(String[] args){
List<Process> PRlist = new ArrayList<Process>();
List<String[]> commandsList = new ArrayList<String[]>();
boolean running = true;
if (args.length == 2 && args[0].matches("-f")){
String dir = System.getProperty("user.dir");
String path = dir + "/" + args[1];
FileReader fr;
try {
fr = new FileReader(path);
BufferedReader bf = new BufferedReader(fr);
String line = "";
while ((line = bf.readLine()) != null){
String[] tk = line.split(" ");
String[] cmd = {"java", "-jar", "Client.jar", "-a", tk[0], "-p", tk[1],
"-u", tk[2], "-pw", tk[3], "-m", tk[4], "-s", tk[5]};
Process pr = new ProcessBuilder().inheritIO().command(cmd).start();
PRlist.add(pr);
commandsList.add(cmd);
System.out.println(tk[4] + " streaming process is established.");
}
}
catch (FileNotFoundException ex) {ex.printStackTrace();}
catch (IOException ex) {ex.printStackTrace();}
} else {
System.out.println("No stream file was specified.");
}
}}
Inside my Client.jar file, i have a variable that monitors the cpu load of that class:
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
cpuLoad = osBean.getProcessCpuLoad();
Is there any way i can reach that variable from the runMultiClient class?
If not, is there any way of using the OperatingSystemMXBean on the running process?
I have tried pr.getClass(), but it got me nowhere.
Any help would be appreciated.
Option #1: Add agent library and expose JMX over HTTP
You can bundle Jolokia agent with your monitored application (another similar thing is SimpleJMX. It exposes JMX beans over http/json so this works for interacting with JMX from other languages like python (and super comfy when troubleshooting from command like). After that you can access mbeans of your interest via apache http client or the like.
Option #2: JMX client
allow remote connections by adding the following params when starting your monitored application:
-Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
Then you should be able to access the mbeans by jconsole and hand written JMX client code, like in the tutorial
Not sure if you need to call ProcessBuilder().inheritIO() for some other requirement, but if not, you could start a daemon thread in your Client.jar process that periodically writes the cpu load to System.out. Then your runMultiClient thread[s] could read those from the InputStream representing the process's System.out. Or, have the thread accept commands and print accordingly. Rough example:
Run this in the spawned Client.jar:
public static void startCmdListener() {
try {
Thread t = new Thread("CmdListener") {
BufferedReader br = null;
InputStreamReader isr = null;
final OperatingSystemMXBean os = (OperatingSystemMXBean) ManagementFactoryHelper.getOperatingSystemMXBean();
public void run() {
try {
isr = new InputStreamReader(System.in);
br = new BufferedReader(isr);
} catch (Exception ex) {
ex.printStackTrace(System.err);
return;
}
try {
String cmd = null;
while(true) {
cmd = br.readLine();
if("cpu".equalsIgnoreCase(cmd)) { // cpu command, print the process load
System.out.println(os.getProcessCpuLoad());
} else if("exit".equalsIgnoreCase(cmd)) { // exit command, break
break;
}
}
} catch (Exception ex) {
ex.printStackTrace(System.err);
return;
}
}
};
t.setDaemon(true);
t.start();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
Run this in the runMultiClient to get the cpu load:
public static double getCpu(OutputStream processIn, InputStream processOut) {
PrintStream ps = null;
BufferedReader br = null;
InputStreamReader isr = null;
try {
ps = new PrintStream(processIn);
isr = new InputStreamReader(processOut);
br = new BufferedReader(isr);
ps.println("cpu");
ps.flush();
return Double.parseDouble(br.readLine());
} catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
if(ps!=null) try { ps.close(); } catch (Exception x) {}
if(br!=null) try { br.close(); } catch (Exception x) {}
if(isr!=null) try { isr.close(); } catch (Exception x) {}
}
}

Detecting terminal command errors in Java

In my Java application I am using the exec() command to call a terminal function:
p = Runtime.getRuntime().exec(command);
p.waitFor();
The call uses the zip and unzip calls. Originally I call:
zip -P password -r encrypted.zip folderIWantToZip
When I call the unzip function through java, I specify the password as the method parameter. If the correct password is specified then the call should unzip the encrypted folder:
unzip -P password encrypted.zip
I want a way to find out if the password entered is incorrect. For example, if password is correct, then the call will correctly unzip the zip file. But I notice that no exception is thrown for an incorrect password. How can I determine this?
You could read the process's ErrorStream and InputStream to determine the process output. Sample code given below
public static void main(String[] args) {
try {
String command = "zip -P password -r encrypted.zip folderIWantToZip";
Process p = Runtime.getRuntime().exec(command);
InputStream is = p.getInputStream();
int waitFor = p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
System.out.println("line:" + line);
}
is = p.getErrorStream();
reader = new BufferedReader(new InputStreamReader(is));
while ((line = reader.readLine()) != null) {
System.out.println("ErrorStream:line: " + line);
}
System.out.println("waitFor:" + waitFor);
System.out.println("exitValue:" + p.exitValue());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You could use the exitcode to validate the process status as well but it is specific to to program. Normally zero means successfully terminated otherwise abnormal termination.
As per my comment, first thing I would do would be to capture the Process's InputStream and ErrorStream via getInputStream() and getErrorStream(), but especially the latter, the ErrorStream, and check to see what it outputs if the input is in error. Note that these would have to be done in their own thread, else you'll tie up your program. I usually use some type of StreamGobbler class for this. Also, don't ignore the int returned by p.waitFor().
e.g.,
ProcessBuilder pBuilder = new ProcessBuilder(COMMAND);
Process process = null;
try {
process = pBuilder.start();
new Thread(new StreamGobbler("Input", process.getInputStream())).start();
new Thread(new StreamGobbler("Error", process.getErrorStream())).start();
int exitValue = process.waitFor();
System.out.println("Exit Value: " + exitValue);
process.destroy();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (process != null) {
process.destroy();
}
}
And:
class StreamGobbler implements Runnable {
private String name;
private Scanner scanner;
public StreamGobbler(String name, InputStream inputStream) {
this.name = name;
scanner = new Scanner(inputStream);
}
#Override
public void run() {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(name + ": " + line); // or better, log the line
}
scanner.close();
}
}

Java: Redirecting output of .bat file in other text file using exec() method?

Java is new to me.
I am executing a batch file using Runtime.getRuntime.exec(filename.bat) and this batch file executes a commandant encrypt.password -Dvalue=somevalue>log.txt and redirects its output to a log.txt file.
Problem that I am facing is batch file is working fine if I run it manually however when program executes it ,it just creates blank 'log.txt'
Content of mybat.bat batch file is as below:
cd/
c:
cd c:/ant_builds/thinclient
ant encrypt.password -Dvalue=someValue >C:/log.txt
Java code is as below:
Process p=Runtime.getRuntime.exec("C:\mybat.bat");
p.waitFor();
It seems that after creating the log file,meantime command is executing control comes out from process.
I have read almost 50 threads here however did not get the solution. Please help me out.
Use ProcessBuilder to create your process and call redirectOutput(File) to redirect and append output to a file.
Try this code:
public class Test {
ProcessBuilder builder;
Path log;
public Test() {
try
{
log = Paths.get("C:\\log.txt");
if (!Files.exists(log))
{
Files.createFile(log);
}
builder = new ProcessBuilder("ant", "encrypt.password", "-Dvalue=someValue");
builder.directory(Paths.get("C:\\ant_builds\\thinclient").toFile());
builder.redirectOutput(ProcessBuilder.Redirect.appendTo(log.toFile()));
builder.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
new Test();
}
}
For jdk 1.6 or less, use the following code:
public class Test {
ProcessBuilder builder;
Path log;
Process process;
BufferedReader br;
PrintWriter pw;
Charset charset = Charset.forName("UTF-8");
public Test() {
try {
log = new File("C:\\log.txt");
if (!log.exists()) {
log.createNewFile();
}
builder = new ProcessBuilder("ant", "encrypt.password","-Dvalue=someValue");
builder.directory(new File("C:\\ant_builds\\thinclient"));
builder.redirectErrorStream(true);
process = builder.start();
br = new BufferedReader(new InputStreamReader(process.getInputStream(),charset));
pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(log, true), charset));
(new Thread() {
public void run() {
try {
while (process.isAlive()) {
String s = null;
while ((s = br.readLine()) != null) {
pw.print(s);
pw.flush();
}
}
br.close();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Test();
}
}
I'm not sure about the order and list of ProcessBuilder arguments so try to play with them to get your code working.
You can also read commands from a common file and redirect output and erros to a sepearate files. Redirect.appendTo is to avoid the process from overiting the existing logs.
Try this code:
try {
File commands = new File("D:/Sample/Commands.txt");
File output = new File("D:/Sample/Output.txt");
File errors = new File("D:/Sample/ErrorsLog.txt");
ProcessBuilder pb = new ProcessBuilder("cmd");
System.out.println(pb.redirectInput());
System.out.println(pb.redirectOutput());
System.out.println(pb.redirectError());
pb.redirectInput(commands);
pb.redirectError(Redirect.appendTo(errors));
pb.redirectOutput(Redirect.appendTo(output));
pb.redirectInput();
pb.redirectOutput();
pb.redirectError();
pb.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

executing **kill -9 <PID>** command through java is not working

I am executing the below command to kill a process, but its not killing any process.
Command I tried: #kill -9 "2319"
But at the same time when I execute the same command in command prompt its working fine.
private void killProcess()
{
InputStream errorStream = null;
final String taskKill = isWindows() ? InstallerConstants.WIN_TASKKILL : InstallerConstants.LIN_TASKKILL;
try
{
Process process = null;
final String killCMD = taskKill+"\""+getGuiProcess()+"\"";\\kill -9 "2319"
process = runTime.exec(killCMD);
errorStream = process.getErrorStream();
bufferedReader = new BufferedReader(new InputStreamReader(errorStream));
String error = "";
while(bufferedReader.readLine() != null)
{
error = bufferedReader.readLine();
}
if(!(error==null || "".equals(error)))
{
logger.error(error);
}
}
catch (IOException ioException) {
logger.error(ioException.getMessage(), ioException);
}
finally
{
try
{
if(bufferedReader!=null)
{
bufferedReader.close();
}
if(errorStream!=null)
{
errorStream.close();
}
}
catch (IOException ioException) {
logger.error(ioException.getMessage(), ioException);
}
}
}
Please help to overcome this problem.
You need to specify the absolute path to the kill command
/bin/kill may be?
$ whereis kill //output will show you where kill command is.
do you get any errors btw?

Windows cmd-output (Java)

I've found this topic, but the code doesn't work for me... Return Windows cmd text from Java?
After pressing a button I want to execute a batch-file, for testing purposes it's just the ipconfig-command.
The cmd-output should be written into a JTextFiled, but all I get is no text...
Here the code for writing it into the JTextField:
btnLock.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String g = "";
try {
Runtime.getRuntime().exec(new String[] {"ipconfig", g});
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Process p = null;
try {
p = Runtime.getRuntime().exec(new String[] {"ipconfig", g});
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
InputStream s = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(s));
String temp;
try {
while ((temp = in.readLine()) != null)
{
System.out.println(temp);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
btnLock.setBounds(10, 68, 89, 23);
contentPane.add(btnLock);
So what do I do wrong?
It's my first project with cmd-input, so please don't get mad cause of silly mistakes I made. ;)
Thx
Try the exec command that just takes a String parameter. The following test code worked on my system (though I was only printing to console, not to textfield):
BufferedReader in = null;
try{
Process p = Runtime.getRuntime().exec("ipconfig");
InputStream s = p.getInputStream();
in = new BufferedReader(new InputStreamReader(s));
String temp;
while ((temp = in.readLine()) != null) {
System.out.println(temp);
}
} catch (Exception e){
e.printStackTrace();
} finally {
if (in != null) in.close();
}
Also your code in the original post is also using a System.out.println. As far as I'm aware, you can't print to a JTextField using System.out.println.... You'd have to use the setText method.
If I run
ipconfig ""
I get
** Error: unrecognized or incomplete command line.**
You can only run from Java, commands which work on the command line.
BTW: If you are looking for errors, you need to read the error stream.
I would Runtime.getRuntime().exec(new String[] {"ipconfig > temp.txt"}); and then just read it as a text file using a BufferedReader.
I hope this helps.

Categories