変数で rm コマンドを使用する際のリスク

変数で rm コマンドを使用する際のリスク

セキュリティカメラの15分のクリップを1つのファイル(24時間長)に圧縮し、そのクリップを削除するcrontabを作成しています。

avimerge -o /media/jmartin/Cams/video/Full_$(date +%F --date "Yesterday") -i /media/jmartin/Cams/video/$(date +%F --date "Yesterday")* # Converts files from the past 24 hours into one .avi

rm /media/jmartin/Cams/video/$(date +%F --date "Yesterday")* # Removes old clips that have already been compressed

私の質問は、$date変数を使用する際の危険性が何であるかです。 /video/のすべてのファイルを削除できますか?より安全な選択肢として何をお勧めしますか?

ファイル名の例(例:ファイル名にスペースが含まれています):

2016-04-25 00:00:01.avi  
2016-04-25 00:15:02.avi 
2016-04-25 00:30:02.avi  
2016-04-25 00:45:01.avi  

答え1

技術的に$(date +%F --date "Yesterday")は変数ではなくコマンドの置き換えですが、あなたの質問には関係ありません。何らかの理由dateでコマンドが存在しないため、何も返さない場合は、この設定に問題がある可能性があります$PATH。この場合、すべての内容が削除されます/video/。コマンドの置換を実行してコマンドの前の変数に割り当ててから、コマンドでそのavimerge変数を使用すると、作業中の日付文字列が変更されていないことを確認したり、長さがゼロであることをテストしたりできます。 2つのコマンド変数の前に(長さ0の文字列がある場合)、不要な操作を実行する前に終了します。avimergerm

答え2

2つが飛び出します。

  1. 交換に失敗したかどうかを確認していません。
  2. コマンドの使用中に日付が変更されると、競合状態が存在しますdate

次のように解決できます。

#/bin/bash

# Exit if any command fails
set -e

dir='/media/jmartin/Cams/video'
day=$(date +%F --date Yesterday)

# Conbine files from the past 24 hours into a single AVI file
avimerge -o "$dir/Full_$day" -i "$dir/$day"*

# Remove old clips that have already been compressed
rm "$dir/$day"*

答え3

ファイル名には常にスペースがあるので、コマンドにスペースを含めます。

rm "$(date +%F --date "Yesterday") "* # Removes old clips

これは、ディレクトリ内のすべてのファイルの削除を防ぐ簡単な方法です。date何も返されなくても、空白文字(おそらく存在しない)で始まるファイルだけが削除されるためです。

しかし、次のような他のリスクもあります。

  • avimergeどういうわけか失敗する可能性があり、まだマージされていないファイルを削除する可能性があります。
  • avimergeかなり時間がかかり、時間が経つrmほど昨日が今日になり、最終的に間違ったものを削除するようになります。

基本的に、これらのコマンドが望みどおりに機能することを盲目的に信頼するのは悪い考えです。自動削除するには、すべてを確認して再度確認して、変数を正しく使用していることを確認する必要があります。

結果を実際の変数に入れ、date変数がどのように見えるかを確認し、両方のコマンドで同じ変数を使用して2つの間で変更されないようにする必要があります。

呼び出すコマンドの戻りコード(終了コード)を確認し、エラーを返さない場合(または予想されるエラーを具体的に処理する場合)にのみ続行する必要があります。

マージされたファイルが作成され、実際のファイルサイズがあることを確認する必要があります。

答え4

スクリプトが正確で奇妙な環境で実行されない限り、すべてが問題ありません。

ただし、予想される出力が壊れると、dateすべての賭けがキャンセルされます。たとえば、このスニペットを次のように実行するIFS=-

rm /media/… 04 26*

つまり、26現在のディレクトリから始まるファイルを削除します。もちろん、これはスクリプトの初心者ミスによるものです。忘れてしまいました。コマンド置換の二重引用符

rm "/media/jmartin/Cams/video/$(date +%F --date "Yesterday")"*

これにより、少なくともターゲットディレクトリ外のファイルが削除されないことが保証されます。

より安全なアプローチは、段階的なクリーンアップを実行することです。これにより、問題が発生した場合でもこれに気付く時間があります。

#!/bin/sh
set -e
cd /media/jmartin/Cams/video
if [ -d yesterday ]; then
  find yesterday -type f -delete
else
  mkdir yesterday
fi
mv "$(date +%F --date "Yesterday") "* yesterday/

関連情報