同じ行をフラッシュするのではなく、コマンド出力を新しい行に分割します。

同じ行をフラッシュするのではなく、コマンド出力を新しい行に分割します。

以下に関連するスクリプトを作成しようとしています。スナップショットRAID、進行状況出力はsnapraid syncタイムスタンプが付けられ、ファイルおよび標準出力に書き込まれます。私が直面している問題は、snapraid sync毎秒更新される行に進行状況を出力することです。つまり、スクリプト内で実行したときの残りの出力は同じです100% completed, 7737 MB accessed in 0:00。コマンドがどのように実行されたかを確認できません。

tssedおよび以下を使用して、tee目標を部分的に達成できます。

#!/bin/bash

LOG_FILE="/tmp/snapRAID.log"

exec 1>> >(ts '[%Y-%m-%d %H:%M:%S]') 2>&1

snapraid sync | sed -e 's/\r/\n/g' | tee >(ts "[%Y-%m-%d %H:%M:%S]" >> $LOG_FILE)

stdoutこれにより、次の出力が生成されます/tmp/snapRAID.log(残りの出力とともにsnapraid sync)。

[2023-04-23 16:24:51] 0%, 0 MB
[2023-04-23 16:24:51] 5%, 552 MB
[2023-04-23 16:24:51] 12%, 1332 MB
[2023-04-23 16:24:51] 17%, 1942 MB
[2023-04-23 16:24:51] 21%, 2311 MB
[2023-04-23 16:24:51] 27%, 3044 MB, 622 MB/s, 1188 stripe/s, CPU 14%, 0:00 ETA
[2023-04-23 16:24:51] 35%, 3836 MB, 656 MB/s, 1253 stripe/s, CPU 14%, 0:00 ETA
[2023-04-23 16:24:51] 42%, 4612 MB, 676 MB/s, 1306 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 49%, 5005 MB, 636 MB/s, 1334 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 58%, 5493 MB, 617 MB/s, 1400 stripe/s, CPU 16%, 0:00 ETA
[2023-04-23 16:24:51] 67%, 5987 MB, 581 MB/s, 1449 stripe/s, CPU 16%, 0:00 ETA
[2023-04-23 16:24:51] 75%, 6415 MB, 564 MB/s, 1470 stripe/s, CPU 16%, 0:00 ETA
[2023-04-23 16:24:51] 80%, 6694 MB, 536 MB/s, 1429 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 84%, 6916 MB, 507 MB/s, 1376 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 92%, 7314 MB, 498 MB/s, 1388 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 97%, 7574 MB, 433 MB/s, 1268 stripe/s, CPU 13%, 0:00 ETA

問題は、この出力がリアルタイムではないことです。snapraid sync実行が完了すると、出力全体が標準出力およびログファイルに表示されます。要素を削除teeしますstdoutsnapraid syncこのテストインスタンスは数秒で同期しますが、実行しようとしているコンピュータには数時間かかることがあり、コマンドの実行中にコマンドの進行状況を確認し、実行する前に何が起こったのかを振り返ることができます。タイムスタンプを確認してください。

私は成功せず、次のアイデアのいくつかを試しました。

unbuffer snapraid sync | sed -e 's/\r/\n/g' | tee >(ts "[%Y-%m-%d %H:%M:%S]" >> $LOG_FILE)

snapraid sync | sed -u -e 's/\r/\n/g' | tee >(ts "[%Y-%m-%d %H:%M:%S]" >> $LOG_FILE)

タイムスタンプを含む改行出力をリアルタイムで発生させる方法を知っている人はいますか?

よろしくお願いします!

答え1

sed出力がttyに送信されないため、出力をバッファリングします。一部の実装では、そのバッファリングを無効にするオプションをサポートするsedか、withまたはwithを-u使用できます。これは特に。stdbufsedtr\r\nsed

snapraid sync |
  stdbuf -oL tr '\r' '\n' |
  ts '[%Y-%m-%d %H:%M:%S]' |
  tee -a "$LOG_FILE"

snapraid端末に入らないときに出力をバッファリングする場合(ラインベースのバッファリング)の代わりに、バッファリングされていないstdbuf(バッファされていない)端末で同じ方法を試すことができます。stdbuf -o0stdbuf -oL

stdbuf -o0 snapraid sync |
  stdbuf -oL tr '\r' '\n' |
  ts '[%Y-%m-%d %H:%M:%S]' |
  tee -a "$LOG_FILE"

これはどのような方法でも標準コマンドではありませんが、可能であればアプリケーションがバッファリングしないように説得しようとしますが、出力を破壊することが知られている擬似stdbufttyを使用するスクリプトよりも優先されるべきです。unbufferexpect

-uなしは標準オプションですsed

多くのsed実装では、アドレスが一致する時期を知るために、あらかじめ1行を読み込みます$。つまり、最終デバイスに到達しても出力は1行遅れます。

tsバッファリングを明示的に無効にするスクリプトですperl$| = 1私のテストでは、teeGNUはオブジェクトファイルまたは標準出力の両方がターミナルデバイスではなかったにもかかわらず、少なくとも出力をバッファリングしませんでした。

ところで、誰でも書くことができるディレクトリに固定された名前でファイルを書き込むことは、/tmpセキュリティの観点から悪い習慣なので避けるべきです。これを使用してmktemp独自の一時ファイルを入手したり、たとえば他の人が悪意のあるシンボリックリンクを植えられないディレクトリにファイルを書き込んだりします。

関連情報