onlycparra
onlycparra

Reputation: 775

How to redirect stdout and stderr for both commands, when one command is argument of the other

The problem

Some programs ('called-command') receive as part of their parameters, another program with its own parameters ('indirect-command'). Such is the case of the commands time, timeout, stdbuf, perf, and many others.

I am trying to capture stdout and stderr of the 'called' as well as the 'indirect' commands in independent files.

Conceptually speaking, I want something like this, but of course, this doesn't work as I am typing it:

/usr/bin/time -p -- { \
    timeout -k 10 7 { \
        stdbuf -oL { \
            ./main >main_out.log 2>main_err.log; \
        } \
    } 2>timeout.log; \
} 2>time.log

In other words:

What I have checked/tried

I am aware that time has the option -o OUTPUT_FILE, but that is a particular feature of time, and I would like to know a generic way in which to capture outputs/errors of commands that are parameters of other commands.

I am suspecting that perhaps this cannot be generically done, because the 'called-command' actually just receives a number of strings. It is up to the 'called-command' to interpret those strings as its own options and from some point recognize the here called ('indirect-command'). Therefore, it is not forced to treat the characters < or > in any special manner...

Thanks in advance.

Upvotes: 1

Views: 188

Answers (2)

Philippe
Philippe

Reputation: 26377

I wonder if this can meet your requirements :

/usr/bin/time -p --\
    bash -c '"$@" 2>timeout.log'                _ timeout -k 10 7 \
    bash -c '"$@"'                              _ stdbuf -oL\
    bash -c '"$@" >main_out.log 2>main_err.log' _ ./main \
    2>time.log

Yes, the idea is to spawn one bash instance per "nesting-level".

I have updated main to ./main, it should work now.

The underscore is a placeholder for $0 of each bash process.

Upvotes: 0

mirage
mirage

Reputation: 631

I think what you are trying to do can be done with tee and exec working together. Try the following example:

/usr/bin/time -p -- { \
    exec 2>timeout.log; \
    timeout -k 10 7 { \
        exec > >(tee -a timeout.log) 2> >(tee -a timeout.log >&2); \
        stdbuf -oL { \
            exec >main_out.log 2>main_err.log; \
            ./main; \
        } \
    } \
} 2>time.log

Upvotes: 1

Related Questions