bash redirect to /dev/stdout: Not a directory
Good morning, user1999165, :)
I suspect it's related to the underlying filesystem. On the same machine, try:
(echo "hi" > /dev/stdout) > /tmp/test.txt
/tmp/ should be linux native (ext3 or something) filesystem
Redirect to stdout in bash
Basic solution:
#!/bin/bash
LOG=/dev/null
# uncomment next line for debugging (logging)
# LOG=/tmp/some_file
{
some_command
echo "blah"
} | tee 1>$LOG 2>&1
More evolved:
#!/bin/bash
ENABLE_LOG=0 # 1 to log standard & error outputs
LOG=/tmp/some_file
{
some_command
echo "blah"
} | if (( $ENABLE_LOG ))
then
tee 1>$LOG 2>&1
fi
More elegant solution from DevSolar's idea:
#!/bin/bash
# uncomment next line for debugging (logging)
# exec 1> >(tee /tmp/some_file) 2>&1
some_command
echo "blah"
Bash redirect and append to non-existent file/directory
Using install
:
command | install -D /dev/stdin nonexistent/file.log
or use
mkdir nonexistent
first.
Consistency of bash redirection to the same file
If you open the descriptors separately, they're totally independent streams. If they're pointing to the same file, they'll each keep track of the file offset independently. So the first time you write to one stream it will write to the beginning of the file, and the first time you write to the other it will also write to the beginning of the file, overwriting what the previous write did. This will keep happening, with writes to each stream overwriting the other.
What you can do is first empty each file, then open them both in append mode:
> $myStdout
> $myStderr
redirect 1>> $myStdout 2>> $myStderr
By appending, each write will first seek to the end of the file, so it will go after whatever the previous write did, rather than overwriting it.
However, there may be another issue. If the program uses stdio, it buffers stdout
by default, but not stderr
. So unless the program flushes the stdout
buffer before printing error messages, they're likely to get interspersed in random places in the output, not neatly on their own lines.
Where do I direct the output?
>&
is a variant on the >
pipeline operation. While >
redirects output into a named file (or the device's representation in the filesystem, such as /dev/console
), >&
redirects the output to one of the standard output streams. The most commonly used exaples are stream 1 (stdout) and stream 2 (stderr). Note that these are the same numbers you can use in front of the >
or >&
operators to say which stream's output you want to redirect.
echo "hello" >&1
is redundant; you're redirecting stdout to stdout.
(echo "hello" 1>&1
would mean the same thing, of course.)
A more interesting example: echo "hello" 2>&1
redirects the echo command's error output from stderr to stdout, combining them into a single stream. This one is often useful if you want to run all the output through a single pipe rather than having them treated separately. echo "hello" 2>&1 | tee log
, for example, captures a copy of both normal output and error messages into a single log file.
BroSlow points out that, in version 4 and later of the bash
shell, |&
can be used as a shorthand for combining the streams, equivalent to 2>&1
. Good to know. (I still move between shells too frequently to have started using that one.)
Is it possible to redirect stdout to a non-stderr stream inside a shell script?
For completeness, based on tripleee's comment, what I actually wanted was the following:
#!/bin/bash
echo "Send me to standard out"
echo "Send me to standard err" >&2
if ! (printf '' 1>&3) 2>&-; then
# File descriptor 3 is not open
# Option 1: Redirect fd3 to stdout.
exec 3>&1
# Option 2: Redirect fd3 to /dev/null.
# exec 3>/dev/null
fi
# No error here.
echo "Send me to stream 3" >&3
With this modification, a parent process can redirect 3 when it desires to do so, and otherwise have it as part of stdout.
$ ./Play.sh
Send me to standard out
Send me to standard err
Send me to stream 3
$ ./Play.sh 3> /dev/null
Send me to standard out
Send me to standard err
Related Topics
How to Find Which Type of System Call Is Used by a Program
How to Clear Space on My Main System Drive on a Linux Centos System
Cross-Compilation to X86_64-Unknown-Linux-Gnu Fails on MAC Osx
Gui Svn Client for Debian Linux
Does There Exist Kernel Stack for Each Process
Tar Command Changing The Owner:Group While Extracting
Linux X86 Nasm - Subroutine: Print a Dword from Eax
Webdrivererror Error: Chrome Failed to Start: Exited Abnormally
Need Explanation on Pri Standard Format Specifier for Ps - Possible Bug in Documentation
Get .Net Core Dll Version on Linux
Libv4L2: Error Turning on Stream: No Space Left on Device
Base Address at Which The Linux Kernel Is Loaded