Search code examples
javaandroidlogcat

Why does the same command work in a terminal but not in my app?


I'm making an app which, using root, takes a logcat so it can find a certain error on another app. The easiest approach for me is saving the logcat to a file directly from the command. So all I have to do is run su and then logcat | grep --line-buffered "search string" > /path/to/save/logcat.log. When I run this on a terminal emulator (like this or even this), it saves the output to a file just exactly how I want it to do so. But when I run the exact same command from my app, it gets me a blank file. I've tried many different ways to output the logcat but they all get me an empty file. Interestingly, when I take a normal logcat using the app (without grep, using ">" to output), the file is being saved as it should and it contains the string I want to grep. What am I doing wrong?

Here is the code I use:

try {
        Process p = Runtime.getRuntime().exec("su");
        DataOutputStream dos = new DataOutputStream(p.getOutputStream());
        dos.writeBytes("logcat | grep --line-buffered \"search string\" > /storage/emulated/0/logcat.log\n");
        dos.flush();
 } catch (IOException e) {
     e.printStackTrace();
 }

Solution

  • I'm listing my comment as an answer since that evidently helped solve your issue but there is more going on here which I'm not capable of fully addressing:

    Try redirecting stderr as well to see if there is any error which can then be captured - I think that would be &> (that's bash) - and >outfile 2>&1 for more general syntax.

    So

    dos.writeBytes("logcat | grep --line-buffered \"search string\" &> /storage/emulated/0/logcat.log\n");
    

    Or

    dos.writeBytes("logcat | grep --line-buffered \"search string\" > /storage/emulated/0/logcat.log 2>&1\n");
    

    The original intention of the comment was to get you more information as to what was really going on - as it turns out, it helped you get the result you were looking for.

    I believe there are a few factors at work here which may contribute to why adding stderr helped:

    • stderr (which the comment suggested adding) is non-buffered - I think (but can't prove) the non-buffering is what is helping you even though the output being captured is stdout.
    • stdout processing is sensitive to TTY (terminal emulation) vs non-TTY (your program) and has different buffering approaches (line buffering in TTY otherwise fully buffered). I realize your grep option should overcome this. This difference in TTY-nonTTY may explain the source of your problem.
    • The code posted is sending a command (logcat...) to the process created and continuing. So for example if the logcat were to output lots of data, in theory your posted code would continue and leave scope - what happens to the process created when p is out scope - not sure.

    Anyways, glad you were able to proceed.