Io-Redirection

重定向 Ruby 腳本的 stderr 未按預期工作

  • December 10, 2016

我有一個我認為正在輸出的命令,stderr因為當我重定向stdout到時,/dev/null我仍然會將輸出列印到螢幕上。

但是,當我重定向stderr到時,/dev/null我也會將輸出列印到螢幕上。

此外,當我將所有輸出重定向到/dev/nullthen 時,它按預期工作。

怎麼會這樣?應該至少抓住1>一些?2>``&>

一個例子可以在下面看到:

$ 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
$ 

要複製,請複製我的項目:

➜  ~/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 ✓

這是該腳本使用的 Ruby 日誌記錄庫美沙酮的一個特性。根據標準輸出和標準錯誤是否是終端,它的行為會有所不同。

initialize方法cli_logger.rb。如評論中所述:

將錯誤類型消息記錄到第二個設備的記錄器;對於確保錯誤消息進入標準錯誤很有用。這對於做正確的事情應該是非常聰明的。如果兩個日誌設備都是 tty,例如,一個進入標準錯誤,另一個進入標準輸出,則消息在整個輸出流中只出現一次。換句話說,記錄的 ERROR 將顯示在標準錯誤中。如果任一日誌設備不是 tty,則所有消息都轉到 +log_device+,只有錯誤轉到 +error_device+

您可能會質疑“做正確的事情非常聰明”的說法。日誌記錄模組的更明智的預設設置是記錄到標準錯誤並忽略標準輸出。

引用自:https://unix.stackexchange.com/questions/329370