web-dev-qa-db-ja.com

bashスクリプト-stdinからtarballを読み取る

スクリプトを作成する必要があるタスクがあり、ばかげて単純なはずだと感じていますが、実際にはかなり苦労しています。

特定の種類のアプリケーションをtarball形式で取得してビルドする短いbashスクリプトがあります。現在、アプリケーションの名前とtarballの場所の2つのコマンドライン引数を使用します。しかし、ビルドスクリプトをマルチホストシステムにデプロイする準備をしています。代わりに、このスクリプトでアプリケーションtarballをstdinに取り込み、sshにパイプ処理します。たとえば、次のようにスクリプトを呼び出します。

ssh build-Host "/usr/local/bin/build-app.sh myapp" < /tmp/myapp.tar.gz

このように呼び出されると、ビルドスクリプトは「myapp」というアプリをビルドしようとします。

ビルドスクリプトがtarballを読み取る前に、いくつかのサニティチェックを実行するようにします。さらに、サニティチェックが失敗した場合は正常に終了する必要があります。ビルドスクリプトでの最初の試みの要点は次のとおりです。

#!/bin/bash

appname=$1

# example sanity check
if [ ! -d "/apps/$appname" ]; then
    mkdir "/apps/$appname"
else
    echo "Error! The app already has been built."
    exit 1
fi

# more sanity checks...

# if passed all tests, then read stdin into tarfile
cat > "/apps/$appname/app.tar.gz"

# build app ...

これはほとんど機能します。問題は、bashスクリプトの途中でstdinから読み取る方法がわからないことです。 cat > fileトリックは、スクリプトの最初の行に配置した場合にのみ機能します。しかし、私はそれをしたくありません。スクリプトの最初の行では、サニティチェックは実行されておらず、tarfileを配置する場所を決定する方法もありません。スクリプトの複数のインスタンスを同時に実行している可能性があり、衝突を回避するための良い方法はありません。

cat > fileに加えて、< /dev/stdin > fileのようなトリックも試しましたが、非常によく似た結果が得られました。)

だから私も次のことを試しました:

#!/bin/bash

tarball="$(cat)"
appname="$1"

# example sanity check
if [ ! -d "/apps/$appname" ]; then
    mkdir "/apps/$appname"
else
    echo "Error! The app already has been built."
    exit 1
fi

# more sanity checks...

# if passed all tests, then read stdin into tarfile
echo -n "$tarball" > "/apps/$appname/app.tar.gz"

# build app ...

しかし、これも2つの理由で非常に問題がありました。まず、それは機能しませんでした。 echoは、-nフラグがあっても、バイナリデータ用に設計されていないようで、結果のtarfileが破損しています。次に、最初のステップとして、tarball全体を変数として格納する必要があります。これは、5MBのテストtarballの場合でも、必要以上に遅いだけでなく、特に私が扱う可能性のある大規模なアプリケーションでは、メモリ消費量が多いことを意味する可能性があります。

Stdinからtarfileを読み取るというアイデアが好きです。これは、bashスクリプトが中止する必要があると感じた場合にパイプを閉じることができることを意味し、ビルドスクリプトを呼び出す元のバージョンとは対照的に、bashスクリプトがすべてのアプリケーションtarballを配置する場所を決定できるようにします。このように見えました:

scp /tmp/myapp.tar.gz build-Host:/tmp/
ssh build-Host /usr/local/bin/build-app.sh myapp /tmp/myapp.tar.gz

この呼び出し方法は、(うまくいけば)明らかな理由で問題があります。

Stdinまたは他の形式のパイプやバッファーを読み取ることで、このbashスクリプトを機能させることができることを本当に望んでいます。これを機能させる方法について何かアイデアはありますか?

7
jayhendren

cat > fileは、以前にそれを読み取って入力ストリームを「使い果たし」たり、ファイル記述子を閉じたりしていない限り、いつ呼び出しても機能するはずです。これは完全に合法で通常のコマンドであり、少なくとも私の側では機能します。

6
orion