ディレクトリに追加されたファイルを処理したら、削除する必要があります。ファイルはサイズが大きく(20KiB〜5GiB)、到着が遅くなる可能性があります(scp
または経由ftp
)。パス(単位を含むsystemd.path
)をどのように監視し、新しいファイルの書き込みが完了した場合にのみ反応できますか?私のサービスは、ファイルの最初のバイトが書き込まれると常にトリガーされ、ファイル全体が存在しないため失敗することがわかりました。
1回試み(DirectoryNotEmpty=
)
*.path
で使用しますDirectoryNotEmpty=
。
利点:
- 欲しいと思う
欠点:
- 早すぎます。作業中にファイルが転送され続け、不完全(破損)しました。
# /etc/systemd/system/incoming.path
[Path]
DirectoryNotEmpty=/var/incoming
# /etc/systemd/system/incoming.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/incoming
# /usr/local/bin/incoming
for i in /var/incoming/*; do
process $i
rm $i
done
試み2(アンケート調査)
私は*.timer
毎分スクリプトを実行します。
利点:
- シンプル
欠点:
- 小さなファイルの場合は約90%の時間動作し、大きなファイルの場合は約0%の時間動作します。
- パイプラインに最大1分の遅延を追加する
- 受信デバイスの起動/停止によりログログが複雑になりました。
# /etc/systemd/system/incoming.timer
[Timer]
OnCalendar=minutely
# /etc/systemd/system/incoming.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/incoming
# /usr/local/bin/incoming
for i in /var/incoming/*; do
process $i
rm $i
done
3回試み(ポーリングとmd5)
ポーリングを続けていますが、*md5
メインコンテンツを送信した後にクライアントからのみ送信される小さなファイルだけを処理することもあります。これらはすべて 1 MTU より小さいので、書き込み処理中に中断されないことを願っています。
利点:
- 常に動作しているようです(ただし動作するかどうかはわかりません)。
欠点:
- パイプラインに最大1分の遅延を追加する
- 受信デバイスの起動/停止によりログログが複雑になりました。
- ユーザーにとってはもっと複雑です。ユーザースクリプトを作成
md5sum
したら、ファイルを送信する必要があります。後ろにマスターファイルを送信します。
# /etc/systemd/system/incoming.timer
[Timer]
OnCalendar=minutely
# /etc/systemd/system/incoming.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/incoming
# /usr/local/bin/incoming
for i in /var/incoming/*.md5; do
file=$(basename $i .md5)
process $file
rm $file $file.md5
done
答え1
唯一の質問だから「1回やって」ファイルがまだ開いている場合は、使用するスクリプトを変更してlsof
処理sleep
する前にファイルが閉じられていることを確認できます。
このような:
# /usr/local/bin/incoming
for i in /var/incoming/*; do
while [ "$(lsof $i)" != "" ]; do
sleep 1
done
process $i
rm $i
done
もう少し考えると、systemd
すでに実行されているスクリプトがファイルが閉じるのを待っている間にスクリプトを再度呼び出すと、競合状態が発生する可能性があります。
このようなことは、競争条件によってバグが発生する可能性が少なくなります(まだ改善の余地があります)。
for i in /var/incoming/*; do
while [ -e $i ]; do
if [ "$(lsof $i)" != "" ]
then
sleep 1
else
process $i
rm $i
fi
done
done
答え2
これを行う従来の方法(メールサーバーなど)は、書き込みプロセスが着信ディレクトリに書き込み、完了したらファイルを処理ディレクトリに移動することです。これにより、処理サービスは、着信ファイルが記録され続けていることを心配することなく、到着する新しいファイルに対して操作を実行できます。
アップロードプロセス中に名前を変更できるはずですが、使用しようとしていたDirectoryNotEmpty
機能を使用できるようになります。