Bashでファイルディスクリプタを作成してファイルをポイントし、ここにいくつかのデータを入れると、次のようになります。
exec 5>>file
for i in {1..10000}; do
echo "$i" >&5
done
ファイル記述子5は開かれた「ファイル」を保持し、その記述子にデータを書き込むたびにデータを追加し、ファイルの現在位置を保持する。
同じ記述子を同じファイルにリダイレクトする場合:
exec 5>>file
現在のfdを閉じて同じファイルを指す新しいfdを再生成しますか?それでは、次にデータを書き込むときに最初にファイルの終わりを見つけてから最後に追加する必要がありますか?それとも、記述子がすでにファイルを指していて何もしないことを認識するのに十分スマートですか?レベルが低くて何が起こっていますか?
編集:より具体的には、ファイル記述子を使用してファイルを開いたままにするためにファイルにデータを書き込みます。関連ビット:
recv_udp () { # Receives a udp stream, timestamps and removes commas and the period from the seconds field, deletes blank lines.
socat -L "$LOCKFILE" -u udp-recv:"$UDP_IN",reuseaddr STDIO | ts '%Y %j %H %M %.S' | sed -u -e 's/,/ /g' -e 's/\./ /' -e '/^$/d' &
}
file_handle () { # Points file descriptor 9 to the desired log file
exec 9>>"$DATADIR"/"$CRUISEID"/"$STAMP"/"$STAMP"_"$JDY"_raw
}
parse_lci90i () { # Parse lci90i winch controller mtnw2 data stream.
echo "Started $STAMP $CRUISEID $(date +'%c')" >> "$LOGFILE"
while read YR JDY HR MIN SEC uS GARBAGE GARBAGE TENS SPD LINE CHKSUM; do
printf '%4.0f %03.0f %02.0f %02.0f %02.0f %.3s %s %.0f %.1f %.0f\n' "$YR" "$JDY" "$HR" "$MIN" "$SEC" "$uS" "$STAMP" "$SPD" "$LINE" "$TENS"
check_path
file_handle
printf '%4.0f %03.0f %02.0f %02.0f %02.0f %.3s %s %.0f %.1f %.0f\n' "$YR" "$JDY" "$HR" "$MIN" "$SEC" "$uS" "$STAMP" "$SPD" "$LINE" "$TENS" >&9
done
}
Socat は 20hz udp フィードを読み込み、プロセス交換を介してパーサにポンピングします。ここでは、データ行を読み取るたびにファイル記述子が再生成されることがわかります。はい。パーサーからstdoutを取得して>>をログファイルに直接置くよりも、これがより効率的かどうか疑問に思います。
これまでのすべての回答に感謝します。皆さんはとても洞察力があります。データファイルのファイル名には、データタイムスタンプのユリウス暦の日付が含まれているため、日付が変更されるたびにログファイルがロールオーバーされます。
答え1
bash
標準ファイル記述子1(出力)と2(エラー)を最初にフラッシュしてリダイレクトを処理します。それ以外は特別なことをしないで(ファイル記述子が何に使用されるかは関係ありません)、単にdup2
設定を呼び出します。新しいファイルへの接続です。
ファイル記述子を開く限り、ファイル記述子を通して同じファイルに従います。名前を変更する。ただし、ファイル名が変更された後に新しいファイル記述子を開くと、古いファイルに書き込むのではなく新しいファイルに書き込むことになります。同様に、前のファイルへの子プロセスの書き込みは、記述子が閉じられるまで続行されます。
追加資料(ソースコード):