I made some buttons in my app that exec a bash cmd.
Here is my string:
final String[] test = {"su","-c","echo test > /system/test.txt"};
This cmd works, in fact, i can see the test.txt file on /system/ with the line test inside.
My question is: When i push on the button for exec that cmd the device create a toast with the string "echo test /system/text.txt".
I'm guessing this is due to "-c", anyway:
final String[] test = {"su","echo test > /system/test.txt"};
won't work, and:
final String[] test = {"su","-c","echo test > /system/test.txt >> /dev/null"};
won't work as well and create a toast showing "echo test /system/test.txt /dev/null"
is there any way i can avoid this "problem"?
Also, can anyone show me a little function that create a toast with a spinning wheel when i onClick to the button that exec it?
Thanks!!!
This extract from su manual should clear your question about -c option:
-c, --command=COMMAND
pass a single COMMAND to the shell with -c
And
final String[] test = {"su","-c","echo test > /system/test.txt >> /dev/null"};
won't work because Android don't have /dev/null device. To get it work you need to have a -c option after su and get a rid of /dev/null. You may use android API to delete this file instead.
Related
So, I need to copy a file to /system, and have to use shell commands, because the application is not running with enough privileges (and is not even installed to /system/apps at that time) - so its impossible to write to /system directly.
String cmd = String.format("\"/bin/sh -c \'cp %s %s'", tempPath, out);
p = Runtime.getRuntime().exec(new String[] { "su", "-c", cmd });
However, SuperSU pop-up informs me, that following application was granted to run as root:
/bin/sh -c _cp %s %s_.
So ' are replaced with _, and eventually command takes no effect.
What is a proper way to run a command having so much quotes ("" and '' for a single argument to su)?
I know of using su's stdin to run commands separated by \n, but it seems to be having its own problems (and was not working too).
If you're calling through SuperSU, there are a ton of pitfalls, and the recommended way is to use libsuperuser. See http://su.chainfire.eu/ for details.
I'm trying to write an android app that backs up data from selected directory of an android device to a remote host using rsync and ssh. When I run the rsync command from adb shell as follows, it works:
rsync -rvz -e "/system/xbin/ssh -y -p 22" "/mnt/sdcard/" "rajeesh#10.0.2.2:backup/"
But my java code using Runtime.exec fails with an error that says:
Error: rsync: failed to exec /system/xbin/ssh -y -p 22: No such file or directory (2)
The code I used is as follows:
String[] commands = {
"rsync", "-rvz", "-e", "\"/system/xbin/ssh -y -p 22\"",
"\"/mnt/sdcard/\"", "\"rajeesh#10.0.2.2:backup/\""
};
Process process = Runtime.getRuntime().exec(commands);
Both rsync and ssh have been placed at /system/xbin and chmoded to 755. Tried replacing "rsync" with "/system/xbin/rsync" also but the issue remains. What would be the issue here?
Found out the issue myself.
When run directly from the shell, quotes have specific meaning and they are required here as follows:
rsync -rvz -e "ssh -y -p 22" "/path/to/src/" "/path/to/dest"
My java snippet above was trying to run the command with the quotes escaped, like "\"arg\"". But quotes not required when used outside shell. The correct usage is:
String[] commands = {
"/system/xbin/rsync", "-rvz", "-e", "/system/xbin/ssh -y -p 22",
"/mnt/sdcard", "rajeesh#10.0.2.2:backup/"
};
I'm not sure but maybe problem is that the destination path (rajeesh#10.0.2.2:backup/) is not absolute?
Also if you what to sync your files in the same device, maybe you should try to not use ssh? And do something like that:
rsync -rvz /mnt/sdcard/some_directory /backup
I have this .php file sending commands to my android application:
I have tried working with:
Runtime.getRuntime().exec(commandLine);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
but the commands echo, pwd and some others are not working.
I get the following exception:
java.io.IOException: Error running exec(). Command: [pwd] Working Directory: null Environment: null
As far as I understand this is because there is not any shell environment.
Then I have tried writing in a .sh file the command I want and then execute the command this way:
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("sh /runCmds/shTest.sh");
InputStream is = proc.getInputStream();
and got solved the problem with pwd, echo and most of the commands.
But later on I realized that I want to keep the state of the commands I execute.
For example I want to change directory(cd data) and execute the command mkdir Apoel
And here is when I face my problem. What to do?
I came up with another idea:
Make a shell script (.sh) and each time the user wants to execute a command append the new command in it (and run the hole script(.sh) again). But I think is not a very good way to do it!
Is there any easy way to it? Can my application open a terminal easily?
Here is a code I found for a Terminal Emulator, but it is too complicated!
https://github.com/jackpal/Android-Terminal-Emulator
An interactive shell is one which remains running, waiting for new commands which it receives from stdin, while producing it's output to stdout and stderr - as a result, it's environment including any changes is retained for the duration of the session. For the shell to be useful to a user, stdin, stoud, stderr need to be connected through to the user - via the console, a serial line, or xterm, etc.
On Android, typically what you do is hook onto the pipes corresponding to stdin, stdout, stderr for the shell process that you've created, and use them to push in commands provided by your java program and accept output for your program to interpret/display.
The idea of creating a script and running it would only work in the case where all the commands are entered before any of them execute.
First, some background. On any Posix system, in the shell, there are 2 types of commands:
Internal commands (pwd,cd,echo)
external commands (ls,cp,mv, sometimes echo as well)
All the directory context commands (cd,pwd etc) are commands implemented inside the shell and thus require the shell to remain running, if the changes are to hold (for eg. cd /data/local/tmp).
On the other hand, external commands are standalone and can run indepenedently, but acquire their directory context from their parent process (in most cases, the shell).
Now to solve the problem. Yes, using a script is a good idea, but it is painful to implement, as it requires an overhead of file editing. However, we can use the shell to create a script on the fly and execute it using the -c option. For example:
/system/bin/sh -c 'cd /data/local/tmp; touch abc; cp abc def; cd /; rm /data/local/tmp/abc'
In summery:
String sPrefix="/system/bin/sh -c 'cd someplace;";
String sInputCmd=getCommand(); // this is simulating your command input
String sPostfix="'";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix); // sh -c 'cd someplace; echo do something'
InputStream is = proc.getInputStream();
However, this does not give us the capability to set a directory context, so we need to simulate that. Directory contexts can be added by using the Runtime.exec(String command, String[] envp, File dir) method. With this we have the possibility of maintaining directory
context between commands. But how do we actually do that? One solution is to append pwd to the command and take the last line of the output as the new directory context. Thus
String sPath = "/"; // start in root directory
String sPrefix = "/system/bin/sh -c 'cd someplace;";
String sInputCmd; // this is simulating your command input
String sPostfix = ";echo;pwd'";
Runtime rt = Runtime.getRuntime();
while(!(sInputCmd=getCommand()).equals("")) {
File dir= new File(sPath);
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix, NULL, dir);
InputStream is = proc.getInputStream();
// Do processing on input.
sPath= last_line_of_is ;
}
Finally, the last option is to integrate one of the terminal emulators into you app.
[1] http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String,%20java.lang.String%5B%5D,%20java.io.File%29
I want to execute the "adb logcat -d time > pathoffile\log.txt &" in my java code.
I want to create my log.txt in my device.
I wrote this code to do this.
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("logcat");
commandLine.add("-d");
commandLine.add("time");
commandLine.add(">");
commandLine.add(getApplicationContext().getFilesDir()
// + "/log.txt"); //already created the file at specified location.
//commandLine.add("&");
Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
The above code not throwing any error , but my file (log.txt) is not updating with the log statements..
please help me in this how to do this, pl. suggest if there's any alternative to do this..
thanks.
Try -f option instead:
adb logcat -d time -f /mnt/sdcard/log.txt
Note that > is io redirection feature of shell. It has no effect when used with exec() function.
I've been told it's a command line option. But Eclipse's Run!Run Configurations...!Target!Additional Emulator Command Line Options field is already occupied with
-sdcard "C:\android-sdk-windows\tools\sd9m.img"
If I wanted to write something like
adb logcat -s MessageBox > "C:\Users\me\Documents\LogCatOutput.txt"
then where do I write it, and how (i.e., is the syntax even correct)? I need to output only a filtered tag, not verbose. ("MessageBox" is my TAG. Again I don't know if any of this punctuation is right, or even where the command goes.)
Thanks for any help.
There should be an adb.exe file in C:\android-sdk-windows\tools. You can invoke this manually from a DOS command prompt:
cd C:\android-sdk-windows\tools
adb logcat -s MessageBox > "C:\Users\me\Documents\LogCatOutput.txt"
There's no need to bother with Eclipse in this case.
Alternatively, if you only want to dump whatever's already in the logcat buffers and exit immediately (useful for scripts), you can specify the -d option:
$ adb logcat -d -s MessageBox > dump_file.txt
Make sure that '-d' is after 'logcat'.
Another useful addition to the above answers is filtering. The application I am working on generates a massive amount of logging, so it is useful to log with filters.
adb -s MyDevice logcat | find /V ": T#" > d:\temp\logcat.txt
or for OSX/Linux
adb -s MyDevice logcat | grep -v ": T#" > ~/logcat.txt
This will write all logcat activity apart from any line that contains ": T#"
find or grep can also be used to filter based on positive results. I then use the likes of BareTail display the growing log file.