2009-07-03 4 views
6

아주 정기적으로 파일에 몇 가지 내용이 쓰여진 후 파일을 읽은 후 그 파일을 읽는 응용 프로그램이 실행됩니다. 우리 회사를 통해 네트워크 대기 시간이 크게 다르다는 것을 알게되었습니다. 예를 들어 sleep 2은 간단하게는 충분하지 않습니다.쉘 스크립트에서 NFS 대기 시간을 다루는 방법

waitLoop() 
{ 
    local timeout=$1 
    local test="$2" 

    if ! $test 
    then 
     local counter=0 
     while ! $test && [ $counter -lt $timeout ] 
     do 
     sleep 1 
     ((counter++)) 
     done 

     if ! $test 
     then 
     exit 1 
     fi 
    fi 
} 

test="[ -e $somefilename ]" 작동 :

나는 이런 (구성) 타임 아웃 루프를 작성했습니다. 그러나 테스트의 존재 자체로는 충분하지 않으며 때로는 특정 문자열이 파일에 기록되었는지 테스트해야합니다. 나는 test="grep -sq \"^sometext$\" $somefilename"을 시도했지만 이것이 작동하지 않았습니다. 누군가 왜 저에게 말할 수 있습니까?

이러한 테스트를 수행하는 다른 옵션이 있습니까?

+0

파일에서 꼬리를 실행하고 꼬리의 출력 (즉, 마지막 줄) 만 검사 할 수 있습니까? 꼬리가 파일을 바꿀 때 검사하기 위해 스크립트를 더 똑똑하게 검사한다고 가정합니다. (그리고 가능성은 꼬리가 더 적절한 방식으로 수행합니다) – nos

+0

올바른 접근 방식은 "일부 물건"이 무엇이고 무엇이 "응용 프로그램"입니다. 해결하고자하는 실제 문제에 대해 더 자세히 설명해 주시겠습니까? 서면으로 된 질문은 다소 모호합니다. 당신이 생각하지 못했던 완전히 다른 접근법이있을 수 있습니다. –

+0

내 수정 된 답변보기 –

답변

1

당신은 테스트 변수이 방법을 설정할 수 있습니다

test=$(grep -sq "^sometext$" $somefilename) 

당신의 grep가 작동하지 않는 이유는 따옴표 인수를 전달하기 정말 어려운 것입니다. 당신은 eval를 사용해야합니다 :

if ! eval $test 
0

나는 라고 말하고 싶습니다. 텍스트 파일의 문자열을 확인하는 방법은 grep입니다.

당신의 정확한 문제는 무엇입니까?

또한 루트 문제를 제거하기 위해 NFS 마운트 매개 변수를 조정할 수도 있습니다. 동기화가 도움이 될 수도 있습니다. NFS 문서를 참조하십시오.

+0

마운트 매개 변수를 변경할 가능성이 없습니다. 내 스크립트는 대기 시간을 처리 할 수있을만큼 강력해야합니다. 문제는 grep 자체가 아니라 grep 테스트가 예상대로 평가되지 않는다는 것입니다. –

+0

네가 환경을 바꿀 수 없다면 문제가 생긴다. 어쨌든 파일을 변경 한 후 '동기화'를 시도 했습니까? NFS 문서에 따르면 (sysnc.2를 호출하는 한)해야합니다. 덕분에 – TheBonsai

0

"if"에서 waitLoop을 사용하려는 경우 "exit"를 "return"으로 변경하여 나머지 스크립트가 오류 상황을 처리 할 수 ​​있습니다 (메시지조차도 없음). 스크립트가 다르게 죽기 전에 실패한 내용을 사용자에게 알려줍니다.

다른 문제는 "$ test"를 사용하여 명령을 실행하면 실제로 실행될 때 셸 확장을하지 않고 평가하는 것입니다. 그래서 test = "grep \"foo \ "\"bar baz \ ""라고 말하면, 7 문자 네임 바 baz가있는 파일에서 세 개의 문자열 foo를 찾는 대신, 다섯 개의 char 문자열을 찾을 것입니다 9 개의 char 파일 "bar baz"에서 "foo".

그래서 당신은 당신이 쉘 마법 및 설정 테스트 = '그렙 -sq^sometext의 $의 somefilename를'필요하지 않습니다 결정할 수 있습니다, 또는 당신이 처리 할 수있는 쉘을 얻을 수있는 같은 것을 명시 적으로 인용 :

if /bin/sh -c "$test" 
then 
    ... 
0

시도가가를 열지 않고 쓸 때 감지하기 위해 파일 수정 시간을 사용. 예 :

old_mtime=`stat --format="%Z" file` 
# Write to file. 
new_mtime=$old_mtime 
while [[ "$old_mtime" -eq "$new_mtime" ]]; do 
    sleep 2; 
    new_mtime=`stat --format="%Z" file` 
done 

여러 프로세스가 동시에 파일에 액세스하려고하면이 기능은 작동하지 않습니다.

0

방금 ​​똑같은 문제가있었습니다. 나는 당신이 당신의 작전에 포함시키는 타임 아웃 대기와 비슷한 접근법을 사용했다; 그러나 파일 크기 검사도 포함되었습니다. 마지막으로 체크 된 이후 파일 크기가 증가했다면 타임 아웃 타이머를 리셋했습니다. 필자가 작성한 파일은 몇 기가 될 수 있으므로 NFS를 통해 작성하는 데 시간이 걸릴 수 있습니다.

이것은 특별한 경우에 과도 할 수 있습니다. 그러나 필기를 마친 후에 필자의 필기 과정에서 파일의 해시를 계산하도록했습니다. 나는 md5를 사용했지만, crc32와 같은 것도 작동 할 것이다. 이 해시는 작성자에서 (여러) 독자에게 브로드 캐스팅되었고 판독기는 a) 파일 크기가 증가하는 것을 멈추고 b) 파일의 (새로 계산 된) 해시가 작성자가 보낸 해시와 일치 할 때까지 기다립니다.

+0

. 어떻게 MD5 해시를 브로드 캐스트합니까? 그리고 그 해시에 대한 대기 루프만으로는 충분하지 않을까요? –

+0

우리는 선반 네트워크 메시징 프로토콜을 사용하고 있습니다 (POE는 Perl이지만 JMS 또는 AMQP는이 기능을 위해 동일합니다). 이 경우 작성자와 독자는 서로 다른 시스템에 있으며 작성자는 쓰기가 완료되었음을 나타내는 메시지의 일부로 해시를 브로드 캐스트합니다. 독자는 메시지를 집어 들고 파일 크기가 커지는 것을 기다린 다음 해시를 확인합니다. –

+0

그리고 네, 해시에 대한 대기 루프도 작동합니다. 그러나 해시를 계산하는 것은 파일 크기를 확인하는 것보다 상대적으로 비용이 많이 들기 때문에 무겁고 값 비싼 것의 "게이트 키퍼"로 쉽고 싼 것을 수행합니다 . –

0

우리에게는 비슷한 문제가 있지만 다른 이유가 있습니다. 우리는 SFTP 서버로 보내진 파일을 읽습니다. 스크립트를 실행하는 시스템은 SFTP 서버가 아닙니다.

내가 한 것은 파일의 cksum을 수행하기 위해 cron (수면과 루프가 작동하더라도)에서 설정 한 것입니다. 이전 cksum이 현재 cksum과 일치하면 (지정된 시간 동안 파일이 변경되지 않은 경우) 쓰기가 완료되었음을 알게되고 파일을 전송합니다.

백업하기 전에 로컬 파일을 덮어 쓰지 않고 원격 파일에 일치하는 행에 두 개의 cksum이 있고 그 cksum이 로컬 파일과 일치하지 않을 때만 전송합니다.

코드 예제가 필요한 경우 필자가 그 코드를 파헤 칠 수 있다고 확신합니다.

0

쉘이 술어를 단어로 분리하고 있습니다. 아래의 코드로 [email protected] 모든 잡아 :

#! /bin/bash 

waitFor() 
{ 
    local tries=$1 
    shift 
    local predicate="[email protected]" 

    while [ $tries -ge 1 ]; do 
    ((tries--)) 

    if $predicate >/dev/null 2>&1; then 
     return 
    else 
     [ $tries -gt 0 ] && sleep 1 
    fi 
    done 

    exit 1 
} 

pred='[ -e /etc/passwd ]' 
waitFor 5 $pred 
echo "$pred satisfied" 

rm -f /tmp/baz 
(sleep 2; echo blahblah >>/tmp/baz) & 
(sleep 4; echo hasfoo >>/tmp/baz) & 

pred='grep ^hasfoo /tmp/baz' 
waitFor 5 $pred 
echo "$pred satisfied" 

출력 :

 
$ ./waitngo 
[ -e /etc/passwd ] satisfied 
grep ^hasfoo /tmp/baz satisfied 

너무 나쁜 타이프 라이터가 실시간으로 보는만큼 흥미 없습니다. 당신은 여기에 '명명 된 파이프'를 만들 수 있습니다

-1

좋아요 ... 이것은 당신이 파일을 제어 할 수있는 경우

는 ... 조금 괴팍스러운 것입니다. (쓰기 프로그램 작동 방식에 따라) 동기화 된 방식으로 파일을 모니터 할 수 있습니다.

명명 된 파이프를 만들기 : 간단한에서

mkfifo file.txt 

으로 동기 수신기 설정 :

echo "Hello There" > file.txt 
:

while : 
do 
    process.sh < file.txt 
end 

테스트 보낸 사람을 만들기를

'process.sh'는 다음과 같습니다. 귀하의 논리가 어디로 가는가 : 이것은 보낸 사람이 출력을 쓸 때까지 차단됩니다. 이론상으로 작가 프로그램은 수정할 필요가 없습니다 ....

경고 : 수신자가 어떤 이유로 작동하지 않을 경우, 발신자를 차단할 수 있습니다!

귀하의 요구 사항에 맞는지는 모르지만 조사 할 가치가있을 수 있습니다.

동기화를 피하려면 'lsof'를 시도해보십시오.

http://en.wikipedia.org/wiki/Lsof

아무것도 그렇지 않으면 (즉, 쓰기 과정이 완료)에 기록되지 않은 경우에만 파일에서 읽고 싶은 것을 가정 - 당신은 아무것도 다른 거기에 파일 핸들이 없습니다 여부를 확인할 수 있을까?

+0

좋은 생각이지만 주목할 점은 보낸 사람과받는 사람이 동일한 NFS 탑재 지점을 가지고 있어도 두 개의 다른 호스트에 있으면 명명 된 파이프가 작동하지 않는다는 것입니다. – dogbane

+0

doh! 제목을 제대로 읽었어야합니다. 예를 들어 NFS 마운트에서 작동하지 않습니다! – monojohnny

관련 문제