On Android, unable to run procrank from java app - java

I would like to have an app (service) that runs in the background, running procrank on a timer & writing the output to a file on the sdcard. Essentially I want to execute "/system/xbin/procrank > /sdcard/procrank.txt". During the wait time I do some [minimal] processing of the file, so I can overwrite it the next time it runs.
This is on a test phone, so it can be considered as "rooted". I have tried many different ways to run the command without success.
When I use this:
String[] cmd = { "/system/xbin/procrank > /sdcard/procrank_result.txt" };
Process process = new ProcessBuilder()
.command(cmd)
.redirectErrorStream(true)
.start();
BufferedReader in = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = in.readLine()) != null) {
Log.i(Constants.TAG, "Line=" + line);
}
process.waitFor();
I get an IOException:
09-28 02:48:16.307: W/System.err(9579): java.io.IOException: Error running exec(). Command: [/system/xbin/procrank > /sdcard/procrank_result.txt] Working Directory: null Environment: [ANDROID_ROOT=/system, EMULATED_STORAGE_SOURCE=/mnt/shell/emulated, LOOP_MOUNTPOINT=/mnt/obb, ...
So I thought I would just issue the command and read the output:
String[] cmd = { "/system/xbin/procrank" };
Process process = new ProcessBuilder()
.command(cmd)
.redirectErrorStream(true)
.start();
BufferedReader in = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = in.readLine()) != null) {
Log.i(Constants.TAG, "Line=" + line);
}
process.waitFor();
but I get an error from procrank that I don't understand:
Line=Error creating kernel interface -- does this kernel have pagemap?
Can anyone help me with this?
Also, I have tried many different ways to issue the command, so another variation of using process from getRuntime().exec probably won't work unless it's different from the many other solutions here on StackOverflow.
Yes, my sdcard is writable and /sdcard is equivalent to . I can issue the command from adb shell and it creates the file.
Would I have more luck with trying to connect via socket to localhost and then issuing the command?

Too old a question but if anyone encounters this: I too hit into this issue. Doing the following fixed this for me:
adb wait-for-devices root
adb wait-for-devices remount
adb shell procrank

This appears to be a problem with the build on the phone and perhaps something else.
I don't know how to close this question. Can I close it?

Related

Java Process Builder runs ffmpeg commands very slowly

I'm trying to run ffmpeg in Java using ProcessBuilder. I'm on Windows. It works fine. But not sure why it's much slower than when I just run the same command in command prompt or PowerShell.
Why is it? Is there any ways to increase the speed?
processBuilder.command("C:\\Windows\\System32\\cmd.exe", "/c","ffmpeg.exe", "-y", "-i", video,"-vf","scale=720:-1","out.mp4");
processBuilder.redirectErrorStream(true);
try {
process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line="";
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
System.err.println("Error in processBuilder. ");
}
You have two starts, delete the first or the redirect will not work:
process = processBuilder.start();
If your sub-process is quite verbose the problem may simply be System.out.println() as multiple line output to some Windows cmd / terminals can be exceptionally slow. You can verify if this is the case by commenting out the print, or capture to File based output before start:
processBuilder.redirectOutput(new File("stdout.log"));
Don't forget to add status check at the end and cross check rc with ffmpeg documentation:
int rc = process.waitFor();

how can I execute "java" command by java code?

I'm trying to run a multi-agent system using JADE by code.
Usually, I can run the jade system by command line using the following command:
java jade.Boot -gui
It also works well using Netbeans IDE by changing the project properties and pointing the run configuration to the jade.Boot class.
My problem is: I want to run this system by java code... let's say, when a user clicks a button, and as far as I know, this command specified above should work using the following code:
Process p=null;
try {
p = Runtime.getRuntime().exec("java jade.Boot -gui;");
}
catch (IOException ex) {
Logger.getLogger(SimulationCreator.class.getName()).log(Level.SEVERE, null, ex);
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s;
try {
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
} catch (IOException ex) {
Logger.getLogger(SimulationCreator.class.getName()).log(Level.SEVERE, null, ex);
}
But I'm getting nothing, neither the JADE system is running nor I'm getting any error.
What am I missing ?
P.S.: I'm working on ubuntu 20.0.
P.S.: running other commands by code like "ps -aux" works very well!
Your problem may be a difference between PATH of the current running VM, compared the shell (bash etc) you use and implicit passing of CLASSPATH. Check the location of java which which java in the shell that works and try using in your exec.
Also you won't see all issues when running as you don't access the error stream at same time as the output stream, changing to ProcessBuilder allows easier debugging as you can redirect the out/err streams to a file. But if JADE runs for a long time or produces a lot of output you should consumer STDOUT+ERR in background threads.
Try this in jshell:
String[] cmd = new String[]{"java", "jade.Boot", "-gui"};
ProcessBuilder pb = new ProcessBuilder(cmd);
File fileOut = new File("stdout.log");
File fileErr = new File("stderr.log");
pb.redirectError(fileErr);
pb.redirectOutput(fileOut);
Process p = pb.start();
int rc = p.waitFor();
String stdout = Files.readString(fileOut.toPath());
String stderr = Files.readString(fileErr.toPath());
System.out.println("Exit : "+rc +' '+(rc == 0 ? "OK":"**** ERROR ****"));
System.out.println("STDOUT : "+stdout);
System.out.println("STDERR : "+stderr);

How to I exit a while loop after starting a process in Java?

Just found this post (and found the code which I'm also pasting below):
java runtime.getruntime() getting output from executing a command line program
My question is, how do I kill the process? It seems that the code blocks in the while loop. I've tried several options like using a boolean, running all the code in a separate thread and stuff like this, but without any success.
I just want to start an Android emulator and kill it whenever I want.
Runtime rt = Runtime.getRuntime();
String[] commands = {"emulator", "-avd", "jenkins",
"-scale", "96dpi", "-dpi-device", "100"};
Process proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
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);
}
Okay.
Use below code to get The Process ID of that current running thread or Process.
String processName =java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
String ProcessID = processName.split("#")[0];//Process Id
Use that Process ID to kill that Process in your CPU.
I think for that purpose you may wish to write any other trigger or any condition in While loop.

Execute Command not work in Java

Execute Command worked well in Terminal, but not in Java code.
String cmd = "find -name javax.jar";
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null)
{
System.out.println("" + line);
}
System.out.println("Line : "+line);
When you spawn a process with
Runtime.getRuntime().exec(cmd);
the process is started from the same working directory as the Java process. If Java was run from a different working directory than you ran the find -name javax.jar in console, you will see different results.
i think you may try to add the path of find.
like find /var/tmp -name

Ctrl C through OutputStreamWriter in Linux

I have a shell script running through a process runtime on Java.
This Shell Script only stops when you hit CTRL+C
Right now I catch the InputStream from the script in a JTextArea.
but I can't send CTRL+C.
When you run CTRL+C on a Shell Konsole the script stops and sends back information.
and this information is the one that I Can't Catch.
So
How can I Send CTRL+C Through Process runtime?
How can I catch the Inputstream from CTRL+C?
File dirw = new File("/home/mydir/sh/");
Runtime runtime = Runtime.getRuntime();
Process process = null;
process = runtime.exec("./start_test.sh", null, dirw);
OutputStream outp = new OutputStream(process.getOutputStream());
InputStreamReader isr = new InputStreamReader(process.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line = null;
int cont = 1;
while ((line = br.readLine()) != null) {
jtextarea.append("LineOK " + line + "\n");
if( cont == 10) {
outp.write(3); //sending Ctrl+C
outp.flush();
cont =0;
}
cont ++;
}
CTRL+C is a command sent from user to shell. When shell receives it, it sends SIGINT to the foreground process.
To do this in Java use Process.sendSignal(pid, Process.SIGNAL_QUIT) - this only works on Android.
Update: the above command is wrong as it's only available on Android.
The correct way is to send kill -2 pid. Beware: this is UNIX-only solution. Another problem is getting the pid (process id). It turns out there is no OS-agnostic solution to it: How to get PID of process I've just started within java program?
The solution is to resort to OS-dependent hacks as mentioned in the link (getting pid from Process via reflection).

Categories