/opt/landing
外部システムが一日中複数のファイルを保存するログインフォルダがあるとします。一部のファイルは小さく、一部は大きいです。ログインフォルダから利用可能なフォルダに完全にコピーされたファイルをコピーするスクリプトを作成しようとしています/opt/available
。転送されるファイルをコピーしたくありません。
UNIXスクリプトコードを使用してこれを達成するにはどうすればよいですか?
答え1
そしてzsh
:
#! /bin/zsh -
files=( /opt/landing/**/*(D.:P) )
typeset -U inuse=( /proc/<->/fd/<->(D-.:P) )
cp ${files:|inuse} /opt/available/
現在のプロセスファイル記述子には表示されない一般ファイルをその中にコピーします。 (私たちはプロセスアドレス空間にマップされたファイルを探していませんが、ファイルがそこに到着する方法ではないと思います。)
ここでは、ファイルが読み取りモードで開かれているか、書き込みモードで開かれているかを確認しません。これは、ファイルを表示したり/proc/*/fdinfo/*
出力を解析したりする必要があるため、より複雑ですlsof
。これは些細なことではありません。
プロセスに属さないファイル記述子を見つけるには、スーパーユーザー権限が必要です。
$inuse
NFSまたは他のカーネルネットワークファイルシステムを介してアップロードされたファイルはリストに表示されません。各タスク間でファイル名を変更または再開する可能性があるため、まだ脆弱な方法です。更新できる場合着陸システムファイルの削除が完了したら、ファイルを直接移動する方がより安定しています。
**/
glob 演算子は次のことを示します。あらゆるレベルのサブディレクトリ。<->
任意の10進数のシーケンスです。(ND.:P)
/(N-.:P)
:グローバル修飾子:D
:D
otglob:ファイルを隠すことも検討してください.
:唯一定期的なファイル(ソケット、ディレクトリ、シンボリックリンクなどの他の種類のファイルではありません...)-.
:同じですが、シンボリックリンクの確認済みタイプを確認してください。:P
:likeはrealpath()
ファイルへの標準(シンボリックリンクなし)絶対パスを取得します。
typeset -U
:配列要素をU
一意にします(重複要素を削除)。${files:|inuse}
:配列減算(未使用ファイル)。- 引数のリストが長すぎます。ファイルが多すぎる場合は、組み込み機能を使用するか
zargs
(アクティブにする)エラーを防ぐことができます。zsh
cp
zmodload zsh/file
答え2
ファイルを使用してはいけないだけでなく、ファイルが正常にコピーされたという制限も追加できます。 2番目の基準は、送信側のクライアントで最もよく認識されます。
これはUNIX / Linuxの問題ではなく、アルゴリズムの問題です。
これらの基準をすべて満たす一般的な方法(つまり、完全に正常にコピーされたファイルのみを処理する)は、一時ファイル名のサフィックスを使用してファイルを転送し、ファイルが正常に完了した場合にのみ送信者にファイル名を変更させることです。 。
顧客
- クライアントが送信します。
datafile.xml.tmp
datafile.xml.tmp
転送が正常に完了すると、クライアント名は次のように変更されます。datafile.xml
仕える人
- サーバーは、次に終わらないファイルを探します。
.tmp
- 一致が成功すると、サーバーは必要な方法でファイルを処理します。
- サーバーは、「未使用」
.tmp
ファイル(1日以上変更されていないファイル)を探します。 - 一致が成功すると、サーバーはその一時ファイルを削除します。
正しくエンコードされていないクライアント側転送システムを処理するために長年使用する必要がある他の方法には、ファイル自体でファイルの終わりの表示を見つけることがあります。たとえば、次のようなXML対応パーサーをxmlstarlet
適用すると、識別しやすいconvert
ImageMagickなどのツールを使用してください。
最悪のシナリオは、ファイルがしばらく更新されていないため、ファイルが完全であるかどうかを推測する必要があります。残念ながら、完全に送信されたか、ネットワークエラーが原因で転送が途中で切り捨てられたかどうかを知る方法はありません。