Test stdout and stderr redirection in bash script

2019-02-11 20:15发布

问题:

I would like to test in my bash script where stdout and stderr are directed, or more precisely, if they have been redirected.

Have you an idea ?

The $* bash variable don't give me this info.

回答1:

You should be able to use the -t test switch to tell if the output streams are ttys or not:

if [ -t 1 ] ; then
  echo stdout is a terminal
else
  echo stdout is not a terminal
fi

Use -t 0 for stdin.

Use -t 2 for stderr.



回答2:

Technically there is no way of telling whether stdin/stdout/stderr are "redirected" because you don't know what's invoking your script. If it's not being invoked from another shell, there is no concept of "redirection".

All you have to go on is what types the in/out/err file descriptors are (terminal, fifo, pipe, device, file etc). Normally you just want to detect whether your output is going to some user's screen or whether it's going to another process. In this case use [ -t 1 ] as per Mat's answer.

If you want to find out where/what your process has been redirected to, examine the targets of the symlinks /proc/$$/fd/1 and /proc/$$/fd/2.

Note that someone could connect the output of your process to a different terminal with ./myscript.sh > /dev/pts/1234. Then it would be "redirected", but stdout would still be a terminal.

Examples:

$ ls -l /proc/$$/fd/1 > results
$ bash -c 'ls -l /proc/$$/fd/1 >>results' > /dev/null
$ bash -c 'ls -l /proc/$$/fd/1 >>results' |cat 
$ bash -c 'ls -l /proc/$$/fd/1 >>results' > /dev/pts/0
$ cat results 
lrwx------ 1 je4d je4d 64 2012-02-17 21:09 /proc/2463/fd/1 -> /dev/pts/11
l-wx------ 1 je4d je4d 64 2012-02-18 13:17 /proc/8302/fd/1 -> /dev/null
l-wx------ 1 je4d je4d 64 2012-02-18 13:17 /proc/8304/fd/1 -> pipe:[222798]
l-wx------ 1 je4d je4d 64 2012-02-18 13:17 /proc/8307/fd/1 -> /dev/pts/0

[ -t 1 ] would be true for the 1st and 4th of those.