2012-04-17 7 views
4

현재 쉘 스크립트가 동시 로깅 할 때마다 왜 실패하는지 파악하려고합니다. 한 번씩 동안이 구문 오류와 함께 실패 지금bash 스크립트의 동시 로깅

log() 
{ 
    local l_text=$1 
    local l_file="/path/to/logs/$(date +%Y%m%d)_script.log" 

    local l_line="$(date +'%Y-%m-%d %H:%M:%S') $(hostname -s) ${l_text}" 

    echo ${l_line} >> ${l_file} 
} 

: 나는 여러 하위를 가지고

/path/to/script.sh: command substitution: line 163: syntax error near unexpected token `)' 
/path/to/script.sh: command substitution: line 163: `hostname -s) ${l_text}' 

문제가있다

나는 다음과 같은 쉘 기능이 프로세스는 각각 로그를 남기고 트랩을 보냅니다 (로깅이 수행되는 동안). 나는 문제를 디버깅하고 함수가 동시에 세 번 입력되었을 때이를 발견했다. 먼저 main 프로세스가 입력되고 child이 입력됩니다. date 부분이 l_text이 실행 된 후 main get이 에 의해 중단되었으므로 child이 발생하고이 trap에서 로그를 시도합니다. childtrap은 로깅을 끝내지 만, main이 트랩 후 재개되어 hostname 부분 (추정치)을 실행하려고 시도하고이 오류로 실패합니다.

따라서 main은 로그 문 일부에 $(date +'%Y-%m-%d %H:%M:%S') $(hostname -s) ${l_text} 부분을 생성하는 동안 잠자기하는 것을 좋아하지 않으므로 다시 시작할 수 없습니다. 로컬 변수와 스레드 안전 출력 메소드를 사용하고 있기 때문에 정상적으로 작동한다고 가정합니다.

여기서 내가 실행하고있는 일반적인 동시성 문제입니까? 또는 이것은 bash 스크립트의 트랩 메커니즘에 매우 특정한가요? C에서 SIGNAL 처리의 필수 항목을 알고 있으므로 SIGNAL 처리기에서만 특정 작업 만 허용된다는 것을 알고 있습니다. 그러나 bash 스크립트에서 SIGNAL을 처리 할 때도 동일한 예방 조치가 적용되는지는 잘 모릅니다. 나는 이것에 대한 문서를 찾으려고 노력했지만, 찾을 수있는 문서가 없기 때문에 스크립트에서 SIGNAL 처리와 관련된 문제를 지적했다.

편집 :

#!/bin/bash 

log() { 
    local text="$(date +'%Y-%m-%d %H:%M:%S') $(hostname -s) $1" 
    echo $text >> /dev/null 
} 

sub_process() { 
    while true; do 
    log "Thread is running" 
    kill -ALRM $$ 
    sleep 1 
    done 
} 

trap "log 'received ALRM'" ALRM 

sub_process & 
sub_process_pid=$! 
trap "kill ${sub_process_pid}; exit 0" INT TERM 


while true; do 
    log "Main is running" 
    sleep 1 
done 

가끔씩이 스크립트 때문에 구문 오류에 살해 얻을 것이다 : 여기

문제를 복제하는 데 사용할 수있는 실제로 사용 간단한 스크립트입니다 라인 5는 echo $text >> /dev/null이지만, 구문 오류가 hostname 명령을 언급했기 때문에 위에 게시 한 명령과 유사합니다. 또한 by-by-one 오류가 있다고 가정하고 실제 오류는 4 행에 있습니다. local text="$(date +'%Y-%m-%d %H:%M:%S') $(hostname -s) $1"입니다.

누구든지 위의 스크립트로 해결하려면 무엇을해야합니까? 나는 약간의 임시 변수에 문자열의 건설을 이동 시도을 벌써 :

log() { 
    local thedate=$(date +'%Y-%m-%d %H:%M:%S') 
    local thehostname=$(hostname -s) 
    local text="${thedate} ${thehostname} $1" 
    echo $text >> /dev/null 
} 

이 방법을 오류가 자주 나타납니다,하지만 여전히 존재하는, 그래서 이것은 진짜 수정하지 않습니다.

+5

'='주위의 공백 문자는 불법입니다. – kojiro

+0

@kojiro : 힌트를 주셔서 감사합니다 ... 공백 문자는 원본에 없습니다. 나는 코드를 좋은 예로 줄이면 실수로 그것을 도입했습니다. 나는 이것을 편집 할 것이다. – LiKao

+1

'thread'라는 이름은 여기 오해의 소지가 있습니다. bash는 쓰레드가 아닌 서브 프로세스를 사용합니다 ...'trap '에'$?'대신'$!'를 쓰고 싶습니다. $ ?; exit 0 "INT TERM' 그리고 'INT' /'TERM' /'ALRM'은'SIG' ('SIGINT')가 누락되었습니다. –

답변

1

나는 이것이 bash의 버그라는 것을 분명히 알 것이며, bash 개발자들에게 그것을 알려주기를 바란다. 최소한 문법적으로 정확한 코드가 무엇인지에 대해서는 구문 오류가 발생하지 않아야합니다.

기록의 경우 GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu)과 같은 결과가 나옵니다.

트랩 처리기에서 함수를 호출하지 않아도 문제를 해결할 수있는 것으로 나타났습니다. 예 :

trap "echo $(date +'%Y-%m-%d %H:%M:%S') $(hostname -s) received ALRM" ALRM 

trap "log 'received ALRM'" ALRM 

를 교체하는 것은 나를 위해 스크립트가 안정되어 있습니다.

I know about the commodities of SIGNAL handling in C, so I am aware that only certain operations are allowed in SIGNAL handlers. However I am not aware if the same precautions also apply when handling SIGNALs in a bash script.

나는 특별한 예방 조치를 취할 필요는 없지만 실제로는 그렇게 할 것입니다. 함수 호출없이 문제가 없어지는 것을 감안할 때, bash에서 무언가가 재진입이나 다시 실패를 막을 수있는 곳이 아닌 것 같아요.

+0

좋아, 이미 문제를보고했지만, 지금까지 나는 의미있는 피드백을받지 못했습니다. 나는 그것들을 가지고 있고 다음 릴리스 중 하나에서 해결책을 찾을 수 있기를 희망합니다. – LiKao