質問
このコマンドは何をしますか?
exec 2>&1
解決
技術的に言えば、stderrをstdoutに複製またはコピーします。
通常、これを実行するのにEXECは必要ありません。 execとファイル記述子のより一般的な使用法は、未使用のファイル記述子にファイルを割り当てることを示すことです。例:
exec 35< my_input
ところで、ファイルにパイピングするときの宣言のシーケンスが重要であることを忘れないでください。
ls > mydirlist 2>&1
stdoutとstderrの両方をファイルmydirlistに送信するので、コマンドは動作します
ls 2>&1 > mydirlist
stderrはmydirlistにリダイレクトされる前にstderrがstdoutのコピーを作成したため、stderrではなくstdoutのみをmydirlistに転送します。
編集:これは、シェルが左から右にスキャンする方法です。だから、「stderrをstdoutにコピー」と言って2番目のものを読んでください。 「標準出力をmydirlistに送信する」と言う前に。次に、「stdoutをファイルmydirlistに送信」と言って最初のものを読みます。 「設定した標準出力にstderrを複製する」と表示される前。知っている。まったく直観的ではありません!
他のヒント
&quot; 2&gt;&amp; 1&quot;で見たより良い記事の1つ Bash One-Linersの説明、パートIII:リダイレクトについて。
しかし、この質問に関する現在の答えが提供できないのは、単純な「exec」の後にこれを行いたい理由です。 execコマンドのbashのマニュアルページで説明されているように、「コマンドが指定されていない場合、リダイレクトは現在のシェルで有効になります」
出力の行をstdoutに書き込み、別の行をstderrに書き込む out-and-err.py
という簡単なスクリプトを書きました:
#!/usr/bin/python
import sys
sys.stdout.write('this is stdout.\n')
sys.stderr.write('this is stderr.\n')
そして、それを&quot; exec 2&gt;&amp; 1&quot;でout-and-err.shというシェルスクリプトにラップしました:
#!/bin/bash
exec 2>&1
./out-and-err.py
Pythonスクリプトのみを実行する場合、stdoutとstderrは別々です:
$ ./out-and-err.py 1> out 2> err
$ cat out
this is stdout.
$ cat err
the is stderr.
しかし、シェルスクリプトを実行すると、execがすべての後のstderrを処理することがわかります:
$ ./out-and-err.sh 1> out 2> err
$ cat out
this is stdout.
this is stderr.
$ cat err
$
ラッピングシェルスクリプトが1つのpythonコマンドだけではなく、すべての出力をstdoutに結合する必要がある場合、&quot; exec 2&gt;&amp; 1&quot;を実行します。簡単になります。
標準エラーを標準出力に関連付けます
2
はstderrで、 1
はstdoutです。プログラムを実行すると、stdoutに通常の出力が表示されますが、エラーや警告は通常stderrに送られます。たとえば、すべての出力をファイルにパイプする場合、最初にstderrとstdoutを 2&gt;&amp; 1
で結合すると便利です。
@cmaが言ったように、stderrをstdoutに置きます。この動作が必要な理由は、grepまたはその他のユーティリティを使用して、stderrにのみ表示される出力をキャプチャするためです。または、後で処理するために、stderrを含むすべての出力をファイルに保存することもできます。
exec 2&gt;&amp; 1
の非常に便利なアプリケーションの1つは、 stderr
と stdout
をマージする場合です。セミコロンで区切られたいくつかのコマンド。私の特定の例は、PHPで複数のコマンドを popen
に送信しているときに発生し、シェルプロンプトでコマンドを入力した場合と同じように、エラーがインターリーブされたことを確認しました:
$ echo hi ; yikes ; echo there
hi
-bash: yikes: command not found
there
$
次のコードは、最後の echo
( yikes
のため無意味です)を除いて、 stderr
と stdout
をマージしません。 >エラーの原因):
echo hi ; yikes ; echo there 2>&1
「ハードな方法」でマージされた出力を取得できます。次のとおりです。
echo hi 2>&1; yikes 2>&1; echo there 2>&1
exec
を使用すると、見た目がすっきりし、エラーが発生しにくくなります:
exec 2>&1 ; echo hi; echo yikes; echo there
セミコロンで区切られた3つのコマンドを実行した場合、ターミナルで表示されるのとまったく同じように、 stdout
および stderr
の出力がうまくインターリーブされます。
私もこの問題に嫌気がさしていましたが、今はその問題から飛び出しました。
ですから、CLIで exec 1&gt;&amp; 2
を入力した後に何が起こるか説明させてください。
問題を少しずつ破壊したいので、知識を知っている場合は、時間を節約するためにそれをざっと読んでください。
-
exec
とは:
exec
は、Linuxの組み込みコマンドです。サブシェルプロセスをフォークするだけの従来のコマンドとは異なり、 exec
は現在のシェルプロセスを変更できます。
-
I / Oリダイレクトとは: リダイレクトはLinuxの機能です。これにより、標準の入力/出力デバイスを変更できます。 Linuxには、デフォルトで3つのファイル記述子があります。 <コード> ハンドル名説明 0 stdin標準入力 1 stdout標準出力 2 stderr標準エラー
-
例を見てみましょう:
- 新しいターミナルを開く
- 端末プロセスプロセスIDを取得する
$ pstree -p | grep 'term' | tr -d ''
- プロセスファイル記述子を確認します。
$ sudo ls -l / proc / {pid} / fd
bash $ pstree -p | grep -i '端末' | tr -d '' |||| -gnome-terminal-(6008)-+-bash(7641)-+-grep(8355) $ sudo ls -l / proc / 7641 / fd 合計0 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 0-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 1-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 2-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 255-&gt; / dev / pts / 3
ご覧のとおり、ls
にはPID(6860)プロセスファイルがリストされています。最初はすべて番号(0、1、2)で名前を付け、2番目はすべて/ dev / pts / 3へのファイルリンクをリンクします。これは、pts3にすべての標準入力/出力/エラーが表示されることを意味します。 - 標準出力を/ tmp / stdoutに変更します
bash $ ls / tmp / stdout ls: '/ tmp / stdout'にアクセスできません:そのようなファイルまたはディレクトリはありません $ exec 1&gt; / tmp / stdout $ ls $ pwd $ echo&quot; Are you ok&quot; $
その時点でコマンド出力は消えていました。 - procファイルを確認するには、新しいターミナルを開きます
bash $ sudo ls -l / proc / 7641 / fd 合計0 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 0-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 1-&gt; / tmp / stdout lrwx ------ 1 alopex alopex 64 Oct 27 19:39 2-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 255-&gt; / dev / pts / 3
明らかに、1(ファイル記述子)が/ tmp / stdoutへのリンクを既に変更していることに気付くことができます。例外として、標準出力は/ tmp / stdoutに転送されます - リダイレクトを復元します。
bash $ exec 1&gt;&amp; 2 $ cat / tmp / stdout 灰 / home / alopex 大丈夫ですか $ sudo ls -l / proc / 7641 / fd 合計0 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 0-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 1-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 2-&gt; / dev / pts / 3 lrwx ------ 1 alopex alopex 64 Oct 27 19:39 255-&gt; / dev / pts / 3
繰り返しますが、1(ファイル記述子)は/ dev / pts / 3にリンクしています。出力をもう一度見ることができます。
-
概要:
-
exec 1&gt;&amp; 2
は標準出力を作成します---&gt;標準エラー