큰 파일과에 이상한 문제가 있습니다 bash. 이것은 맥락입니다 :
- 나는 75G와 400,000,000+ 라인의 큰 파일을 가지고 있습니다 (로그 파일입니다.
- 각 줄의 처음 10자는 YYYY-MM-DD 형식의 타임 스탬프입니다.
- 그 파일을 하루에 한 파일 씩 분할하고 싶습니다.
작동하지 않는 다음 스크립트로 시도했습니다. 내 질문은이 스크립트가 작동하지 않고 대안 솔루션이 아니라는 것입니다 .
while read line; do
new_file=${line:0:10}_file.log
echo "$line" >> $new_file
done < file.log
디버깅 후 new_file변수 에서 문제를 발견했습니다 . 이 스크립트는 :
while read line; do
new_file=${line:0:10}_file.log
echo $new_file
done < file.log | uniq -c
결과를 다음과 같이 제공합니다 ( x데이터를 기밀로 유지하기 위해 es를 넣었습니다. 다른 문자는 실제 문자입니다). 통지 dh와 짧은 문자열 :
...
27402 2011-xx-x4
27262 2011-xx-x5
22514 2011-xx-x6
17908 2011-xx-x7
...
3227382 2011-xx-x9
4474604 2011-xx-x0
1557680 2011-xx-x1
1 2011-xx-x2
3 2011-xx-x1
...
12 2011-xx-x1
1 2011-xx-dh
1 2011-xx-x1
1 208--
1 2011-xx-x1
1 2011-xx-dh
1 2011-xx-x1
...
내 파일 형식에 문제가 없습니다 . 스크립트 cut -c 1-10 file.log | uniq -c는 유효한 타임 스탬프 만 제공합니다. 흥미롭게도 위의 출력 중 일부는 다음과 cut ... | uniq -c같습니다.
3227382 2011-xx-x9
4474604 2011-xx-x0
5722027 2011-xx-x1
uniq count 후에 4474604내 초기 스크립트가 실패했음을 알 수 있습니다.
bash에서 내가 모르는 한계에 도달 했습니까, bash에서 버그를 발견 했습니까 (이음새가 거의 없을 것입니다), 또는 내가 잘못한 것이 있습니까?
업데이트 :
파일의 2G를 읽은 후에 문제가 발생합니다. 이음새 read와 리디렉션은 2G보다 큰 파일을 좋아하지 않습니다. 그러나 여전히 더 정확한 설명을 찾고 있습니다.
업데이트 2 :
그것은 분명히 버그처럼 보입니다. 다음과 같이 재현 할 수 있습니다.
yes "0123456789abcdefghijklmnopqrs" | head -n 100000000 > file
while read line; do file=${line:0:10}; echo $file; done < file | uniq -c
그러나 이것은 해결 방법으로 잘 작동합니다 (유용한 것으로 찾은 이음새 cat).
cat file | while read line; do file=${line:0:10}; echo $file; done | uniq -c
GNU와 데비안에 버그가 제기되었습니다. 영향을받는 버전은 bashDebian Squeeze 6.0.2 및 6.0.4에서 4.1.5입니다.
echo ${BASH_VERSINFO[@]}
4 1 5 1 release x86_64-pc-linux-gnu
업데이트 3 :
내 버그 보고서에 빠르게 반응 한 Andreas Schwab 덕분에이 오류는이 오작동에 대한 해결책입니다. 영향을받는 파일은 lib/sh/zread.cGilles가 더 빨리 지적한대로입니다.
diff --git a/lib/sh/zread.c b/lib/sh/zread.c index 0fd1199..3731a41 100644
--- a/lib/sh/zread.c
+++ b/lib/sh/zread.c @@ -161,7 +161,7 @@ zsyncfd (fd)
int fd; { off_t off;
- int r;
+ off_t r;
off = lused - lind; r = 0;
이 r변수는의 반환 값을 보유하는 데 사용됩니다 lseek. 으로 lseek되돌아가 파일의 선두로부터의 오프셋 (offset)가 2기가바이트 위에있을 때,의 int값은 시험, 이로 인해 음 if (r >= 0)이 성공해야 어디 실패합니다.
readbash 의 문장 한계 방향을 가리 키도록 솔기가 있습니다.