1

I have a command that I think is outputting to stderr because when I redirect stdout to /dev/null I still get output printed to the screen.

However, when I redirect stderr to /dev/null I also get output printed to the screen.

Further, when I redirect all output to /dev/null then it works as expected.

How can this be? Should 1> and 2> catch at least some of &>?

An example can be seen below:

$ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': fatal: destination path 'fake-dotfiles' already exists and is not an empty directory.
Error running 'git clone https://github.com/mbigras/fake-dotfiles'
checkout dir already exists, use --force to overwrite
$ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles 1>/dev/null
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': fatal: destination path 'fake-dotfiles' already exists and is not an empty directory.
Error running 'git clone https://github.com/mbigras/fake-dotfiles'
checkout dir already exists, use --force to overwrite
$ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles 2>/dev/null
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': fatal: destination path 'fake-dotfiles' already exists and is not an empty directory.
Error running 'git clone https://github.com/mbigras/fake-dotfiles'
checkout dir already exists, use --force to overwrite
$ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles &>/dev/null
$ 

To replicate please clone my project:

➜  ~/D/w/tmp  rm /tmp/fakehome
➜  ~/D/w/tmp  mkdir /tmp/fakehome
➜  ~/D/w/tmp  git clone https://github.com/mbigras/mb-fullstop
Cloning into 'mb-fullstop'...
remote: Counting objects: 150, done.
remote: Compressing objects: 100% (84/84), done.
remote: Total 150 (delta 49), reused 147 (delta 46), pack-reused 0
Receiving objects: 100% (150/150), 24.06 KiB | 0 bytes/s, done.
Resolving deltas: 100% (49/49), done.
Checking connectivity... done.
➜  ~/D/w/tmp  cd mb-fullstop
➜  mb-fullstop master ✓ git checkout fix-git-logging-to-stderr
Branch fix-git-logging-to-stderr set up to track remote branch fix-git-logging-to-stderr from origin.
Switched to a new branch 'fix-git-logging-to-stderr'
➜  mb-fullstop fix-git-logging-to-stderr ✓ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': Cloning into 'fake-dotfiles'...
➜  mb-fullstop fix-git-logging-to-stderr ✓ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': fatal: destination path 'fake-dotfiles' already exists and is not an empty directory.
Error running 'git clone https://github.com/mbigras/fake-dotfiles'
checkout dir already exists, use --force to overwrite
➜  mb-fullstop fix-git-logging-to-stderr ✓ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles 1> /dev/null
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': fatal: destination path 'fake-dotfiles' already exists and is not an empty directory.
Error running 'git clone https://github.com/mbigras/fake-dotfiles'
checkout dir already exists, use --force to overwrite
➜  mb-fullstop fix-git-logging-to-stderr ✓ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles 2> /dev/null
stderr output of 'git clone https://github.com/mbigras/fake-dotfiles': fatal: destination path 'fake-dotfiles' already exists and is not an empty directory.
Error running 'git clone https://github.com/mbigras/fake-dotfiles'
checkout dir already exists, use --force to overwrite
➜  mb-fullstop fix-git-logging-to-stderr ✓ HOME=/tmp/fakehome/ bundle exec bin/fullstop https://github.com/mbigras/fake-dotfiles &> /dev/null
➜  mb-fullstop fix-git-logging-to-stderr ✓
  • 2> should do the work, can you post the calling of the script – Wissam Roujoulah Dec 10 '16 at 8:45
  • Hi @WissamAl-Roujoulah thanks for the comment, please see edit – mbigras Dec 10 '16 at 8:56
  • @WissamAl-Roujoulah added edit, please let me know if you'd like me to clear it up. I'm using a custom prompt, will change it to $ if you're having trouble seeing where the prompt ends and the command begins :) – mbigras Dec 10 '16 at 9:13
  • Interesting, i can't replicate your errors because i don't have ruby installed in my machine – Wissam Roujoulah Dec 10 '16 at 9:19
0

This is a peculiarity of the Ruby logging library methadone used by that script. It behaves differently depending on whether standard output and standard error are terminals.

See the initialize method of cli_logger.rb. As described in the comments:

A logger that logs error-type messages to a second device; useful for ensuring that error messages go to standard error. This should be pretty smart about doing the right thing. If both log devices are ttys, e.g. one is going to standard error and the other to the standard output, messages only appear once in the overall output stream. In other words, an ERROR logged will show up only in the standard error. If either log device is NOT a tty, then all messages go to +log_device+ and only errors go to +error_device+

You may dispute the assertion that it is “pretty smart about doing the right thing”. A more sensible default for a logging module would log to stderr and ignore stdout.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.