답변:
Linux에서는 inotify 커널 서브 시스템을 사용하여 디렉토리에 파일이 나타날 때까지 효율적으로 대기 할 수 있습니다 .
while read i; do if [ "$i" = sleep.txt ]; then break; fi; done \
< <(inotifywait -e create,open --format '%f' --quiet /tmp --monitor)
# script execution continues ...
( <()
출력 재 지정 구문에 대해 Bash를 가정 )
고정 시간 간격 폴링과 비교하여이 방법의 장점
while [ ! -f /tmp/sleep.txt ]; do sleep 1; done
# script execution continues ...
커널이 더 많이 잠들었다는 것입니다. create,open
스크립트 와 같은 inotify 이벤트 사양을 사용하면 아래 파일을 /tmp
만들거나 열 때 스크립트가 실행되도록 예약됩니다 . 고정 시간 간격 폴링을 사용하면 각 시간 단위로 CPU주기가 낭비됩니다.
파일이 이미 존재할 때 open
등록 하는 이벤트도 포함 시켰습니다 touch /tmp/sleep.txt
.
inotifywait -e create,open --format '%f' --quiet /tmp/sleep.txt --monitor > /dev/null ; # continues once /tmp/sleep.txt is created/opened
습니까?
inotifywait
자체는 while 루프이며 파일을 열거 나 만들 때마다 줄을 출력합니다. 따라서 변경 될 때 중단하려면 while 루프가 필요합니다.
sleep.txt
특정 시점에 생성 될 프로세스를 시작하기 전에 스 니펫을 실행한다고 가정합니다 . 따라서 경쟁 조건이 없습니다. 이 질문에는 당신이 염두에 둔 시나리오에 대한 힌트가 포함되어 있지 않습니다.
inotifywait
지금까지 제공된 일부 기반 접근 방식 에는 몇 가지 문제점이 있습니다 .
sleep.txt
먼저 임시 이름으로 작성된 파일 이름 을 찾지 못했습니다 sleep.txt
. moved_to
이벤트 이외에도 일치해야 합니다.create
sleep.txt
이 만들어 졌는지 확인할 수 없습니다 . 뭐라고 경우 foo\nsleep.txt\nbar
파일은 예를 들어 생성 된?inotifywait
됩니까? 그런 다음 inotifywait
이미 존재하는 파일을 영원히 기다립니다. 시계를 설치 한 후 파일이 없는지 확인해야합니다 .inotifywait
파일을 찾은 후 일부 솔루션이 실행됩니다 (적어도 다른 파일이 작성 될 때까지).이를 해결하기 위해 다음을 수행 할 수 있습니다.
sh -c 'echo "$$" &&
LC_ALL=C exec inotifywait -me create,moved_to --format=/%f/ . 2>&1' | {
IFS= read pid &&
while IFS= read -r line && [ "$line" != "Watches established." ]; do
: wait for watches to be established
done
[ -e sleep.txt ] || [ -L sleep.txt ] || grep -qxF /sleep.txt/ && kill "$pid"
}
우리의 창조를 위해보고있는 것을 참고 sleep.txt
, 현재 디렉토리에 .
(당신이 할 거라고, 그래서 cd /tmp || exit
귀하의 예제에서 전에). 현재 디렉토리는 변경되지 않으므로 해당 파이프 라인이 성공적으로 리턴되면 sleep.txt
작성된 현재 디렉토리에 있습니다.
물론, 당신은 대체 할 수 .
와 /tmp
이상하지만, 동시에 inotifywait
실행되고, /tmp
여러 번 이름이 변경되었습니다 수 (대한 가능성 /tmp
때문에 때 파이프 라인 반환, 그렇지 않을 수도 있지만, 뭔가 일반적인 경우에 고려해야 할) 새 파일 시스템은, 그 위에 장착 될 /tmp/sleep.txt
만들어 졌는지하지만 /new-name-for-the-original-tmp/sleep.txt
대신합니다. /tmp
또한 간격에 따라 새 디렉토리를 작성할 수 있었으며 해당 디렉토리를 보지 않았으므로 작성된 디렉토리는 sleep.txt
감지되지 않습니다.
허용 된 답변은 실제로 작동하지만 (maxschlepzig 덕분에) 스크립트가 종료 될 때까지 inotifywait 모니터링을 백그라운드로 둡니다. inotifywait에 의해 모니터링되는 디렉토리가 점 (.)에서 '/ tmp'로 변경되면 요구 사항 과 정확히 일치하는 유일한 대답 (예 : sleep.txt가 / tmp 내에 표시되기를 기다리는 것)은 Stephane의 것 같습니다.
그러나 임시 디렉토리를 사용하고자하는 경우 에만 귀하의 sleep.txt 플래그를 퍼팅과 단지 파일 작품이 충분하다이 디렉토리를 볼 inotifywait를 요청, 디렉토리의 파일을 넣어 다른 그 누구도 장담 할 수 없다 :
1 단계 : 모니터링 할 디렉토리를 만듭니다.
directoryToPutSleepFile=$(mktemp -d)
2 단계 : 디렉토리가 실제로 있는지 확인
until [ -d $directoryToPutSleepFile ]; do sleep 0.1; done
3 단계 : 모든 파일이 내부에 나타날 때까지 기다립니다 $directoryToPutSleepFile
inotifywait -e create --format '%f' --quiet $directoryToPutSleepFile
넣을 파일 $directoryToPutSleepFile
이름은 sleep.txt awake.txt 일 수 있습니다. 순간 어떤 파일이 내부에 생성 $directoryToPutSleepFile
스크립트는지나 계속 inotifywait
문.
sleep.txt
두 개의 inotifywait 호출 사이에 파일이 생성되는 경우 파일 생성이 누락 될 수 있습니다.
sleep.txt
이 작성 될 때까지 여러 번 호출됩니다 . 예를 들어보십시오 touch /tmp/foo /tmp/sleep.txt
다음의 인스턴스 inotifywait
의지 보고서 foo
및 종료, 그리고 inotifywait를 그것의 생성을 감지하지 않도록 다음 inotifywait를 시작하는 시간의 sleep.txt 긴 이미 된 것입니다.
일반적으로 간단한 테스트 / 수면 루프 이외의 것을 안정적으로 만드는 것은 매우 어렵습니다. 주요 문제점은 테스트가 파일 작성과 경쟁한다는 점입니다. 테스트를 반복하지 않으면 작성 이벤트가 누락 될 수 있습니다. 셸을 사용하여 시작하는 대부분의 경우 가장 좋은 방법은 다음과 같습니다.
#!/bin/bash
while [[ ! -e /tmp/file ]] ; do
sleep 1
done
성능 문제로 인해 이것이 불충분하다는 것을 알게되면 셸을 사용하는 것이 처음에는 좋은 생각이 아닙니다.
maxschlepzig의 승인 된 답변 (및 /superuser/270529/monitoring-a-file-until-a-string-is-found 에서 허용 된 답변의 아이디어)을 바탕으로 다음을 개선 할 것을 제안합니다 ( 내 견해로는) 시간 초과와 함께 작동 할 수있는 답변 :
# Enable pipefail, so if the left side of the pipe fails it does not get silently ignored
set -o pipefail
( timeout 120 inotifywait -e create,open --format '%f' --quiet /tmp --monitor & ) | while read i; do if [ "$i" == 'sleep.txt' ]; then break; fi; done
EXIT_STATUS=$?
if [ "${EXIT_STATUS}" == '124' ]; then
echo "Timeout happened"
fi
주어진 시간 초과 내에 파일이 작성 / 열리지 않는 경우, 종료 상태는 124입니다 (시간 초과 문서 (man page)). 작성 / 열린 경우 종료 상태는 0 (성공)입니다.
예, inotifywait는 이런 방식으로 하위 셸에서 실행되며 시간 초과가 발생하거나 주 스크립트가 종료 될 때 (둘 중 먼저 오는 경우) 하위 셸의 실행이 완료됩니다.
$MAILPATH
.