特定のディレクトリでtarファイルを探す自動化プロセスを(1分のcronスクリプトを介して)展開する必要があります。 tarファイルが見つかると、適切な場所に展開され、tarファイルは削除されます。
Tarファイルは、別のサーバーからSSH経由でこのサーバーに自動的にコピーされます。場合によっては、tarファイルは非常に大きく、多数のファイルがあります。
私が実行することを期待している問題:tarファイルがサーバーにコピーされるのに1分以上かかり、cronスクリプトが毎分1回実行される場合、.tar.gzファイルを確認して実行しようとしますtarファイルがまだ書き込まれている最中でも、それをuntarします。
ファイルが現在書き込まれているのか、それが部分的なファイルだけであるのかなどをテストする方法はありますか(bashコマンドを介して)?
私が考えていた1つの代替案は、ファイルを別のファイル拡張子(.tar.gz.part
など)としてコピーし、転送の完了後に.tar.gz
に名前を変更することでした。しかし、私は、ファイルがコマンドラインで完全であるかどうかを最初に判断する方法があるかどうかを考えようと考えました...手がかりはありますか?
あなたは正しい軌道に乗っています。ファイルの名前を変更することはアトミック操作であるため、アップロード後に名前を変更することはシンプルでエレガントで、エラーが発生しにくくなっています。私が考えることができる別のアプローチは、lsof | grep filename.tar.gz
は、ファイルが別のプロセスによってアクセスされているかどうかを確認します。
あなたの最善の策は、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
)転送が完了するまで、その後所定の場所に移動します。
少し古いですが、ほとんどの回答は質問の要点を完全に逃しています。
しかし、私は最初にファイルがコマンドラインで完全であるかどうかを判断する方法があるかどうかを理解しようとするだろうと考えました...
一般的にはありません。それを判断するのに十分な情報がありません。
ファイルがclosedであると判断することは、ファイルがwholeであるかどうかを判断することと同じではないためです。たとえば、転送の途中で接続が失われた場合、ファイルは「クローズ」されます。
@Alexの答えだけがこの問題を解決しました。そして彼はlsof
をいくらか使用することに失敗しました。
ファイルが完全に転送されたかどうかを確認するには、正常に転送するにはさらにデータが必要です。といった:
私が考えていた1つの代替案は、ファイルを別のファイル拡張子(_
.tar.gz.part
_など)としてコピーし、転送が完了した後で_.tar.gz
_に名前を変更することでした。
これは、ファイルが完全に正常に転送されたことを伝えるための完全に優れた方法です。同じファイルシステム内にいる限り、ディレクトリ間でファイルを移動することもできます。または、送信者に空の_filename.done
_ファイルを送信して完了を知らせます。
しかし、すべての方法は、転送が正常に完了したことを何らかの方法で通知する送信者に依存する必要があります。送信者だけがその情報を持っているからです。
一部のファイル形式(PDFなど)には、ファイルが完全であるかどうかを判別できるデータが含まれています。しかし、見つけるには、ファイル全体を開いて読み取る必要があります。
lsof
は、ファイルが開いていないことを通知するだけです-通知されません理由開いていない。また、ファイルの大きさが想定される大きさもわかりません。
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、つまり書き込みです。
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 を参照してください