z3n*_*ful 6 shell android loops su busybox
对于我的生活,我无法让我的应用程序从su shell中调用busybox的进程获得响应.
我已经尝试了三种不同的方法,并尝试了三种方法的组合以使其工作,但我永远无法使用busybox的任何东西获得输出,只有其他命令.
更具体地说,我可以让它返回像"ls/data"和"cat suchandsuch.file"这样的命令,但任何以"busybox"开头的东西(即busybox mount,busybox free)都不会显示任何内容.
这是最接近我的方法,此代码使用"ls/data",但不是"busybox free"
这个将运行命令(大多数情况下),并返回一个空字符串而不是从输入流无限循环.
Process p;
try {
p = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
stdin.writeBytes("ls /data\n");
DataInputStream stdout = new DataInputStream(p.getInputStream());
byte[] buffer = new byte[4096];
int read = 0;
String out = new String();
while(true){
read = stdout.read(buffer);
out += new String(buffer, 0, read);
if(read<4096){
break;
}
}
Toast.makeText(getApplicationContext(), out, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
底部附近的吐司显示"ls/data"中的所有内容,但是当更改为busybox的任何内容时,其空白或为空.
我也尝试了这两种方法,但其中没有一种方法有效.(我在命令运行后将进程传递给他们.)
当你点击方法的按钮时,这两个都会导致应用程序冻结.
String termReader(Process process){
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
try {
int i;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((i = reader.read(buffer)) > 0) output.append(buffer, 0, i);
reader.close();
return output.toString();
} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
}
}
String processReader(Process process){
InputStream stdout = process.getInputStream();
byte[] buffer = new byte[1024];
int read;
String out = new String();
while(true){
try {
read = stdout.read(buffer);
out += new String(buffer, 0, read);
if(read<1024){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
return out;
}
Run Code Online (Sandbox Code Playgroud)
没有堆栈跟踪可以使用,所以我开始有点难过.
使用下面提出的代码编辑,嗯,下面:D我稍微改了一下,使它成为一个单击运行的东西,以便更容易地进行故障排除和测试.
当它尝试读取输入流时也会冻结,如果我在尝试读取流之前调用stdin.writeBytes("exit \n"),它会在关闭终端时给出空白答案,如果我之后调用它,它会循环不休.
void Run() {
String command = "busybox traceroute\n";
StringBuffer theRun = null;
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream stdin = new DataOutputStream(process.getOutputStream());
stdin.writeBytes(command);
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);
}
Toast.makeText(getApplicationContext(), theRun, Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)
它似乎跳过第一行(每次调用命令时获得的busybox信息行)并且不捕获其余数据.香港专业教育学院尝试了所有我能想到的变化,以使其正常工作:/
如果有人对此有所了解,我会非常谨慎:)
我找到了一种解决方法。
首先,在我的例子中,运行链接到 busybox 的命令永远不会通过其 InputStream 返回其输出,无论我尝试什么方法(而且我尝试了很多,哈哈)。
这就是我发现我能做的。这有点乏味,并且不会为您提供完整的输出,但是如果您想要依赖命令是否正确启动的东西(在我的情况下,如果我无法比较所有内容,我的应用程序就无法正常工作)跑了。)
您无法从进程中获取输入,但如果操作正确,您可以获得退出值:)这适用于任何不会给您提供复杂响应的内容(例如在大文件上使用 cat )
两者之间的区别很容易发现,例如:
command = "cat /sys" // works, exits with 1
command = "cat /init.rc" doesnt work, exits with 0
Run Code Online (Sandbox Code Playgroud)
这就是我设置它以轻松工作的方式。使用MasterJB提供的方法正常运行命令:
process p;
try {
p = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
stdin.writeBytes(command);
stdin.writeBytes("echo $?\n");
DataInputStream stdout = new DataInputStream(p.getInputStream());
byte[] buffer = new byte[4096];
int read = 0;
String out = new String();
while(true){
read = stdout.read(buffer);
out += new String(buffer, 0, read);
if(read<4096){
break;
}
// here is where you catch the error value
int len = out.length();
char suExitValue = out.charAt(len-2);
Toast.makeText(getApplicationContext(), String.valueOf(suExitValue), Toast.LENGTH_SHORT).show();
return0or1(Integer.valueOf(suExitValue), command); // 0 or 1 Method
// end catching exit value
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
我还发现使用“0 或 1”方法来返回发生的情况更容易。在此示例中,它是作为祝酒词被触发的。您可能还想测试 char 是否实际上是整数,因为某些命令没有给出任何退出值(我知道很奇怪。一个实例是 ls /sys,当通过 su 终端运行时,它会返回一个空白退出值。)
String return0or1 (int returnValue, String command){
String message = command + " - Cannot get return value.";
if (returnValue == 0){
message = command + " - successful.";
return message;
}
if (returnValue == 1){
message = command + " - failed.";
return message;
}
return message;
}
Run Code Online (Sandbox Code Playgroud)
通过一些研究,您可以将任何退出值与适当的响应相匹配,只需正确捕获它们即可:)
这些方法仅返回命令是否运行 (0),但如果它获得双字符或三字符退出代码,则失败时最后一位数字可能为 0(即当退出值为 10 时),因此这在大多数情况下都有效,但需要扩展以捕获双倍和三倍值。