シリアルケーブルなしでシリアルコンソール出力をローカルファイルに保存する方法

シリアルケーブルなしでシリアルコンソール出力をローカルファイルに保存する方法

私は組み込みLinuxを実行しており、コマンドラインにconsole=/dev/ttyO0,...このUARTに接続されたターミナルプログラムがあり、表示できます。すべてシステムによって生成されます。

これで、ライブを実行するときにこれらのすべての出力をファイルに保存したいと思います(メディアが接続されています)。しかしsyslogd、とCo.を使用したすべての努力は私が望む結果を得ていませんでした。一部のメッセージは保存されましたが、一部は保存されませんでした。一般的に最も重要なメッセージですklogdlogger

たとえば、次のように実行すると:

myapplication.sh | logger        

echoまた、アプリケーションのコマンドsyslogといくつかのドライバメッセージが表示されます。printただし、分割エラーが原因でアプリケーションがクラッシュした場合、この情報は記録されません。しかし、これが最も貴重なものです!

もしそうなら、あなたが一番いいと思うのは、ファイルttyO0にリダイレクトすることです。しかし、どうすればいいですか?

次のおすすめを見つけました。

(stty raw; cat > received.txt) < /dev/ttyO0

しかし、これはうまくいきません。たとえば、コマンドを入力できますが、ifconfig応答はファイルやコンソールには表示されません。ファイルが生成されなくても... :-(

ファイルとシリアルコンソールの両方を持つことができれば良いでしょう。ただし、ファイルの優先順位が高くなります。

助けてくれてありがとう!

修正する解決策を見つけて回答セクションに追加しました。

ベストアンサー1

あなたはやや基本的な事実を見落としているようです。パイプライン可能なすべてのプログラムは、次の事実に依存します。サム標準ファイル記述子は、それを呼び出すプログラムに関係なく、事前に開かれています。パイプに関連するほとんどの場合、呼び出し側プログラムはコマンドシェルになります。

3つのファイル記述子は次のとおりです。

  • ファイル記述子#0:標準入力ストリームまたはstdin簡単に説明します。
  • ファイル記述子#1:標準出力ストリームまたはstdout単に。
  • ファイル記述子#2:標準エラー出力ストリーミングするか、stderr単に。

プログラムがファイルの読み取り/書き込みにパイピングまたはリダイレクトしない場合、通常、3つのファイル記述子はすべて現在ログインセッションが実行されているTTYデバイスを指します。プログラムが意図的にデーモンまたはバックグラウンド/非対話型プロセスで開始された場合、これらすべてがファイル、/dev/nullまたは一種のロギングツールに渡される可能性があります。

エラーメッセージは、通常、stderrパイプで接続されたデータ出力と混在しないようにストリームに出力されます。しかし、あなたと同じ場合は、キャプチャしたいときみんな出力の場合は、両方のストリームを取得するようにシステムに明示的に通知する必要があります。

すべての出力をパイプに渡すには、myapplication.sh次のことを行う必要があります。

myapplication.sh 2>&1 | logger

「ファイル記述子#2を#1と同じ場所にリダイレクトする」とマークされた後、2つの2>&1ファイルを同時にパイプできます。

次の小さなスクリプトを使用して直接テストできます。

#!/bin/sh
echo "this is stdout"
echo "this is stderr" >&2

>&2「このコマンドの標準出力を取得し、標準エラーストリームに送信します」を意味します。これはおそらくstderrスクリプトから出力を生成する最も簡単な方法です。

このスクリプトを実行して./test.sh | od -t x1z16進ダンプ形式の出力を取得すると、次のような結果が得られます。

$ ./test.sh | od -t x1z
this is stderr
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a     >this is stdout.<
0000017

したがって、コマンドはstdout出力のみを処理しますod

2>&1両方のストリームをマージするために追加すると、次の結果が得られます。

$ ./test.sh 2>&1 | od -t x1z
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a 74  >this is stdout.t<
0000020 68 69 73 20 69 73 20 73 74 64 65 72 72 0a        >his is stderr.<
0000036

これで、両方の出力がパイプに送信されます。これは| logger


2番目のコマンドラインは、組み込みデバイスが端末に送信するのではなく、組み込みデバイスが端末プログラムから受け取るすべてをキャプチャします。

(stty raw; cat > received.txt) < /dev/ttyO0

カーネルパラメータを使用する組み込みシステムを開発していると言うと、console=/dev/ttyO0本質的に/dev/consoleグラフィックディスプレイ(組み込みデバイスには存在しない可能性があります)ではなくシリアルポートになります。

内蔵デバイスでこのコマンドを実行する場合、括弧内のコマンドは次のようになります。標準入力ストリーム(ファイル記述子#0またはstdin単に)がに割り当てられます/dev/ttyO0。ただし、に接続されているシリアルラインを介してコマンドを入力すると、デフォルトでこのようなttyO0場合が発生する可能性があるため、この入力リダイレクトは状況をそのまま再適用できます。 。

この/dev/ttyO0デバイスは、他のコンピュータの端末プログラムに接続されたUARTを直接表現したものです。読めば手に入る端末プログラムに入力した内容のみ:以前に送信された出力を再読み込みできません。ここに書かれているすべての内容は、シリアルケーブルの端にある端末プログラムに直接渡されます。

シリアルポートのUnixコマンドラインは通常次のとおりです。リモートエコー仕組み:ターミナルプログラムに書いた内容を表示するには、組み込みシステムのTTYドライバは、ユーザーが入力したすべての文字のコピーをターミナルプログラムに送り返す必要があります。この動作は非対称です。ターミナルプログラムは、シリアルポート接続を介して受信したコンテンツのコピーも再送信しません。

TTYドライバはUnixの伝統で多くのことを必要とするので複雑です。リモートエコー機能はそのうちの1つにすぎません。

を使用するとstty raw効果的にTTYドライバの一般的に便利な機能をすべてオフにします。、リモートエコー機能付き。したがって、その時点から明示的に読み取ってすぐに書き換えない限り、/dev/ttyS0端末プログラムに書かれた内容を見ることはできません。

stty rawコマンドが終了した後、ターミナルプログラムのすべての入力はコマンドに入り、cat引数なしで呼び出されると変更されずに標準出力に渡されます。ただし、標準出力は現在ファイルにリダイレクトされますreceived.txtターミナルプログラムに入力した内容だけがファイルに書き込まれます。コマンドが終わるまでcat- そしてファイルの終わり文字(通常Control+D)を取得したときにのみ可能です。

received.txt(リダイレクトシェルで実行できるバッファリングのため、ファイルの終わり文字で入力を終了したり、複数行のテキストを入力しない限り、ファイルに何も出力されないことがあります。)

したがって、TTYドライバ機能をオフにする以外に、(stty raw; cat > received.txt) < /dev/ttyO0組み込みシステムのTTYドライバは何もキャプチャしません。出力書き込み/dev/ttyO0このコマンドは、問題を解決するときにのみ使用されます。シリアル接続: 端末プログラムが送信する文字を何らかの形で損なうと思われる場合は、端末プログラムが組み込みデバイスに送信するすべてを最も原始的な形式でキャプチャする方法です。


録音したい場合絶対にすべてたとえば、カーネルパニックメッセージを含むUART接続でこれが発生した場合、最良の方法は他のコンピュータのターミナルプログラムにすべてのトラフィックを記録するように指示することです。多くの端末プログラムにはこの機能が組み込まれています。

これは、カーネルに問題が発生すると、実際にはディスクファイルに何も書き込めなくなる可能性があるためです。 UARTがエラーメッセージのテキストを送信し、それを受け取る人がそれを発見すると信頼する方がはるかに簡単です。

おすすめ記事