Bashでグラントシェルと通信

Bashでグラントシェルと通信

hadoop fsHDFSの照会にかかる遅い起動時間に疲れました。ただし、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_outpigコマンドをいつ処理するかを知るために、コメントを送信し、出力を受け取るコマンドでそれを検出してトークンに遭遇した"-- 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。)現在、解決できない問題は2つだけです。

  1. 初めてスクリプトを呼び出すと(つまり、/tmp/grunt_infifoがまだ存在せず、pigインスタンスがバックグラウンドで起動された場合)、ターミナル設定はとても混乱します。これ以上入力エコーが発生しなくなるため、reset通常の端末に戻るには盲目的に入力する必要があります。しかし、その後の呼び出しはうまく機能します。
  2. 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行が切れる場合もあり、中間部分が切られる場合もあります。これはとても奇妙です。また、手動でにコマンドを送信してから読み込もうとしましたが、同じ結果が得られましたが、ここではとして解析することは問題ではないことを確認しました。一般的にこれは大きな出力にも問題にならないようです。たとえば、長いディレクトリリストの場合はうまく機能します。pigfs -texthadoop/tmp/grunt_in/tmp/grunt_outcatsed

    $ 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次のコマンドで切り捨てられるか、追加の出力が表示されます。明らかに名前付きパイプを適切にフラッシュする方法が必要です。誰でもアドバイスがあれば嬉しいです。

おすすめ記事