Intercept input and output from specific executable

6,242

Solution 1

Option 1 would be to modify the source code of the calling app and insert tee into the output pipeline to get a copy of the output for review at that stage.

Option 2 would be to write a wrapper script around the executable in question. A quick script that passes on stdin and arguments to the real app, then tee's the output to a location for you to review and also spits it back out the same way the app would should be just a couple lines to whip up. Put it someplace special and make add that location to the front of your PATH variable, then run your application.

#!/bin/sh
cat - | /path/to/realapp $@ | tee /tmp/debug_output

Solution 2

You can obtain a lot of information about a program by calling it under strace. This shows every system call that the program makes, which can be too much information sometimes, but can be a big help to find what's going wrong.

Approach one is to run your big application under strace. This is likely to produce a lot of output and slow your application down.

strace -s9999 -efile,process -f -o bigapp.strace bigapp

If the big application is interactive, you may prefer to start it, and connect strace to it once you're ready to trigger the calculations. Note the application's process ID, say 12345, and run

strace -s9999 -efile,process -f -o bigapp-calculations.strace -p12345

If it's enough to observe that external executable, then as other answers have already suggested, replace that executable by a wrapper script. You can move the executable to a different name and put the wrapper script in its place, or put the wrapper script ahead of the usual executable in the PATH, or configure the application to call your wrapper script instead of the usual executable, whatever is convenient. Make that wrapper script

#!/bin/sh
exec strace -s9999 -efile -o auxapp-$$.strace /path/to/original/executable "$@"

Explanation of the strace parameters used:

  • -e selects the system calls to trace. You can specify system calls by name or use a few categories such as file (open, close, read, write, …) and process (fork, execve, …).
  • -f makes strace follows forks, i.e. trace subprocesses as well as the original process.
  • -o selects the name of the file containing the trace. $$ is a shell construct that stands for the process ID of the shell process (due to the use of exec in the last wrapper script, that will also be the auxiliary application's process ID).
  • -s9999 makes it display that many bytes for read and write and other calls.

Solution 3

Rather than changing your path, you should move the binary you are interested in from "binary" to "binary.orig" then replace it with a script. You said you are interested in the arguments, so you'll want to write those out to a file as well. You will probably also be interested in the output of the command "env". It dumps all the environment variables currently active. Environment variables are often used by one program to influence the behavior of another program that it calls.

Solution 4

The following works for me:

cat - | tee /tmp/in.log | /path/to/realapp $@ | tee /tmp/out.log

Share:
6,242

Related videos on Youtube

Mad Scientist
Author by

Mad Scientist

Updated on September 18, 2022

Comments

  • Mad Scientist
    Mad Scientist over 1 year

    I have a certain Linux executable that is called from a bigger application to perform some calculations. I want to modify the way the calculations are performed, for that I first need to understand how the executable is called and in what way the parameters and data are transferred.

    So, I'd like to monitor the command line parameters, stdin and stdout if this executable is called. The normal operation of the executable should not be disturbed.

    Is there an easy way to do that?

    Update:

    I tried the shell script placeholder idea to grab all the data using the following script:

    #!/bin/bash
    export LOGFILE=/tmp/logname
    echo `env` > $LOGFILE-env
    echo "$@" >> $LOGFILE-arguments
    tee -a $LOGFILE-stdin | /path/to/real/executable 2>&1 | tee -a $LOGFILE-stdout
    

    This works fine for test input, but it just hangs if it is called for real. Probably there is even more going on than I suspected.

    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' about 13 years
      That's unusual. The system doesn't give the caller any indication of whether it's calling a binary or a script, the application would have to go out of its way to even find out. What's the exact error message? Are you trying to work around some kind of content protection mechanism (in which case there'll probably be other hurdles)?
    • Alen Milakovic
      Alen Milakovic about 8 years
      @MadScientist If you no longer see an error, then remove the reference to it in your question. I can't think of any reason to leave it in, and it just causes confusion. You could also delete the comment: "My previously described error was caused by a mistake in the shebang of the script."
  • Mad Scientist
    Mad Scientist about 13 years
    Thanks for the idea, I tried it but replacing the executable with a shell script does not work, unfortunately. I can't change the source code of the calling app either.
  • tcoolspy
    tcoolspy about 13 years
    @Fabian In general this DOES work, I've had to do it several times. You do need to know what to wire up to each end; basically all the input/output options on both ends need to be directly patched through. This could include trapping and passing signals. Can you explain why this "doesn't work" for you?
  • Mad Scientist
    Mad Scientist about 13 years
    Sorry for the confusion, it was just an error in the shebang causing the problem.