2

I have a bash script that has a print function, like this:

print(){
  [ $quiet == 1 ] && return
  type=$1; shift
  message="$*"; shift $#
  # shellcheck disable=SC2086
  if [ $type -eq 1 ]; then
    echo "$message"
  else
    >&2 echo "$message"
  fi
}

In a nutshell it receives 2 parameters, the first is the type, if 1 it will print the message on the screen (stdout), else (in that case 2) it will print the message on the stderr. Also, I have a quiet var that says that if my program is called with -q, it will not print anything on the screen whether its stdout or stderr (the function returns).

The problem is that throughout my program when I run commands, I run them more or less like below:

ip link add "${interface}" &&
  print 1 " interface ${interface} added successfuly." ||
  { print 2 "  interface ${interface} could not be added."; return 1; }

It works fine (success message is printed) if the command runs without error (meaning $? == 0) but if my quiet var is 1 and the command runs with error (meaning $? != 0) it will not print my message from the print() instruction (as expected), but it will print the error from the command itself, for example, RTNETLINK answers: File exists.

Ideally, what I wanted was to not just run all my commands with 2> /dev/null since the error messages can be important, but I would like to redirect them to my print() function with the type 2, so they would be printed on stderr only if my quiet var is 0. As if I ran a program with 2> $(print 2 "RTNETLINK answers: File exists") even though I know that this doesn't make since.

I thought about doing something like:

ip link add "${interface}" 2> /var/tmp/myprog.output || print 2 $(cat /var/tmp/myprog.output)

But 1) I would prefer not to use the filesystem for that and 2) there must be a more elegant way.

Any ideas?

Adriano_Pinaffo
  • 1,429
  • 4
  • 23
  • 46

1 Answers1

0

You could capture the stderr of the command and pass it to print.

print 2 "$(ip link add '${interface}' 2>&1 > /dev/null)"

programmer
  • 743
  • 4
  • 10
  • But you are redirecting stdout and stderr to null and passing nothing to print(). No? – Adriano_Pinaffo Oct 14 '20 at 02:06
  • 1
    @Adriano_Pinaffo That should capture the `stderr` by redirecting it as `stdout` and direct the original `stdout` to `/dev/null`. – programmer Oct 14 '20 at 02:08
  • but in that case, I'm always passing the print parameter as 2... but that should only be two when there was an error with the program – Adriano_Pinaffo Oct 14 '20 at 02:20
  • In that case you would have to somehow capture both and check if the `stderr` is empty to decide what to print, but I don't think that's possible without running the command twice. – programmer Oct 14 '20 at 02:22
  • damn, maybe I will have to run the command and redirect stdout to a output.stdout file and stderr to output.stderr file and print whatever is not empty – Adriano_Pinaffo Oct 14 '20 at 02:28