hadoop fs
HDFS를 쿼리하는 데 소요되는 느린 시작 시간 에 지쳤습니다 . 그러나 Pig "grunt shell"에서 HDFS 파일 시스템 명령을 사용하는 것은 매우 빠르기 때문에 HDFS 자체에는 문제가 되지 않습니다. 그러나 일부 HDFS 명령을 실행하려는 경우 항상 그런트 셸을 시작하는 것은 비현실적입니다. 그래서 저는 백그라운드에서 그런트 셸 인스턴스를 시작하고 후속 호출을 위해 열어두기 위해 다음 스크립트를 작성했습니다.
#!/bin/bash
in=/tmp/grunt_in
out=/tmp/grunt_out
err=/tmp/grunt_err
if [ ! -p $in ]
then
mkfifo $in
mkfifo $out
( pig <>$in >$out 2>$err; rm $in $out ) &
disown
fi
>$err # Truncate errors
echo "fs $*" >$in
echo >$in
echo "-- end" >$in
sed -n '/^grunt> -- end/q;/^grunt>/d;p' $out
cat $err >&2
물론 입력을 스크립트로 전송해야 할 뿐만 아니라 스크립트의 출력도 현재 bash 세션으로 리디렉션해야 합니다. 나는 이것을 달성하기 위해 여기서 FIFO를 /tmp/grunt_in
사용하고 있습니다 /tmp/grunt_out
. pig
명령을 언제 처리해야 하는지 파악하기 위해 "-- end"
주석을 보내고 sed
출력을 수신하는 명령에서 이를 감지하여 end
토큰을 만날 때 종료하고 모든 프롬프트를 건너뛰어 관련 부분만 출력하도록 합니다 grunt>
.
<>$in
출력을 로 리디렉션하더라도 $out
첫 번째 명령 이후 Pig가 종료되는 것을 방지하기 위해 입력 FIFO를 추가해야 합니다. 정확한 이유는 모르겠지만 이렇게 되는 것 같아요.
이것은 실제로 꽤 잘 작동합니다. 예를 들어
$ time hadoop fs -ls
Found 38 items
[ skipped output ]
real 0m1.828s
user 0m3.160s
sys 0m0.137s
$ time dfs -ls
[apollo@dc1-had03-clusterutil01 reporting-APO-5394]$ time dfs -ls
Found 38 items
[ skipped output ]
real 0m0.149s
user 0m0.003s
sys 0m0.006s
(여기서 스크립트를 호출합니다 dfs
.) 현재 해결할 수 없는 문제는 두 가지뿐입니다.
- 처음으로 스크립트를 호출하면(즉,
/tmp/grunt_in
fifo가 아직 존재하지 않고 pig 인스턴스가 백그라운드에서 시작되는 경우) 터미널 설정이 어쩐지 엉망이 됩니다. 더 이상 입력 에코가 발생하지 않으므로reset
일반 터미널로 돌아가려면 맹목적으로 입력해야 합니다. 그러나 후속 호출은 잘 작동합니다. HDFS에서 파일 내용을 출력하려고 하면 출력이 임의로 잘립니다
-cat
.-text
예를 들어:$ hadoop fs -text some-medium-size.gz|wc -l 3606 $ dfs -text some-medium-size.gz|wc -l text: Unable to write to output stream. 9
여기서 오류 메시지를 확인하세요 . 에서 온 것이 아니라 의 명령 에서 온
text: Unable to write to output stream.
것입니다 . 여기처럼 처음 9~10줄이 잘리는 경우도 있고 중간 부분이 잘리는 경우도 있습니다. 이것은 매우 이상합니다. 또한 수동으로 에 명령을 보내고 으로 읽어 보려고 시도했지만 동일한 결과를 얻었지만 여기서는 으로 구문 분석하는 것이 문제가 아니라는 것을 확인했습니다. 일반적으로 이것은 큰 출력에도 문제가 되지 않는 것 같습니다. 예를 들어 긴 디렉토리 목록의 경우 잘 작동합니다.pig
fs -text
hadoop
/tmp/grunt_in
/tmp/grunt_out
cat
sed
$ dfs -ls -R|wc -l 10686
(이것은 와 동일한 결과를 제공합니다 hadoop fs -ls -R|wc -l
)
hadoop fs -text
어쩌면 마지막 문제는 and 자체에 대한 문제일까요 hadoop fs -cat
? 아니면 명명된 파이프를 사용하는 데 문제가 있습니까?
답변1
지금은 이 버전이 더 확실하지 않습니다.
#!/bin/bash
in=/tmp/grunt_in
out=/tmp/grunt_out
err=/tmp/grunt_err
if [ ! -p $in ]
then
mkfifo $in
mkfifo $out
mkfifo $err
{ script -q -c "pig 1>$out 2>$err" <>$in; rm $in $out $err; } &
fi
{
echo "fs $*"
echo
echo "-- end"
} >$in
cat $err >&2 &
catpid=$!
sed -n -u '/^grunt> -- end/q;/^grunt>/d;p' <$out
kill $catpid
그래서 명령 내부에서 stderr를 리디렉션했습니다 script
. 또한 괄호를 중괄호로 바꾸고 disown
그렇게 해도 아무런 이점이 없으므로 제거했습니다. $err
조기에 출력할 수 있도록 FIFO로 교체하기도 했지만 이로 인해 킬도 추가 되었습니다 cat
.
여태까지는 그런대로 잘됐다와는 별개로파이프를 통해 출력을 자르면 head
다음 명령에서 잘리거나 추가 출력이 표시됩니다. 분명히 명명된 파이프를 적절하게 플러시하는 방법이 필요합니다. 누구든지 조언이 있으면 기뻐할 것입니다.