tags:

views:

480

answers:

12

I have an application that runs the a command as below:

<command> <switches> >& /dev/null

I can configure <command>, but I have no control over <switches> . All the output generated by this command goes to /dev/null. I want the output to be visible on screen or redirected to a log file.

I tried to use freopen() and related functions to reopen /dev/null to another file, but could not get it working.

Do you have any other ideas? Is this possible at all?

Thanks for your time.

PS: I am working on Linux.

+5  A: 

Terrible Hack:

use a text editor in binary mode open the app, find '/dev/null/' and replace it with a string of the same length

e.g '~/tmp/log'
  • make a backup first
  • be carefull
  • be very carefull
  • did I mention the backup?
lexu
Clarification: open the binary executable with the text editor. Somewhere in the gibberish of the binary stuff there should be "/dev/null" which is what you replace as suggested above.
Ricket
@lexu: I had done it earlier. Replaced /dev/null with a string of spaces of equal length. This works, but for every version of the application, hacking the executable is tedious...I was thinking of writing a program that does some redirection hack and calls the <command>. This will be a one time effort.
Gowtham
+1 for the accompanying list.
T.J. Crowder
@Gowtham: (alternative approaches) (1) Write a program that does the 'replace'... (2) Go to the developer of the application and (politely) ask for a configeration option that allows you to redirect to a log-file ..
lexu
@Gowtham: is the command being called a Perl script that you can modify? If yes, you can re-open stdio to another file.
lexu
+2  A: 

Append # at the end of your command so it becomes <command> # >& /dev/null, thus commenting out the undesired part.

e-t172
Gowtham
+1  A: 

You can do this with an already running process by using gdb. See the following page: http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/

ar
+1  A: 

Can you create an alias for that command? If so, alias it to another command that dumps output to a file.

Melvin
A: 

EDIT: This is NOT a good idea and certainly not worth trying unless you know what this can break. It works for me, may work for you as well.

Ok, This is a really bad hack and probably not worth doing. Assuming that none of the other commands works, and you simply do not have access to the binary/application (which contains the command with /dev/null) and you cannot re-direct the output to other file (by replacing /dev/null).

Then, you can delete /dev/null ($> rm /dev/null) and create your own file at its place (preferably with a soft link) where all the data can be directed. When you are done, you can create the /dev/null once again using following command:

$> mknod -m 666 /dev/null c 1 3

Just to be very clear, this is a bad hack and certainly requires root permissions to work. High chances that your re-directed file may contain data from many other applications/binaries which are running and use /dev/null as sink.

Shrey
Just to add, I tried this on my machine which is a Fedora running 2.6.30. This info is so because Major and Minor number may be different for mknod on other platforms/environment.
Shrey
It would be great if 'why-my-answer-was-voted-down' is explained as comment. I know this is a hack (mentioned quiet clearly) and this is explicitly what the poster was looking for "...but I have no control over ...".
Shrey
Removing /dev/null goes beyond being a hack. It is a completely broken idea. It affects the whole system (any new opens on the pathname), not just the targeted script/program. It has to be “fixed” after you are done. And it requires root access. The answer here its not to “redirect /dev/null” but to reopen existing descriptors that were originally opened from /dev/null.
Chris Johnsen
@Chris Well, this exactly what I have mentioned that this is not worth doing. Being a 'bad' hack is more of perspective - for any production environment, this certainly is not right - but, if I have my debugging environment and I _need_ the output to see something - I may very well prefer this hack. Nevertheless, thanks for comments - I have edited the post.
Shrey
+1  A: 

The device file /dev/tty references your application's controlling terminal - if that hasn't changed, then this should work:

freopen("/dev/tty", "w", stdout);
freopen("/dev/tty", "w", stderr);

Alternatively, you can reopen them to point to a log file:

freopen("/var/log/myapp.log", "a", stdout);
freopen("/var/log/myapp.err", "a", stderr);
caf
+2  A: 

Your application is probably running a shell and passing it that command line.

You need to make it run a script written by you. That script will replace >/dev/null in the command line with >>/your/log and call the real shell with the modified command line.

The first step is to change the shell used by the application. Changing the environment variable SHELL should suffice, i.e., run your application as

SHELL=/home/user/bin/myshell theApp

If that doesn't work, try momentarily linking /bin/sh to your script.

myshell will call the original shell, but after pattern-replacing the parameters:

#!/bin/bash
sh ${1+"${@/\>\/dev\/null/>>\/your\/log}"}

Something along these lines should work.

angus
+2  A: 

Since you can modify the command you run you can use a simple shell script as a wrapper to redirect the output to a file.

#!/bin/bash
"$@" >> logfile

If you save this in your path as capture_output.sh then you can add capture_output.sh to the start of your command to append the output of your program to logfile.

Ven'Tatsu
A: 

In perl, if you just want to redirect STDOUT to something slightly more useful, you can just do something like:

open STDOUT, '>>', '/var/log/myscript.log';
open STDERR, '>>', '/var/log/myscript.err';

at the beginning of your script, and that'll redirect it for the rest of your script.

pioto
A: 

Along the lines of e-t172's answer, can you set the last switch to (or append to it):

; echo 
mobrule
A: 

It may not exactly redirect, but it allows to get the output wherever it's being sent

strace -ewrite -p $PID

It's not that cleen (shows lines like: write(#,) ), but works! (and is single-line :D ) You might also dislike the fact, that arguments are abbreviated. To control that use -s parameter that sets the maxlength of strings displayed.

It catches all streams, so You might want to filter that somehow.

You can filter it:

strace -ewrite -p $PID 2>&1 | grep "write(1"

shows only descriptor 1 calls. 2>&1 is to redirect stderr to stdout, as strace writes to stderr by default.

naugtur
A: 

If you can put something inline before passing things to /dev/null (not sure if you are dealing with a hardcoded command), you could use tee to redirect to something of your choice.

Example from Wikipedia which allows escalation of a command:

echo "Body of file..." | sudo tee root_owned_file > /dev/null

http://en.wikipedia.org/wiki/Tee_(command)

Jauder Ho