2016-07-01 2 views
2

20MiB CSV 파일 배치를 처리하는 스크립트가 있습니다 (선택 사항으로 약 4MiB까지 gzip 압축 됨). 수천 개의 파일이 있고 각각 개별적으로 처리하는 데 약 30 초가 걸립니다. 압축되지 않은 파일이나 압축 된 파일을 읽고 압축을 풀면 "거의 즉시"이루어 지므로 프로세스 수준에서 프로세스를 병렬 처리 할 수 ​​있다고 제안합니다. 사실 그것은 복잡한 Ruby 파이프 라인을 사용하여 수행되고 있습니다. 그러나, 나는 bash를 사용하여 루비 코드를 더 작은 부분으로 분해하려고 시도하고있다. 작업 제어를 위해, 나는 실행중인 작업의 옵션 최소로,이 날 wait_until_job_available를 호출 할 수 있습니다Bash 프로세스 대체 backgrounding으로 작업 제어

wait_until_job_available() { 
    maximum_jobs=${MAXIMUM_JOBS} 
    [ $# -eq 0 ] || maximum_jobs="${1}" 
    exit_status=0 
    RUNNING_JOBS=($(jobs -p)) 
    while [ ${maximum_jobs} -le ${#RUNNING_JOBS[@]} ] && [ 0 -eq "${exit_status}" ] 
    do 
     # `wait -n` requires bash 4.3 which is unfortunately not available on several recent RHEL-based Linux distributions such as Oracle Linux 
     wait -n 
     exit_status=$? 
     RUNNING_JOBS=($(jobs -p)) 
    done 
    return ${exit_status} 
} 

이 bash는 기능을 마련하려는에 코어의 수, 기본값을 생략하면 가능 (허용 bash 파이프 라인을 backgrounding하기 전에. 당신이 볼 수 있듯이

while read file 
do 
    CAT_COMMAND=cat 

    # if input file is gzip-compressed, pipe zcat instead of cat 
    if [ "${INFILE: -3}" == ".gz" ] 
    then 
     CAT_COMMAND=zcat 
    fi 

    # wait for a job to become available 
    wait_until_job_available 

    # read the uncompressed file, write processed data to file.out 
    process_file -i <(${CAT_COMMAND} ${file}) -o ${file}.out & 

# while searching for filesystem paths of type _f_ile 
done < <(find ${search_path} -type f) 

# wait for all background jobs to finish 
wait 

, 이것은 search_path 내의 모든 파일을 찾을 수 있어야하고 process_file 명령이 전달 :

그래서 나는 그런처럼 사용할 수 있습니다. 그렇게 함으로서, 나는 프로세스 치환을 사용하여 파일을 cat하거나 on-the-fly로 파일을 압축 해제한다; 입력 파일 이름은 압축되지 않은 파일의 내용을 내보내는 프로세스로 대체되며 출력 파일은 ".out"이 추가 된 원본 파일 이름입니다. process_file의 호출이 백그라운드로 보내지고 작업 제어로 전송됩니다. 멋쟁이 같네, 그렇지?

일부 파일이 제대로 처리되지 않는 것을 제외하고는.

process_file으로 처리되는 것으로보고 된 파일은 process_file의 별도 동시 인스턴스 인 경우에도 항상 /dev/fd/63으로보고됩니다. 반면에 파일을 임시로 복사하거나 압축을 풀고 임시 파일의 이름을 process_file으로 전달하면 실행이 정상적으로 이루어지며 모든 파일이 올바르게 처리 된 것처럼 보입니다.

특히 디스크 (성능)를 만지고 처리 후 임시 파일을 정리 (제거)해야하는 것과 관련하여 임시 파일을 만들지 않으려했습니다. 이 문제가 발생하면이를 막을 수 없습니다. 그래서 대체 프로세스 파이프 라인에 대한 의사 파일의 이름에 어떤 종류의 경쟁 조건이 있는지 궁금합니다. 아니면 오해하는 것처럼 보이는 프로세스 대체 또는 작업 제어에 대한 무언가가 있습니까?

참고로

, 내가 우분투 서버 14.04, 리눅스 3.19.0-59 배쉬 4.3.11 gzip으로 1.6

답변

1

을 사용하고 내가 파고의 조금 한 오른쪽에서 당신을 지적 할 수있을 것 방향.

분명히/dev/fd/63은 process_file에서 사용하는 표준 파일 디스크립터입니다. 따라서 process_file의 여러 인스턴스를 실행하면이 파일 설명자를 통해 모든 것을 보내려고합니다. 의심되는 경우 갈등이나 경쟁 조건이 발생할 수 있습니다.

이 페이지 file descriptors and bash shell scripting과이 페이지 redirection_tutorial에는 출력 방향 재 지정에 대한 예제가 있습니다.

고유 한 파일 설명자를 만들거나 설명자를 사용하는 동안 잠그기 위해 process_file을 수정해야 할 수도 있습니다.

+0

제 생각에 파일 디스크립터는 Bash에 의해 만들어졌습니다. – inetknght