期待どおりに動作しないRubyスクリプトのstderrリダイレクト

期待どおりに動作しないRubyスクリプトのstderrリダイレクト

出力中と思われるコマンドがあります。これは、コマンドにstderrリダイレクトしても出力が画面に印刷されるためです。stdout/dev/null

stderrただし、にリダイレクトすると、/dev/null画面に出力も印刷されます。

また、すべての出力をthenにリダイレクトすると、期待/dev/nullどおりに機能します。

どうやって?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 ✓

答え1

これはRubyロギングライブラリの機能です。メタドンこのスクリプトで使用されます。標準出力と標準エラーが端末かどうかによって動作が異なります。

initialize方法を見るcli_logger.rb。コメントで説明されているように:

エラータイプメッセージを2番目のデバイスのロガーに書き込みます。エラーメッセージが標準エラーに移動することを確認するのに役立ちます。正しいことをするには非常に合理的でなければなりません。両方のログデバイスがttyの場合(たとえば、1つは標準エラー用、もう1つは標準出力用)、メッセージは出力ストリーム全体で一度だけ表示されます。つまり、記録されたエラーが表示されます。ただ標準エラーから。ログデバイスの1つがttyでない場合、すべてのメッセージは+ log_device +に送信され、エラーのみ+ error_device +に送信されます。

正しいことをするのが賢明であるという言葉に問題が生じる可能性があります。ロギングモジュールのより合理的なデフォルトはstderrに書き込んでstdoutを無視することです。

関連情報