Bash: IF-THEN 문에 "인수가 너무 많습니다"

Bash: IF-THEN 문에 "인수가 너무 많습니다"

특정 파일이 존재하는지 확인하려고 합니다(24시간 미만인 경우에만 해당). 그렇다면 이름이 ".control"로 끝나는 파일이 존재하는지 두 번째 확인을 수행합니다. 두 조건이 모두 충족되면 이메일과 로그 항목이 생성됩니다. 첫 번째 파일은 존재하지만 .control은 존재하지 않는 경우 다른 로그 항목이 생성됩니다. 24시간 이내에 파일이 존재하지 않으면 스크립트의 나머지 부분이 계속 실행됩니다.

이는 Solaris 및 Linux에서 Bash를 사용하여 cron에서 실행되는 쉘 스크립트에 있습니다.

if [ find "$MAINTENANCE_LOCK/testLOCK" -mtime -1 ]; then
    if [ -f "$PATH_TO_TRIGGER_FILES/*.control" ]; then
        test_log_msg "test_SYSTEM" $NOTICE "Valid Maintenance Lock file found, test actions blocked." "status"
        test_log_email " " " " " " "test Actions were blocked because an testLOCK file less than 24hrs old is in place." " "
    else
        test_log_msg "test_SYSTEM" $NOTICE "Valid Maintenance Lock file in place." "status"
        exit
    fi
fi

그러나 "set -x Trap read debug"를 사용하여 코드 줄을 단계별로 실행하면 다음 오류가 발생합니다.

+ '[' find /var/opt/test/maintenancelock/testLOCK -mtime -1 ']'
/opt/test/test_control.sh: line 72: [: too many arguments

여기서 내가 원하는 것을 할 수 있는 방법이 있나요?

답변1

시도해 보세요 help [- help testyes [의 동의어 도움말에 다음과 같이 나와 있습니다 test.test

테스트 동작은 매개변수 수에 따라 달라집니다.

이렇게 하면 [ find "$MAINTENANCE_LOCK/testLOCK" -mtime -1 ];
4개의 단어를 에 전달 [하고 4개의 인수로 무엇을 해야 할지 알 수 없습니다.


특정 파일이 존재하는지 확인하려고 합니다(24시간 미만인 경우에만 해당). 그렇다면 이름이 ".control"로 끝나는 파일이 존재하는지 두 번째 확인을 수행합니다.

배시 사용:

mapfile -t testlock < <(find "$MAINTENANCE_LOCK/testLOCK" -mtime -1)
if [[ ${#testlock[@]} -eq 0 ]]; then
    echo "lock file does no exist or is too old"
else
    control=( "$PATH_TO_TRIGGER_FILES/"*.control )
    if [[ ${#control[@]} -gt 0 ]]; then
        echo "lock file exists and at least one control file exists"
    else
        echo "lock file exists but no control files exist"
    fi
fi

답변2

기본적으로 find일치하는 파일이 있는지 여부에 관계없이 항상 true(0)가 반환됩니다.

그러나 -exec일치하는 파일에 대해 작동하는 조건자를 사용하면 /bin/false하나 이상의 일치 항목이 발견되면 false(1)를 반환하도록 할 수 있습니다. 부정( !)이 발견되면 true, 그렇지 않으면 false를 테스트합니다.

예를 들어:

# does the lock file exist?
if ! find "$MAINTENANCE_LOCK/testLOCK" -mtime -1 -exec false {} + ; then
  # are there any .control files?
  if ! find "$PATH_TO_TRIGGER_FILES" -name '*.control' -exec false {} + ; then
    test_log_msg "test_SYSTEM" $NOTICE "Valid Maintenance Lock file found, test actions blocked." "status"
    test_log_email " " " " " " "test Actions were blocked because an testLOCK file less than 24hrs old is in place." " "
  else
    test_log_msg "test_SYSTEM" $NOTICE "Valid Maintenance Lock file in place." "status"
    exit
  fi
fi

이 작업을 자주 수행하거나 스크립트를 더 읽기 쉽고 자체적으로 문서화하기를 원하는 경우 함수로 래핑할 수 있습니다.

file_exists () {
  # The args to this function are passed directly to find,
  # so anything that works with find will work here.
  # And anything that breaks find will break this function too.
  # Also, you probably don't want to use any find arguments that
  # produce any output.

  if ! find "$@" -exec false {} + ; then
    # one or more matching files were found, return true
    return 0
  else
    # nothing found, return false
    return 1
  fi
}

if file_exists "$MAINTENANCE_LOCK/testLOCK" -mtime -1 ; then
  if file_exists "$PATH_TO_TRIGGER_FILES" -name '*.control' ; then
    ...
  else
    ...
  fi
fi

인수를 완전히 무시 하면 /bin/false인수 수에 관계없이 false(1)의 종료 코드만 반환합니다. 따라서 존재 여부만 테스트해야 하는 경우 유용합니다.아니요필요하면 유용하다계산일치하는 파일의 수입니다. 이 작업을 수행해야 하는 경우 다음과 같이 수행할 수 있습니다(GNU find 또는 기타 지원되는 find 사용 -printf).

if [ "$(find . -mtime -1 -printf 1 | wc -c)" -gt 10 ] ; then
  : do something here
fi

이것은 발견된 각 파일에 대한 문자를 인쇄합니다(어떤 문자가 인쇄되는지는 중요하지 않습니다. 여기서는 "1"을 사용하고 있지만 ".", "x" 또는 기타 문자에 대해 동일한 방식으로 작동합니다). 그들을 계산하는 데 사용됩니다 wc -c. 10개 이상 if이면 테스트는 true로 평가됩니다.

find-printf옵션을 지원하지 않는(POSIX도 아니지만 여전히 일반적인) GNU가 아닌 경우 다음을 사용할 -print0수 있습니다.

if [ "$(find . -mtime -1 -print0 | awk -v RS='\0' 'END{print NR}')" -gt 10 ] ; then
  : do something here
fi

이 버전은 출력 awk에 NUL로 구분된 레코드 수(즉, 일치하는 파일 수)를 인쇄합니다 .find

당신이 절대적으로 확신한다면전혀파일 또는 디렉토리 이름 중 하나에 줄 바꿈( ) 문자가 포함되면 대신 \nPOSIX 표준을 사용할 수 있습니다 (그리고 입력을 파이프할 수 있습니다 ). 그러나 이것에 대해 절대적으로 확신할 수 없기 때문에 이것은 결코 신뢰할 수 있는 것이 아닙니다. 파일 이름은 미래의 어떤 시점에도 존재하지 않을 것입니다. 즉, 지금은 잘 작동할 수도 있지만 내일이나 내년에 실패할 수도 있습니다.-print-print0wc -l

답변3

명령 은 find여러 파일을 반환해야 하므로 경고가 표시됩니다.

파일을 확인하고 싶다면 사용하는 것이 좋습니다stat

file_btime=$(stat -c%W /var/opt/test/maintenancelock/testLOCK)
time_now=$(date %s)
file_age=$(( time_now - file_btime ))

if [ $file_age -le 86400 ] ; then
   echo File is less then 24h old
fi

관련 정보