I would like to write a Java program to control the Android emulator to do some testing, and now I have to take snapshots of the emulator when it is created and every time it has changes, so according to google, the command is like:
telnet localhost 5555
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Android Console: type 'help' for a list of commands
OK
avd snapshot save 1
OK
So basically two commands, the first is to open a telnet connection and then enter avd snapshot save x command to save the snapshot.
However using the command like this:
public static void main(String[] args) throws IOException{
int initScore = 1000;
int ID = 0;
// monitor the log, check if a new activity is reached.
// if so, take a snapshot of the current activity and save it to the snapshot folder.
String cmd1 = "telnet localhost " + 5555;
// the static port 5557 should change to this.getVM_consolePort();
String cmd2 = "avd snapshot save " + ID;
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", cmd1, cmd2);
Process p = pb.start();
// read the process output
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
}
can only run the first command (which is to open telnet connection).
So could anyone tell me how to interact with a opened connection or enter command to another process in Java?
Here's an example using grep:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws IOException {
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", "grep foo");
Process p = pb.start();
BufferedReader stdOut = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdErr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
Writer stdIn = new OutputStreamWriter(p.getOutputStream());
stdIn.write("foo1\nbar\nfoo2\n");
stdIn.close();
String s = null;
while ((s = stdOut.readLine()) != null) {
System.out.println(s);
}
while ((s = stdErr.readLine()) != null) {
System.out.println(s);
}
}
}
I renamed stdIn to stdOut, so they are named from the point of view of the process you're running.
I read from stderr, so that you can see any problems.
Actually I have tried this before like the code below:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
public class Main {
public static void main(String[] args) throws IOException {
// int initScore = 1000;
int ID = 0;
Process p = Runtime.getRuntime().exec("telnet localhost 5555");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedWriter stdIn = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
String line;
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
if (line.contains("OK")){
break;
}
}
stdIn.write("avd snapshot save " + ID);
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
}
}
}
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Android Console: type 'help' for a list of commands
OK
I think the reason is that the telnet created a new shell and the writer is writing to the old shell, therefore it is not working, so I am looking for a solution to enter the new command into the new shell.
Related
I am trying to call python within my java code. However I found that if I import numpy in my python code, this is my java code
Process pcs = Runtime.getRuntime().exec(cmd);
String result = null;
BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println("\nExecuting python script file now.");
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
result = lineStr;
}
br.close();
in.close();
System.out.println("done!");
System.out.println(result);
This is my python code:
import sys
import os
import numpy as np
a = sys.argv[1]
b = sys.argv[2]
print("hello world!")
print("%s * %s = %s"%(a,b,int(a)*int(b)))
Results if I don't include "import numpy as np":
10 * 11 = 110
Results if include "import numpy as np":
null
Any intuitive explanation?
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Hello{
public static void main(String[] args)throws java.io.IOException{
Process pcs=Runtime.getRuntime().exec("python test.py 8 5");// in linux or unix use python3 or python
String result=null;
BufferedInputStream in = new BufferedInputStream(pcs.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println("\nExecuting python script file now.");
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
result = lineStr;
}
br.close();
in.close();
System.out.println("done!");
System.out.println(result);
}
}
java code
compile:
javac Hello.java
run:
java Hello
#test.py
import sys
import os
import numpy as np
a = sys.argv[1]
b = sys.argv[2]
print("hello world!")
print("%s * %s = %s"%(a,b,int(a)*int(b)))
Have you got the right PYTHONPATH setup in your application? When you have import numpy as np in your code, you may be receiving back empty STDOUT and an ModuleNotFoundError in STDERR. You can confirm by extracting STDERR - or check with this code:
Launch.exe(cmd);
where Launch.java is:
public class Launch
{
/** Launch using FILE redirects */
public static int exec(String[] cmd) throws InterruptedException, IOException
{
System.out.println("exec "+Arrays.toString(cmd));
Path tmpdir = Path.of(System.getProperty("java.io.tmpdir"));
ProcessBuilder pb = new ProcessBuilder(cmd);
Path out = tmpdir.resolve(cmd[0]+"-stdout.log");
Path err = tmpdir.resolve(cmd[0]+"-stderr.log");
pb.redirectError(out.toFile());
pb.redirectOutput(err.toFile());
Process p = pb.start();
int rc = p.waitFor();
System.out.println("Exit "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****")
+" STDOUT \""+Files.readString(out)+'"'
+" STDERR \""+Files.readString(err)+'"');
System.out.println();
return rc;
}
}
The fix for using numpy should be to access ProcessBuilder pb.environment() and set your PYTHONPATH for the subprocess before calling start()
I used the following code to execute simple OS command on Windows:
public class Ping {
public static void main(String[] args) throws IOException {
String command = "ping google.com";
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
System.out.println();
System.out.println("Finished");
How to modify the code to insert multiple commands instead of one, so let us say I want to ping google.com, and then ping yahoo.com after that.
I tried to create array string like:
String [] command = {"ping google.com", "ping yahoo.com"};
However, this showed me an error.
I appreciate your help on this.
Use a loop:
String [] commands = {"ping google.com", "ping yahoo.com"};
for(String command: commands) {
Process process = Runtime.getRuntime().exec(command);
//more stuff
}
I am trying to view the temperature table for my CPU on my Linux machine with Java. This bit of code will display the shell output for other commands, ls, cat file, but will not display watch sensors as it returns an interactive output. Is there a way I can convert it to plain text somehow?
Error: [/usr/bin/watch, sensors]
Error opening terminal: unknown.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class tempapp{
public static void main (String args[]) throws IOException, InterruptedException {
//build command
List<String> commands = new ArrayList<String>();
commands.add("/usr/bin/watch");
//args
commands.add("sensors");
System.out.println(commands);
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/ethano"));
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null, previous = null;
while ((line = br.readLine()) != null)
if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
System.out.println(line);
}
//Check result
if (process.waitFor() == 0){
System.out.println("\n success");
System.exit(0);
}
//weird termination
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
All that watch does is call the command it is given (sensors in this case) once every two seconds. You can simply have your application emulate this behaviour by calling /usr/bin/sensors in a for-loop once every two seconds (or however many times you need), therefore omitting the need to read interactive shell output.
I wrote a Java program which executes a PowerShell Command. Here is my code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PowerShellCommand {
public static void main(String[] args) throws IOException {
String command = "powershell.exe your command";
// Getting the version
String command = "powershell.exe $PSVersionTable.PSVersion";
// Executing the command
Process powerShellProcess = Runtime.getRuntime().exec(command);
// Getting the results
powerShellProcess.getOutputStream().close();
String line;
System.out.println("Standard Output:");
BufferedReader stdout = new BufferedReader(new InputStreamReader(
powerShellProcess.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
System.out.println("Standard Error:");
BufferedReader stderr = new BufferedReader(new InputStreamReader(
powerShellProcess.getErrorStream()));
while ((line = stderr.readLine()) != null) {
System.out.println(line);
}
stderr.close();
System.out.println("Done");
}
}
What I want to do is: instead of executing a command in a local PowerShell I want to make the code execute a command in the Windows Server PowerShell which is running on VMware? How should I modify the code to do so?
Have PowerShell invoke the command on the remote host:
String server = "remotehost";
String command = "powershell.exe -Command \"&{Invoke-Command -Computer " +
server + " -ScriptBlock {$PSVersionTable.PSVersion}}\"";
The remote host needs to have PSRemoting enabled for this to work.
I am trying to execute some Linux commands from Java using redirection (>&) and pipes (|). How can Java invoke csh or bash commands?
I tried to use this:
Process p = Runtime.getRuntime().exec("shell command");
But it's not compatible with redirections or pipes.
exec does not execute a command in your shell
try
Process p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});
instead.
EDIT::
I don't have csh on my system so I used bash instead. The following worked for me
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"});
Use ProcessBuilder to separate commands and arguments instead of spaces. This should work regardless of shell used:
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(final String[] args) throws IOException, InterruptedException {
//Build command
List<String> commands = new ArrayList<String>();
commands.add("/bin/cat");
//Add arguments
commands.add("/home/narek/pk.txt");
System.out.println(commands);
//Run macro on target
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/narek"));
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null, previous = null;
while ((line = br.readLine()) != null)
if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
System.out.println(line);
}
//Check result
if (process.waitFor() == 0) {
System.out.println("Success!");
System.exit(0);
}
//Abnormal termination: Log command parameters and output and throw ExecutionException
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
Building on #Tim's example to make a self-contained method:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Shell {
/** Returns null if it failed for some reason.
*/
public static ArrayList<String> command(final String cmdline,
final String directory) {
try {
Process process =
new ProcessBuilder(new String[] {"bash", "-c", cmdline})
.redirectErrorStream(true)
.directory(new File(directory))
.start();
ArrayList<String> output = new ArrayList<String>();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = null;
while ( (line = br.readLine()) != null )
output.add(line);
//There should really be a timeout here.
if (0 != process.waitFor())
return null;
return output;
} catch (Exception e) {
//Warning: doing this is no good in high quality applications.
//Instead, present appropriate error messages to the user.
//But it's perfectly fine for prototyping.
return null;
}
}
public static void main(String[] args) {
test("which bash");
test("find . -type f -printf '%T#\\\\t%p\\\\n' "
+ "| sort -n | cut -f 2- | "
+ "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt");
}
static void test(String cmdline) {
ArrayList<String> output = command(cmdline, ".");
if (null == output)
System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline);
else
for (String line : output)
System.out.println(line);
}
}
(The test example is a command that lists all files in a directory and its subdirectories, recursively, in chronological order.)
By the way, if somebody can tell me why I need four and eight backslashes there, instead of two and four, I can learn something. There is one more level of unescaping happening than what I am counting.
Edit: Just tried this same code on Linux, and there it turns out that I need half as many backslashes in the test command! (That is: the expected number of two and four.) Now it's no longer just weird, it's a portability problem.