2011-12-20 2 views
1

셸 스크립트를 작동 시키려고 시도하는 동안 약간의 스 텀퍼가 실행되었습니다. 나는 데이터베이스에서 한 줄을 읽고 텍스트 파일로 포맷하여 다른 소프트웨어와 함께 사용하는 스크립트를 만들고자한다. 스크립트는 약 5 천만 번 (대형 데이터베이스) 반복해야하며, 5,500 ~ 5,800 회 반복 될 때까지 문제가 없으므로 세그멘테이션 오류가 발생합니다.
strace (지난 몇 줄 아래에 있음)를 사용하여 오류를 추적하려고 시도했지만 실제로 무엇을보고 있는지 잘 모르겠습니다.셸 스크립트 - 분할 오류

clone(child_stack=0,flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,      child_tidptr=0xb76f8728) = 17547 
close(4)        = 0 
close(5)        = 0 
pipe([4, 5])       = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,  child_tidptr=0xb76f8728) = 17548 
close(3)        = 0 
close(5)        = 0 
pipe([3, 5])       = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17549 
close(4)        = 0 
close(5)        = 0 
pipe([4, 5])       = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17550 
close(3)        = 0 
close(5)        = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17551 
close(4)        = 0 
close(-1)        = -1 EBADF (Bad file descriptor) 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17546 
--- SIGCHLD (Child exited) @ 0 (0) --- 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17547 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17548 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17549 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17551 
--- SIGCHLD (Child exited) @ 0 (0) --- 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17550 
--- SIGCHLD (Child exited) @ 0 (0) --- 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17545 
--- SIGCHLD (Child exited) @ 0 (0) --- 
write(1, "OK!\n", 4OK! 
)     = 4 
pipe([3, 4])       = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17552 
close(4)        = 0 
read(3, "10632\n", 128)     = 6 
read(3, "", 128)      = 0 
close(3)        = 0 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17552 
--- SIGCHLD (Child exited) @ 0 (0) --- 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17553 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17553 
--- SIGCHLD (Child exited) @ 0 (0) --- 
write(1, "Preparing file 10632 of ", 24Preparing file 10632 of) = 24 
write(1, "51041073(7) ....", 1651041073(7) ....)  = 16 
pipe([3, 4])       = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17554 
close(4)        = 0 
read(3, "8\n", 128)      = 2 
read(3, "", 128)      = 0 
close(3)        = 0 
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17554 
--- SIGCHLD (Child exited) @ 0 (0) --- 
pipe([3, 4])       = 0 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17555 
close(4)        = 0 
read(3, "", 128)      = 0 
close(3)        = 0 
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV}], 0, NULL) = 17555 
--- SIGCHLD (Child exited) @ 0 (0) --- 
--- SIGSEGV (Segmentation fault) @ 0 (0) --- 
+++ killed by SIGSEGV +++ 
Segmentation fault 

스크립트
은 다음과 같습니다 : 정보의 중편 소설에 대한

#!/bin/sh 
#----VARS---- 
prefix="10.0.3.2/read/" 
oprdir="/home/andrew/doc/read/" 
throttle=0 

#---------------- 
x=5000 
advcount=0 
count=`curl "$prefix""count.php" 2> /dev/null` 

#----Funcs---- 
getline() 
{ 
    #Run curl to get the line of text 
    #TODO -n 
    echo -n "Preparing file" $x "of " 
    if [ $advcount -ge 25 ] 
    then 
    count=`curl "$prefix""count.php" 2> /dev/null` 
    advcount=0 
    fi 
    echo -n $count"("$advcount")" "...." 
    advcount=`expr $advcount + 1` 

    line=`curl "$prefix""testfile-prep.php?x=$x" 2> /dev/null` 
    if [ "$line" = "ERR ERROR: X OUTSIDE RECORDS." ] 
    then 
    echo "ERROR: X OUTSIDE DB... WAITING TO RETRY." 
    sleep 60 
    getline 
    fi 
    prepline 
} 

prepline() 
{ 
    echo $line | sed 's/^[0-9]*\./\n./g' | sed 's/\([a-zA-Z]*\)\./\1\n./g' | sed 's/\,/\n\,/g' | sed 's/(\(.*\)/(\n\1/g' | sed 's/\(.*\))/\1\n)/g' | sed 's/ /\n/g'> out-0-$x.dat 
    echo "OK!" 
    #cat out-$x.dat 
    advance 
} 
advance() 
{ 
    x=`expr $x + 1` 
    sleep $throttle 
    getline 
} 

cd "$oprdir" 
getline 

죄송는, 어떤 도움이 감사합니다.

+0

* "스크립트를 5 천만 회 반복해야합니다."*이 말을해야합니다. 컴파일 된 (또는 JIT 가상 머신) 구현이이 사용 사례에 좋은 아이디어 일 수 있습니다. 아니면 IO 바인딩 된 그대로 표시 할 수 있습니까? – dmckee

+1

'prepline' 함수는'sed -e 'command1 -e'command2 '...'를 사용하여 여러 개의'sed' 명령을 하나의 명령으로 조합 할 수 있습니다. 이것은 아마도 충돌과 관련이 없지만 프로세스 수를 상당히 줄입니다. –

답변

4

귀하는 stack overflow입니다.

getline 함수는 prepline을 호출하며 advance을 호출하며 getline을 호출합니다.

예외가 아닌 조건에서 함수를 호출하는 대신 어떤 종류의 루프를 사용해야합니다. 오류 케이스의 자체 호출은 괜찮습니다. 스택 오버플로가 발생하는 5,000 개의 오류는 없습니다.

+0

'_ 반복은 인간입니다. 되풀이하다, 신성하다? _ 분명히이 경우 분명히는 아니다. 명시 적 반복은 어딘가에 문제를 해결할 것입니다. –

+0

그걸 수정하는 것 같습니다. 왜 내가 그랬는지 그 이유는 모르겠다. 감사! – akester