7

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.

3
  • 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)?CommentedMay 4, 2011 at 20:26
  • My previously described error was caused by a mistake in the shebang of the script.CommentedMay 5, 2011 at 7:54
  • @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."CommentedMar 12, 2016 at 8:32

4 Answers 4

8

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 
4
  • 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.CommentedMay 4, 2011 at 14:48
  • @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?
    – Caleb
    CommentedMay 4, 2011 at 20:11
  • I've added my progress to my question. You're right that it works, my script works exactly as it should with test input. But it is not executed by a shell for some reason when called from the big program.CommentedMay 4, 2011 at 20:22
  • Sorry for the confusion, it was just an error in the shebang causing the problem.CommentedMay 5, 2011 at 7:53
4

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 otheranswers 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.
    2

    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.

      1

      The following works for me:

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

        You must log in to answer this question.

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.