0

I am running the following command in a script:

kubectl cp -n $OVN_NAMESPACE -c ovnkube-node $ovnkube_node:$save_dir ${WORKDIR}/restore_flows

However, it outputs to stderr "tar: Removing leading `/' from member names" everytime it runs. Aside from this it runs fine, however, I need to remove this error message. I would just send all stderr to /dev/null, but I want other errors that might actually matter to be remain.

Therefore, my question is is it possible to remove a specific error message from the output using grep or sed and allow others through?

  • 3
    Redirect stderr to stdout with `2>&1`. Then you can pipe this to `grep -v`. – Barmar Oct 26 '21 at 16:18
  • When I do [command] 2>&1 | grep -v "unwanted error message" the script stops running after the command is completed. Any clue why that might be? –  Oct 26 '21 at 16:24
  • 1
    No reason I can think of. – Barmar Oct 26 '21 at 16:26
  • Strange. It runs fine if the grep doesnt find a match, but when it does it stops running. –  Oct 26 '21 at 16:31
  • 3
    See [How can I pipe stderr and not stdout?](https://stackoverflow.com/q/2342826/15168) for discussion about piping stderr. See [How can. I exclude all "permission denied" messages from `find`?](https://stackoverflow.com/q/762348/15168) for a discussion of filtering stderr. – Jonathan Leffler Oct 26 '21 at 16:31
  • 1
    @sdaniele I don't know `kubectl`. is it possible it's prompting you to answer a question? It may write the prompt to `stderr`, and buffering is preventing you from seeing it. – Barmar Oct 26 '21 at 16:33
  • Does `2> >(cat >&2)` work? If so, we know that in `2> >(grep -v "whatever" >&2)` it isn't the `grep` causing trouble. – Charles Duffy Oct 26 '21 at 16:35
  • 2
    Actually, I might know the problem -- if you have `set -e` enabled, then `grep -v` can return a nonzero return status if there are no messages on stderr at all. [In general, `set -e` is a bad idea.](http://mywiki.wooledge.org/BashFAQ/105) – Charles Duffy Oct 26 '21 at 16:36
  • Nope, it is just coping from a kubernetes pod to the local system, which produces the tar error I want to remove. When I run grep w/o the -v option it works fine. with the -v option the program just stops running –  Oct 26 '21 at 16:36
  • Use the process-substitution form I mentioned above, not the pipeline form; that way `grep` doesn't change the exit status of the compound command. – Charles Duffy Oct 26 '21 at 16:36
  • Would it be simpler to create the tar file without the absolute file names (leading slash) so that the error message is not generated? – Jonathan Leffler Oct 26 '21 at 16:39
  • @CharlesDuffy, yes I do have -e set for other reasons. That being said 2> >(cat >&2) works, however 2> >(grep -v "whatever" >&2) does not remove lines containing "whatever" –  Oct 26 '21 at 16:43
  • @JonathanLeffler definitely, however this would require me to copy the files first into the main working directory of the k8 pod. Since they can be large database files, this is pretty impractical –  Oct 26 '21 at 16:44
  • Can you persuade those who build the tar file on your behalf to do the job properly — without the absolute file names? It's quite probable that you're not the only person suffering from headaches as a result of their carelessness. – Jonathan Leffler Oct 26 '21 at 16:46
  • Sorry let me clarify, it is not a tar file, I am running kubectl cp which it would seem relies on tar to extract the files locally. I am not actually using tar directly (or I could do something like -C) –  Oct 26 '21 at 16:50
  • Take a good look at the GNU `tar` manual. Consider whether the [`--warnings=none`](https://www.gnu.org/software/tar/manual/tar.html#warnings) option could help — possibly in conjunction with the `TAR_OPTIONS` environment variable. – Jonathan Leffler Oct 26 '21 at 17:06
  • 1
    @sdaniele `errfunc() { printf '%s\n' "first line" "whatever" "third line" >&2; }; errfunc 2> >(grep -v whatever >&2)` successfully strips `whatever` while leaving `first line` and `third line`. I'd need to see a [mre] demonstrating how it fails before I could start to speak to a solution. (Are you certain the error is actually written to stderr, not stdout?) – Charles Duffy Oct 26 '21 at 19:56

2 Answers2

1

The following two methods will only process stderr and do not

1. Process stderr in a subshell:

$ kubectp cp ... 2> >(grep -v 'unwanted error' - )

2. Use redirection swapping to filter stderr:

$ { kubectp cp ... 2>&1 1>&3 | grep -v 'unwanted error' - 1>&2; } 3>&- 3>&1

This does the following:

  • run command kubectp cp ...
  • redirect the output of stdout into fd3 (1>&3) and redirects stderr into stdout (2>&1)
  • process the new stdout (the actual stderr) with grep and redirect the output back to stderr (1>&2)
  • finally, we redirect the output of fd3 back into stderr (3>&1) and close fd3 (3>&-)
kvantour
  • 25,269
  • 4
  • 47
  • 72
0

Thanks @CharlesDuffy, solved it with a slight workaround on your answer since I didn't want to turn off set -e:

kubectp cp .... 2>&1 | grep -v 'unwanted error' || true >&2