シェルスクリプトに出てくる「2>&1」ってなんですか?【エラーログの保存に使えます】
シェルスクリプトを書くために勉強をしていると
時々行末に「2>&1」という記号を見かけると思います。
プログラミング初心者には意味不明なこの呪文について解説をしたいと思います。
この呪文はファイルディスクリプタと呼ばれる番号"1, 2"と
リダイレクト">"から成り立っているのでこの2つについてをまず解説します。
コマンドによる出力には”標準出力”と”標準エラー出力”の2種類がある
コマンドecho
を例に説明します。
まず、echo
で”Hello”と表示させてみましょう。
$echo "Hello" Hello
"Hello"と問題なく出力されます。
これが標準出力です。
次に存在しないコマンドaaa
を行ってみると
$aaa "Hello" -bash: aaa: command not found
"aaaというコマンドはありません"というエラーメッセージが出ます。
これが標準エラー出力です。
上記の "標準出力"と "標準エラー出力"にはそれぞれ"1" "2"という番号が与えられており、この番号をファイルディスクリプタと呼びます。
この番号と">(リダイレクト)"を使うことでそれぞれの出力を呼び出すことができます。
リダイレクトとはコマンドの出力先を変更する記号で
> (file名).txtとすることで指定したファイルにコマンドの結果を出力することができます。
それでは、echo
の標準出力と標準エラー出力を2つのファイルにリダイレクトしてみましょう。
$ echo "Hello" 1>result.txt 2>error.txt $ cat result.txt Hello $ cat error.txt $
echo "Hello"
によって出力される"Hello"はresult.txtにリダイレクトされたため、
これまでと異なりecho
後、ターミナル上には表示されません。
その代わりにcat
でresult.txtファイル内を開くと
"Hello" と書き込まれていることがわかります。
echo "Hello"
ではエラーが出ませんので
error.txtには何も書き込まれていません。
次に、エラーが出るaaa
というコマンド(?)を使ってみましょう。
$aaa "Hello" 1>result.txt 2>error.txt $cat error.txt -bash: aaa: command not found $cat result.txt $
aaa "Hello!"
で出力されるエラーメッセージは
error.txtに書き込まれていました。
aaa
は存在しないコマンドでエラー以外に出力される結果はありませんので、
result.txtファイルには何も書き込まれていません。
2>&1は標準エラー出力を標準出力と一緒に出力させる
上記の内容から"2>&1"が標準エラー出力(2)を標準出力(1)にリダイレクトさせているということはなんとなくわかると思います。
では&とは何でしょうか。
&なしで以下のコマンドを実行してみると
$echo "Hello" 2>1 "Hello"
とくに何も起こらないように見えますが
カレントディレクトリに[1]というファイルが新たに出現しています。
しかし、このファイルには何も書かれていません。
$cat 1 $
これはecho "Hello"
の標準エラー出力(2)を[1]というファイルにリダイレクトしたために生まれたファイルであり、エラーメッセージが出ないのでファイルは空です。
そのため、エラーメッセージの出るaaa
を使うと
$aaa "Hello!" 2>1 $cat 1 -bash: aaa: command not found
[1]というファイルにはエラーメッセージが書き込まれました。
では&とは一体なんなのでしょうか。
これはマージを意味しており、
「標準出力と標準エラー出力をまとめて出力する」を意味しています。
そのため、 2>&1を使えば標準出力と標準エラー出力をまとめてresult.txtファイルに書き込むことができます。
$echo "Hello" >result.txt 2>&1 $cat result.txt Hello $aaa "Hello" >result.txt 2>&1 $cat result.txt -bash: aaa: command not found
echo
の標準出力もaaa
の標準エラー出力もresult.txt内に保存することができました。
これをシェルスクリプト内で使えばエラーメッセージが出た場合には指定のファイルにログを保存させることができますのでデバックする際などに役立てることができます。
おまけ・リダイレクトの種類
リダイレクトはシェルスクリプトを書く際に大事な手法なので
使い方をまとめた表をhttps://eng-entrance.com/linux-redirect様より転載させていただきました。
この機会に覚えておきたいですね。
コマンド > ファイル | コマンド結果をファイルへ書き込む |
コマンド < ファイル | ファイルの中身をコマンドの標準入力へ |
コマンド >> ファイル | コマンドの出力結果をファイルへ追記 |
コマンド 2> ファイル | エラー出力をファイルへ書き込む |
コマンド 2>> ファイル | ファイルにエラー出力を追記 |
コマンド > ファイル 2>&1 | ファイルに標準出力と標準エラー出力を書き込む |
コマンド >> ファイル 2>&1 | ファイルに標準出力と標準エラー出力を追記 |
コマンド << 終了文字 | 終了文字が現れるまで標準入力へ送る |
コマンド &> ファイル | 標準出力と標準エラー出力を同じファイルに書き込む |
コマンド > /dev/null 2>&1 | 表示をしない。(表示をゴミ箱へ) |
https://eng-entrance.com/linux-redirectより引用
参考
https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea