しかし...

しかし...

出力がログファイルにリダイレクトされるプログラムがあります。

./my_app > log

時々(要求時に)ログを消去(つまり空にし)、次のようなさまざまな方法を試してみたいと思います。

cat "" > log

しかし、元のパイプが中断され、プログラムが出力をログファイルにリダイレクトしなくなったようです。

これを行う方法はありますか?

修正する

出力を生成するアプリケーションは変更できません。 stdoutで印刷し、必要に応じて確認して消去できるようにログに保存したいと思います。しかし、アプリケーションを再起動する必要はありません。

ベストアンサー1

この問題の別の形式は、ログが定期的に循環する長期実行アプリケーションで発生します。元のログ(たとえば)を移動し、mv log.txt log.1実際のロギングが発生する直前に同じ名前のファイルに置き換えても、プロセスがファイルを開いたままにすると書き込みは終了しますlog.1(まだ開いているinodeかもしれません)。何もしないでください。

これを処理する一般的な方法(システムロガー自体はこのように機能します)は、ログを閉じて再度開くプロセスにシグナルハンドラを実装することです。その後、ログを移動または削除(削除)したい場合は、すぐにその信号をプロセスに送信します。

以下はbashの簡単なデモです。私の都合の良いシェル技術を許してください(ただし、ベストプラクティスなどのためにこれを編集するには、まず機能を理解してリビジョンをテストしてください)。今後あなたの編集):

#!/bin/bash

trap sighandler INT

function sighandler () {
    touch log.txt
    exec &> log.txt
}

echo $BASHPID
exec &> log.txt

count=0;
while [ $count -lt 60 ]; do
    echo "$BASHPID Count is now $count"
    sleep 2
    ((count++))
done          

バックグラウンドに分岐して始めます。

> ./test.sh &
12356

PIDを端末に報告してからロギングを開始しますlog.txt。これで2分間プレイできます。数秒待ってから、次のことを試してください。

> mv log.txt log.1 && kill -s 2 12356

簡単なものもkill -2 12356あなたに役立ちます。シグナル2はSIGINTです(Ctrl-Cが実行する操作でもあるため、フォアグラウンドでこれを試して他の端末でログファイルを移動または削除できます)。これはtrapキャプチャする必要があります。確認する。

> cat log.1
12356 Count is now 0
12356 Count is now 1
12356 Count is now 2
12356 Count is now 3
12356 Count is now 4
12356 Count is now 5
12356 Count is now 6
12356 Count is now 7
12356 Count is now 8
12356 Count is now 9
12356 Count is now 10
12356 Count is now 11
12356 Count is now 12
12356 Count is now 13
12356 Count is now 14

log.txtそれでは、移動したにもかかわらず、まだ作成中であることを確認してみましょう。

> cat log.txt
12356 Count is now 15
12356 Count is now 16
12356 Count is now 17
12356 Count is now 18
12356 Count is now 19
12356 Count is now 20
12356 Count is now 21

中断された部分から引き続き開始されます。記録を残したくない場合は、ログを削除して削除してください。

> rm -f log.txt && kill -s 2 12356

確認する:

> cat log.txt
12356 Count is now 29
12356 Count is now 30
12356 Count is now 31
12356 Count is now 32
12356 Count is now 33
12356 Count is now 34
12356 Count is now 35
12356 Count is now 36

まだ続いています。

残念ながら、実行された子プロセスのシェルスクリプトではこれを行うことはできません。これは、bashの独自の信号ハンドラがtrap前景にあると停止し、背景に分岐するとその信号ハンドラを再割り当てできないためです。出力。つまり、これはアプリケーションで実装する必要があります。

しかし...

アプリケーションを変更できない場合(たとえば、アプリケーションを作成していないため)CLIユーティリティ仲介者として使用できます。ログのパイプとしてスクリプトに単純なバージョンを実装することもできます。

#!/bin/bash

trap sighandler INT

function sighandler () {
    touch log.txt
    exec 1> log.txt
}

echo "$0 $BASHPID"
exec 1> log.txt

count=0;
while read; do
    echo $REPLY
done  

それをと呼びましょうpipetrap.sh。これで、記録したいアプリケーションを模倣してテストする別のプログラムが必要です。

#!/bin/bash

count=0
while [ $count -lt 60 ]; do
    echo "$BASHPID Count is now $count"
    sleep 2
    ((count++))
done           

それは次のとおりですtest.sh

> (./test.sh | ./pipetrap.sh) &
./pipetrap.sh 15859

これは、異なるPIDを持つ2つの別々のプロセスです。以下で組み立てtest.shられた出力を削除しますpipetrap.sh

> rm -f log.txt && kill -s 2 15859

確認する:

>cat log.txt
15858 Count is now 6
15858 Count is now 7
15858 Count is now 8

15858、はtest.shまだ実行中で、出力を記録しています。この場合、アプリケーションを変更する必要はありません。

おすすめ記事