충돌 로그가 포함된 디렉토리가 있고 find 명령을 기반으로 bash 스크립트에서 조건문을 사용하고 싶습니다.
로그 파일은 다음 형식으로 저장됩니다.
/var/log/crashes/app-2012-08-28.log
/var/log/crashes/otherapp-2012-08-28.log
지난 5분 이내에 수정된 특정 애플리케이션에 대한 충돌 로그가 있는 경우에만 if 문이 true를 반환하도록 하고 싶습니다. find
내가 사용할 명령은 다음과 같습니다.
find /var/log/crashes -name app-\*\.log -mmin -5
if
나는 이것을 성명서에 적절하게 포함시키는 방법을 모른다 . 내 생각엔 이것이 효과가 있을 것 같다:
if [ test `find /var/log/crashes -name app-\*\.log -mmin -5` ] then
service myapp restart
fi
내가 잘 이해하지 못하는 몇 가지 사항이 있습니다.
- 나는 본 적이플래그가 있는 경우하지만 어떤 것을 사용해야 할지 잘 모르겠습니다.
- 해당 지시어가 필요합니까
test
, 아니면 find 명령의 결과를 직접 처리해야 합니까, 아니면 이를 사용하여find... | wc -l
행 수를 얻을 수 있습니까? - 이 질문에 100% 대답할 필요는 없지만
test
명령에서 반환된 반환 코드를 테스트하기 위한 것입니까? 보이지 않는가? 내부stdout
/외부stderr
? 페이지 를 읽었man
지만 언제 사용test
하고 디버깅하는 방법이 여전히 명확하지 않습니다.
답변1
[
및 test
동의어( [
require 제외 ]
)이므로 다음을 사용하고 싶지 않습니다 [ test
.
[ -x /bin/cat ] && echo 'cat is executable'
test -x /bin/cat && echo 'cat is executable'
test
조건이 true이면 종료 상태 0을 반환하고, 그렇지 않으면 0이 아닌 값을 반환합니다. 이는 실제로 종료 상태를 확인하는 프로그램으로 대체될 수 있습니다. 여기서 0은 성공을 의미하고 0이 아닌 경우 실패를 의미합니다.
# echoes "command succeeded" because echo rarely fails
if /bin/echo hi; then echo 'command succeeded'; else echo 'command failed'; fi
# echoes "command failed" because rmdir requires an argument
if /bin/rmdir; then echo 'command succeeded'; else echo 'command failed'; fi
그러나 위의 모든 예제는 프로그램의 종료 상태만 테스트하고 프로그램의 출력을 무시합니다.
의 경우 find
출력이 생성되는지 테스트해야 합니다. -n
비어 있지 않은 문자열을 테스트합니다.
if [[ -n $(find /var/log/crashes -name "app-*.log" -mmin -5) ]]
then
service myapp restart
fi
help test
테스트 매개변수의 전체 목록은 명령줄에서 호출하여 얻을 수 있습니다 bash
.
이는 조건에 공백이나 기타 특수한 경우가 있을 때 더 예측 가능하게 동작하는 bash
(대신 sh
)을 사용하면 작동합니다. [[ condition ]]
그렇지 않으면 일반적으로 를 사용하는 것과 동일합니다 [ condition ]
. 이 예에서는 이를 사용 했으며 [[ condition ]]
가능할 때마다 사용합니다.
또한 일반적으로 유사하게 작동하지만 중첩된 명령에 더 나은 로 `command`
변경 했습니다 .$(command)
답변2
find
오류 없이 성공적으로 종료되므로 종료 상태에 의존하여 파일을 찾았는지 확인할 수 없습니다. 하지만 말씀하신 대로 얼마나 많은 파일을 찾았는지 계산하고 그 수를 테스트할 수 있습니다.
다음과 같이 보일 것입니다:
if [ $(find /var/log/crashes -name 'app-*.log' -mmin -5 | wc -l) -gt 0 ]; then
...
fi
test
(일명 [
)은 명령의 오류 코드를 확인하지 않으며 이를 테스트하는 특수 구문이 있으며 테스트에 성공하면 오류 코드 0으로 종료하고 그렇지 않으면 1로 종료합니다. if
전달한 명령의 오류 코드를 확인하고 이를 기반으로 본문을 실행합니다 .
man test
(또는 help test
을 사용하는 경우 bash
) 및 help if
(ibid.)를 참조하세요 .
이 경우 wc -l
숫자가 출력됩니다. test
s 옵션을 사용하여 -gt
숫자가 보다 큰지 여부를 테스트합니다 0
. 그렇다면 test
(또는 [
)은 종료 코드를 반환합니다 0
. if
종료 코드는 성공으로 해석되고 코드는 해당 본문 내에서 실행됩니다.
답변3
이것은 ~이 될 것이다
if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5)" ]; then
또는
if test -n "$(find /var/log/crashes -name app-\*\.log -mmin -5)"; then
명령은 완전히 동일 test
합니다 . [ … ]
유일한 차이점은 이름과 마지막 매개변수로 [
end가 필요하다는 점입니다. ]
항상 그렇듯이 명령 대체에는 큰따옴표를 사용하십시오. 그렇지 않으면 명령의 출력이 find
단어로 나누어지고 일치하는 파일이 여러 개 있는 경우 구문 오류가 발생합니다(인수가 없는 경우 true [ -n ]
). 그러나 원하는 [ -n "" ]
것은 잘못된 것입니다. .
ksh, bash 및 zsh에서는 ash가 아닌 [[ … ]]
다른 구문 분석 규칙을 사용하여 사용할 수도 있습니다. 이는 [
일반 명령 [[ … ]]
이지만 구문 분석 구조가 다릅니다. 내부에 큰따옴표를 사용할 필요는 없습니다 [[ … ]]
(해롭지는 않지만). ;
명령 뒤에 오는 내용이 여전히 필요합니다 .
if [[ -n $(find /var/log/crashes -name app-\*\.log -mmin -5) ]]; then
이는 비효율적일 수 있습니다. 에 파일이 많으면 /var/log/crashes
find가 해당 파일을 모두 탐색합니다. 일치하는 항목을 찾은 직후 또는 즉시 검색을 중지해야 합니다. GNU find(비임베디드 Linux, Cygwin)에서는 기본 -quit
.
if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5 -print -quit)" ]; then
다른 시스템의 경우 파이프 find
입구는 head
최소한 첫 번째 일치 직후에 종료됩니다(파이프가 파손된 것을 발견하면 사망하게 됩니다).
if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5 -print | head -n 1)" ]; then
head -c 1
(명령이 지원 하는 경우 head
작동합니다 .)
또는 zsh를 사용하십시오.
crash_files=(/var/log/crashes/**/app-*.log(mm-5[1]))
if (($#crash_files)); then
답변4
find /var/log/crashes -name app-\*\.log -mmin -5 -exec service myapp restart ';' -quit
적합한 솔루션입니다.
-exec service myapp restart ';'
find
쉘이 아무것도 해석하지 않고 직접 실행하려는 명령이 호출 되도록 합니다 .
-quit
처리 후 명령이 종료되도록 하여 find
둘 이상의 파일이 조건과 일치하는 경우 명령이 다시 실행되지 않도록 합니다.