Bash - 出力を変数またはファイル記述子にリダイレクトし、変数またはファイル記述子から読み込みます。

Bash - 出力を変数またはファイル記述子にリダイレクトし、変数またはファイル記述子から読み込みます。

以下は、すべての出力をファイルにリダイレクトし、画面に出力を表示するbashスクリプトの例です。

# writing to it
exec > >(tee --ignore-interrupts ./log)
exec 2>&1

echo "here is a message"

# reading from it again
cat ./log

これでファイルを作成したくありません./log。すべてのstdoutをメモリに保存し、後でスクリプトから再読み込みできるようにしたいです。また、ルートファイルシステムがマウントされない状況にあります。

代わりに、プロセス置換を試してみましたが、作成した内容を./log読み取るために、後続のコマンドのプロセス置換によって生成されたファイル記述子を渡す方法がわからないようです。

別の例は次のとおりです。

# can I make ./log a temporary file descriptor, an in-memory buffer?
exec 3>./log 4<./log
# writes
echo >&3 "hello"
# reads
cat <&4

ベストアンサー1

作成されたすべてのコンテンツをグローバルにリダイレクトしたい場合は(今のように)トリッキーですが、まとめることができます。

可能であれば、通常のパイプを使用することをお勧めします。サブシェルで実行するすべての作業をラップするだけです。この場合

(
 echo "this is the message"
 other stuff
) | cat

または、単に "$()" 構文を使用してすべてを変数に書き込みます。

次の方法は、あなたがしたものを使用し、tmpfsに書き込むか、または/dev/shm利用可能な場合に書き込むことです。非常にシンプルですが、どのRAMベースのファイルシステムがあるかを知る必要があります(可能であれば設定する必要があります)。

もう一つの方法はmkfifo。どちらの場合も、自分で掃除する必要があります。

編集する:

本当に醜いハッキングがありますが、誰かがそれを改善できると確信しています。

#!/bin/bash
exec 3>&1
exec > >( tee >( ( tac && echo _ ) | tac | (read && cat > ./log) ) )

echo "lol"
sleep 5
echo "lol"

echo "finished writing"

exec >&-
exec >&3
exec 3>&-
echo "stdout now reopen"
sleep 1 #wait if the file is still being written asynchronously
cat ./log

仕組み:まず、tee何が起こっているのかを確認することができます。その後、交換のために別のプロセスに出力されます。続行する前に、ストリーム全体が完了するのを待つトリックtac|tactac出力を開始するには完全な入力が必要なので)があります。最後の部分は実際にファイルとして出力するサブシェルにあります。もちろん、最終シェルはインスタンス化直後にファイルシステムに出力ファイルを生成します(唯一の行の場合)。したがって、入力が最終的に到着するのを待ってファイルの生成を遅らせる作業を最初に実行する必要があります。まず、echoを使用してダミーラインを出力し、それを読み取って削除してこれを達成しました。これらのreadブロックは、ファイル記述子を閉じてtacその時間が満了したことを示すまでブロックされます。したがって、stdoutファイル記述子は最終的に閉じられます。また、プロセスの交換をオンにする前に、元のファイルを保存してstdout最後に復元することができました(cat再利用のため)。そこに1つあるので、ファイルが実際に早すぎて作成されていないことをsleep 5確認できます。ls最後のスリープモードはもっとトリッキーです。サブシェルは非同期です。出力が多い場合は、tacファイルが実際に存在する前に2つの操作が完了するのを待ちます。したがって、合理的にタスクが実際に完了したことを確認するために他のタスクを実行したい場合があります。たとえば、ファイルを最後に使用する前に、最後のサブシェルの&& touch sentinel最後に。while [ ! -f sentinel ]; do sleep 1; done && rm sentinel

全体として2つのプロセス交換があり、内部には2つのサブシェルと2つのパイプがあります。これは私が書いたものの中で最も醜いものの1つです...しかし、stdoutを閉じたときにのみファイルを生成する必要があります。これは、ファイルシステムの準備が整うとうまく制御され、完了できることを意味します。

おすすめ記事