The problem using output redirection >/dev/null as a variable in Bash Shell script

Written by - 0 comments

Published on - Listed in Coding Bash Linux Shell


While working on a script to monitor a SFTP server, I wanted to add a verbose switch to the script. The idea would be that by toggling a "-v" parameter, the SFTP commands are shown at the output of the script.

The following Bash script was created for this purpose:

#!/bin/bash
verbose=false
[...]
if [ "${verbose}" = true ]; then
  stdoutredir=""
else
  stdoutredir=">/dev/null"
fi
[...]
# Establish connection and make sure the directory exists on the SFTP server
sftp -b - -P ${port} ${user}@${host} <<EOF "${stdoutredir}" 2>&1
cd ${directory}
exit
EOF

The idea was that the sftp command line would look like this in a "normal" (without verbose) way:

sftp -b - -P ${port} ${user}@${host} <<EOF >/dev/null 2>&1

Note: Writing >/dev/null without a variable works!

But with verbose set to true, the >dev/null redirect would disappear and lead to the output of the sftp commands:

sftp -b - -P ${port} ${user}@${host} <<EOF 2>&1

But this failed. Whatever I tried, the sftp commands were still shown in the output, both toggling verbose and non-verbose modes with the -v parameter:

$ ./check_sftp.sh -H sftpserver.example.com -u sftpuser
sftp> cd monitoring
sftp> exit

$ ./check_sftp.sh -H sftpserver.example.com -u sftpuser -v
sftp> cd monitoring
sftp> exit

While this works fine without using a variable (with a hard-coded ">/dev/null"), it does not when using ">/dev/null" as a value from a variable. The reason for this is that the output redirection using ">/dev/null" cannot be put into a variable, as the > is a special symbol inside the Shell and cannot be parsed from a variable's value:

The reason you can't cause redirection to occur by expanding "$HideErrors" is that symbols like > aren't treated specially after being produced by parameter expansion. - Eliah Kagan on Ask Ubuntu

Reading this explanation twice and it makes sense. D'oh!

In order to define an output redirect, the ">" character needs to stay in place, as this is the part actually causing the output redirect. But what follows (/dev/null, /dev/stdout or anything else) can be, in fact, a variable.

Rewriting this in the code now results in:

[...]
if [ "${verbose}" = true ]; then
  stdoutredir="/dev/stderr"
else
  stdoutredir='/dev/null'
fi
[...]
# Establish connection and make sure the directory exists on the SFTP server
sftp -b - -P ${port} ${user}@${host} <<EOF >${stdoutredir} 2>&1
cd ${directory}
exit
EOF

This now results in a real verbose and non-verbose mode where the (s)ftp commands can be seen (in verbose) or omitted (in normal) mode:

$ ./check_sftp.sh -H sftpserver.example.com -u sftpuser
CHECK_SFTP OK: Communication to sftpserver.example.com worked. Upload, Download and Removal of file (mon.1671734205) into/from remote directory (monitoring) worked.

$ ./check_sftp.sh -H sftpserver.example.com -u sftpuser -v
sftp> cd monitoring
sftp> exit
sftp>
sftp> cd monitoring
sftp> put /tmp/mon.1671734237
sftp> get mon.1671734237
sftp> rm mon.1671734237
sftp> exit
CHECK_SFTP OK: Communication to sftpserver.example.com worked. Upload, Download and Removal of file (mon.1671734237) into/from remote directory (monitoring) worked.














Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.