Redirecting Function Output to /Dev/Null

Redirecting function output to /dev/null

If you are sure that thing does not redirect output (e.g. to /dev/tty/, which would be standard-out again) (which I don't think), you could redirect before calling them.

#include <iostream>
#include <sstream>

void foobar() { std::cout << "foobar!\nfrob!!"; }

int main () {
using namespace std;

streambuf *old = cout.rdbuf(); // <-- save
stringstream ss;

cout.rdbuf (ss.rdbuf()); // <-- redirect
foobar(); // <-- call
cout.rdbuf (old); // <-- restore

// test
cout << "[[" << ss.str() << "]]" << endl;
}

How do I conditionally redirect the output of a command to /dev/null?

You could write a wrapper function:

redirect_cmd() {
# write your test however you want; this just tests if SILENT is non-empty
if [ -n "$SILENT" ]; then
"$@" > /dev/null
else
"$@"
fi
}

You can then use it to run any command with the redirect:

redirect_cmd echo "unsilenced echo"
redirect_cmd ls -d foo*

SILENT=1
redirect_cmd echo "nothing will be printed"
redirect_cmd touch but_the_command_is_still_run

(If all you need to do is echo with this, you can of course make the function simpler, just echoing the first argument instead of running them all as a command)

Redirecting or appending to /dev/null

It seems the behaviour for redirecting to /dev/null via either redirect > or append >> is identical. A quick test shows that it also makes no difference timing wise:

Content to print:

for i in range(10**4):
print("content")

Test time command:

 time python printlots.py >> /dev/null ; time python printlots.py > /dev/null

Result:

$ time python printlots.py >> /dev/null ; time python printlots.py > /dev/null

real 0m0.094s
user 0m0.047s
sys 0m0.047s

real 0m0.096s
user 0m0.031s
sys 0m0.063s

So it won't make a measureable difference which you use. It seems the reason both work is to enable developers to use /dev/null in their code with more flexibility. If you have a program where one input parameter is the output file it prints to, and append is your default mode, not having append to /dev/null would mean you'd have to check first what the target file is. At least that's what this answer assumes.

How can I redirect all output to /dev/null?

Redirection operators are evaluated left-to-right. You wrongly put 2>&1 first, which points 2 to the same place, as 1 currently is pointed to which is the local terminal screen, because you have not redirected 1 yet. You need to do either of the following:

2>/dev/null 1>/dev/null google-chrome &

Or

2>/dev/null 1>&2 google-chrome &

The placement of the redirect operators in relation to the command does not matter. You can put them before or after the command.

How to redirect output away from /dev/null

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.

Will printf still have a cost even if I redirect output to /dev/null?

Pretty much.

When you redirect the stdout of the program to /dev/null, any call to printf(3) will still evaluate all the arguments, and the string formatting process will still take place before calling write(2), which writes the full formatted string to the standard output of the process. It's at the kernel level that the data isn't written to disk, but discarded by the handler associated with the special device /dev/null.

So at the very best, you won't bypass or evade the overhead of evaluating the arguments and passing them to printf, the string formatting job behind printf, and at least one system call to actually write the data, just by redirecting stdout to /dev/null. Well, that's a true difference on Linux. The implementation just returns the number of bytes you wanted to write (specified by the 3rd argument of your call to write(2)) and ignores everything else (see this answer). Depending on the amount of data you're writing, and the speed of the target device (disk or terminal), the difference in performance may vary a lot. On embedded systems, generally speaking, cutting off the disk write by redirecting to /dev/null can save quite some system resources for a non-trivial amount of written data.

Although in theory, the program could detect /dev/null and perform some optimizations within the restrictions of standards they comply to (ISO C and POSIX), based on general understanding of common implementations, they practically don't (i.e. I am unaware of any Unix or Linux system doing so).

The POSIX standard mandates writing to the standard output for any call to printf(3), so it's not standard-conforming to suppress the call to write(2) depending on the associated file descriptors. For more details about POSIX requirements, you can read Damon's answer. Oh, and a quick note: All Linux distros are practically POSIX-compliant, despite not being certified to be so.

Be aware that if you replace printf completely, some side effects may go wrong, for example printf("%d%n", a++, &b). If you really need to suppress the output depending on the program execution environment, consider setting a global flag and wrap up printf to check the flag before printing — it isn't going to slow down the program to an extent where the performance loss is visible, as a single condition check is much faster than calling printf and doing all the string formatting.

Redirect stderr to /dev/null

In order to redirect stderr to /dev/null use:

some_cmd 2>/dev/null

You don't need xargs here. (And you don't want it! since it performs word splitting)

Use find's exec option:

find . -type f -name "*.txt" -exec grep -li needle {} +

To suppress the error messages use the -s option of grep:

From man grep:

-s, --no-messages
Suppress error messages about nonexistent or unreadable files.

which gives you:

find . -type f -name "*.txt" -exec grep -lis needle {} +

Redirect output to /dev/null only if VERBOSE is not set

You could redirect all output using exec:

if [[ -z $VERBOSE ]]; then
exec >/dev/null 2>&1
fi

pip install requirements.txt

If you want to restore the output later on in the script you can duplicate the file descriptors:

if [[ -z $VERBOSE ]]; then
exec 3>&1
exec 4>&2
exec >/dev/null 2>&1
fi

# all the commands to redirect output for
pip install requirements.txt
# ...

# restore output
if [[ -z $VERBOSE ]]; then
exec 1>&3
exec 2>&4
fi

Another option is to open a file descriptor to either /dev/null or to duplicate descriptor 1:

if [[ -z $VERBOSE ]]; then
exec 3>/dev/null
else
exec 3>&1
fi

echo "Installing Pip packages"
pip install requirements.txt >&3



Related Topics



Leave a reply



Submit