
私は組み込みLinuxを実行しており、コマンドラインには がありますconsole=/dev/ttyO0,...
。このUARTに接続されたターミナルプログラムを見ると、すべてシステムによって生成されます。
さて、現場で実行しているときに、このすべての出力をファイルに保存したいと思います (メディアは接続しています)。しかし、、、およびその他を使用してすべての努力をしても、望ましいsyslogd
結果は得られません。一部のメッセージは保存されますが、一部は保存されません。通常、最も重要なメッセージです。klogd
logger
たとえば、次のように実行します。
myapplication.sh | logger
echo
で表示されるコマンドsyslog
、print
アプリケーションからの s、一部のドライバー メッセージもあります。ただし、アプリケーションがセグメンテーション エラーでクラッシュした場合、この情報は記録されません。しかし、これは最も価値があります。
したがって、最善かつ最も望ましい方法は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>&1
書かれており、その後、両方を一度にパイプすることができます。
次のような小さなスクリプトを使って自分でテストすることができます。
#!/bin/sh
echo "this is stdout"
echo "this is stderr" >&2
これは>&2
、「このコマンドの標準出力を取得し、代わりに標準エラー ストリームに送信する」ことを意味します。これはおそらく、stderr
スクリプトで出力を生成する最も簡単な方法です。
ここで、このスクリプトを実行して./test.sh | od -t x1z
出力を 16 進ダンプ形式で取得すると、次のようになります。
$ ./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
ファイルの終わりの文字で入力を終了しない限り、および/または 1 行を超えるテキストを入力しない限り、ファイルに出力されない可能性があります。)
したがって、TTYドライバの機能をオフにする以外に、(stty raw; cat > received.txt) < /dev/ttyO0
組み込みシステムでは何もキャプチャしません。出力に書き込まれます/dev/ttyO0
。このコマンドは、トラブルシューティングを行う場合にのみ使用されます。シリアルポート接続: 端末プログラムが送信する文字を何らかの形で改変している疑いがある場合、これは端末プログラムが組み込みデバイスに送信しているものを最も生の形式でキャプチャする方法です。
録音したい場合絶対にすべてUART 接続経由で発生する、カーネル パニック メッセージなどのトラフィックをすべてログに記録する場合は、他のコンピューターのターミナル プログラムにすべてのトラフィックをログに記録するように指示するのがおそらく最善の方法です。多くのターミナル プログラムにはこの機能が組み込まれています。
これは、カーネルに問題が発生した場合、ディスク ファイルに何も書き込めなくなる可能性があるためです。エラー メッセージのテキストを UART から送信し、それを受信した人がそれをキャッチすることを信頼する方がはるかに簡単です。
答え2
よし、答えを見つけたと思う。私見では、こんなに単純で必要なことが、こんなに「変則的な」方法で解決されているなんて、本当に驚きです。でも、これが人生です...:-)
とにかく、telcoM
参考文献を教えてくれた方々に感謝します。その参考文献が参考文献につながり、ついに私がttyrpl
求めていた通りのことをするパッケージを見つけることができました。
パッケージのメンテナンスは 7 ~ 10 年前に停止し、Linux バージョンと必要なライブラリに採用するのに時間がかかりましたが、うまくいきました。
まさに私が求めていた通りのことをします。ttyS0/ttyO0 の出力を収集してファイルに保存します。また、必要ないのに、多くの派手なオプションがあります...:-)
答え3
console=/dev/ttyS0 の代わりに picocom を使用してみてください。他のツールもありますが、picocom が最も簡単そうです。
これらのツールのいずれかを使用する場合は、出力にパイプと T 字継手を使用できます。
picocom /dev/ttyS0 -b 115200 -l | tee my.log
答え4
試す出典: github.io- ファイルへのログ記録をサポートします。例:
tio /dev/ttyS0 --log --log-file my-log.txt
または
tio /dev/ttyS0 --log
シリアル出力を自動生成されたファイル名でファイルに記録します。tio_ttyS0_2022-09-14T08:56:09.log