변수와 함께 rm 명령을 사용할 때의 위험

변수와 함께 rm 명령을 사용할 때의 위험

보안 카메라의 15분 분량의 클립을 단일 파일(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명령에서 해당 변수를 사용하면 작업 중인 날짜 문자열이 변경되지 않는지 확인할 수 있을 뿐만 아니라 길이가 0인지 테스트할 수도 있습니다. 두 명령 변수 앞에 그리고 (길이가 0인 문자열이 있는 경우) 원하지 않는 작업을 수행하기 전에 종료합니다.avimergerm

답변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변수가 어떻게 보이는지 확인한 다음 두 명령에 동일한 변수를 사용하여 둘 사이에서 변경되지 않도록 해야 합니다.

호출하는 명령의 반환 코드(종료 코드)를 확인하고 오류를 반환하지 않는 경우(또는 예상되는 오류를 구체적으로 처리하는 경우)에만 계속해야 합니다.

병합된 파일이 생성되었는지, 실제 파일 크기를 가지고 있는지 확인해야 합니다.

답변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/

관련 정보