ファイルが書き込み中かどうかを判断しますか?


25

特定のディレクトリでtarファイルを探す自動化されたプロセスを展開する必要があります(1分cronスクリプトを使用)。tarファイルが見つかった場合、適切な場所にuntarされた後、tarファイルが削除されます。

tarファイルは、SSHを介して別のサーバーからこのサーバーに自動的にコピーされます。場合によっては、tarファイルは非常に大きく、多くのファイルがあります。

予想される問題:tarファイルがサーバーにコピーされるのに1分以上かかり、cronスクリプトが1分に1回実行される場合、.tar.gzファイルが表示され、実行しようとします。 tarファイルがまだ書き込まれている途中であっても、それをuntarします。

ファイルが現在書き込まれているのか、それとも部分的なファイルだけなのかなどをテストする方法はありますか(bashコマンドを使用)?

私が考えていた1つの選択肢は、ファイルを別のファイル拡張子(など.tar.gz.part)としてコピーし.tar.gz、転送が完了した後に名前を変更することでした。しかし、最初にファイルがコマンドラインで完全であるかどうかを判断する方法が単純にあるかどうかを把握しようと思ったのですが...手がかりはありますか?


2
ファイルはどのくらい正確に転送されますか?たとえばrsync、転送中に一時ファイル名を使用し(デフォルト)、ファイルが完全に転送されたにのみ、実際のファイル名に名前を変更します。
Piskvor

回答:


12

ファイルの名前変更はアトミックな操作であるため、アップロード後に名前変更を実行するのは簡単でエレガントであり、エラーが発生しにくいです。私が考えることができる別のアプローチはlsof | grep filename.tar.gz、ファイルが別のプロセスによってアクセスされているかどうかを確認するために使用することです。


7
lsof filename.tar.gzより効率的かつ正確ですlsof | grep filename.tar.gz
リッチ

ところで、それはファイル名の絶対パスでなければなりません
DennisLi

14

最善の策はlsof、プロセスによってファイルが開かれたかどうかを判断することです。

#  lsof -f -- /var/log/syslog
COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
rsyslogd 1520 syslog    1w   REG  252,2    72692 16719 /var/log/syslog

書き込み中かどうかは簡単にはわかりませんが、書き込み中の場合は開いている必要があります。


編集:提案されたソリューションを実装しようとするのではなく、ここで実際の問題を解決しましょう!

rsyncを使用してファイルを転送します。

  rsync -e ssh remote:big.tar.gz .

この方法では、ファイルは既存のファイルの上にコピーされるのではなく.big.tar.gz.XXXXXX、転送が完了するまで一時ファイル()にコピーされ、その後所定の場所に移動されます。


6

少し古いですが、答えのほとんどは完全に質問のポイントを逃しています:

しかし、最初にファイルがコマンドラインで完全であるかどうかを判断する方法が単純にあるかどうかを把握しようと思いました...

一般的にはありません。それを判断するのに十分な情報がないだけです。

ファイルがあると判断したため、閉鎖するファイルがあるかどうかを決定すると同じではありません全体。たとえば、転送の途中で接続が失われた場合、ファイルは「クローズ」されます。

@Alexの答えだけがこれを正しくしました。そして、彼でさえlsof多少使用したために落ちました。

ファイルが完全に揃っているかどうかを判断するには、正常に転送するにはより多くのデータが必要です。といった:

私が考えていた1つの選択肢は、ファイルを別のファイル拡張子(など.tar.gz.part)としてコピーし.tar.gz、転送が完了した後に名前を変更することでした。

これは、ファイルが完全かつ正常に転送されたことを伝えるための完全に素晴らしい方法です。同じファイルシステム内にいる限り、あるディレクトリから別のディレクトリにファイルを移動することもできます。または、送信者に空のfilename.doneファイルを送信して、完了を通知します。

ただし、すべての方法は、送信者が転送が正常に完了したことを何らかの形で通知することに依存する必要があります。送信者だけがその情報を持っているからです。

一部のファイル形式(PDFなど)には、ファイルが完全かどうかを判断できるデータが含まれています。ただし、ファイル全体を開いて確認する必要があります。

lsofファイルが開いていないことを通知するだけで、なぜ開いていないのはわかりません。また、ファイルの大きさもわかりません。


1
これを十分に支持することはできません。ここでXY問題を解決するのは良い仕事です。
ビーフスター

5

これを行うための最良の方法は、incron(「cronシステムの初期化」)を使用することです。これにより、ディレクトリにinotifyウォッチを設定して、ファイル操作を通知できます。この場合、close_writeのディレクトリを監視する必要があります。これにより、書き込み後にファイルが閉じられたらコマンドを実行できます。


2

lsofは、ファイルがどのモードで開いているかを検出できるようです:

lsof -f -- a_file
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     52391 bob    1w   REG    1,2       15 19545007 a_file

1wと表示されている箇所をご覧ください。これは、ファイル記述子番号が1で、モードがwまたはwriteであることを意味します。


ファイルが読み取り用に開いている場合、このFDフィールドに表示さ3rれます。
ソパラホデアリエレズ

0

を使用inotifywaitすると、目的を達成できます。ファイルの書き込みが完了するまで待機してからコマンドを実行できます。

以下は、新しいファイルのフォルダーを継続的に監視し、ファイルへの書き込みが終了するとループ内のコマンドを実行します。

WATCH_DIR=/directory/to/monitor
DEST_DIR=/x/y/z

/usr/bin/inotifywait --recursive --monitor --quiet -e moved_to -e close_write --format '%w%f' "$WATCH_DIR" | while read -r INPUT_FILE; do

mv "$0" "$DEST_DIR"

done

その他の構成オプションについては、https://linux.die.net/man/1/inotifywatchを参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.