0

説明

以下を変更せずに実行するThe Scriptと、(正しく) 出力されます。

2 1 スタート

以下のスクリプトのステートメントのコメントを外した後exec、ファイル記述子 3 は標準出力を指し、ファイル記述子 4 は標準エラーを指します。

exec 3>&1 4>&2

また、すべての標準出力と標準エラーは、コンソールに出力する代わりにファイルに記録されます。

# Two variances seen in the script below
exec 1>"TEST-${mode:1}.log" 2>&1  # Log Name based on subcommand
exec 1>"TEST-bootstrap.log" 2>&1  # Initial "bootstrap" log file

exec ステートメントが配置されると、スクリプトは 3 つのファイル (コンテンツを含む) を作成する必要があります。

TEST-bootstrap.log(正常に作成されました - 空のファイル)

TEST-one.log(正常に作成されました)

ワンスタート

TEST-two.log(作成されません)

2 1 スタート

しかし、代わりに、最初のログ ファイルの後に停止するように見え、作成されませんTEST-two.logexecコメントアウトされたステートメントで機能することを考えると、何が問題になる可能性がありますか?

スクリプト

#!/bin/bash
SELFD=$(cd -P $(dirname ${0}) >/dev/null 2>&1; pwd)  # Current scripts directory
SELF=$(basename ${0})   # Current scripts name
SELFX=${SELFD}/${SELF}  # The current script exec path

fnOne() { echo "one ${*}"; }
fnTwo() { echo "two ${*}"; }

subcommand() {
    # exec 3>&1 4>&2
    # exec 1>"TEST-${mode:1}.log" 2>&1
    case "${mode}" in
        -one) fnOne   ${*}; ;;
        -two) fnTwo   ${*}; ;;
    esac
}

bootstrap() {
    # exec 3>&1 4>&2
    # exec 1>"TEST-bootstrap.log" 2>&1
    echo "START" \
        | while read line; do ${SELFX} -one ${line}; done \
        | while read line; do ${SELFX} -two ${line}; done
    exit 0
}

mode=${1}; shift

case "${mode:0:1}" in
    -) subcommand ${*} ;;
    *) bootstrap ${mode} ${*} ;;
esac
exit 0

このスクリプトは、厳密には、私の別のより複雑なスクリプトで直面している問題の孤立した例です。できるだけ簡潔にまとめましたが、必要に応じて拡張します。

私が達成しようとしていること(興味のある人は余分に読んでください)

上記では、簡単にするためにThe Scriptの代わりにwhileループを使用しており、デバッグとここでの質問を容易にするために「1」と「2」をエコーする単純な関数を使用しています。

私の実際のスクリプトでは、プログラムは、URL からアーカイブのリストをフェッチし、それらをダウンロードし、それらのコンテンツを抽出し、結果のファイルをそれぞれ処理する次の関数を持ちlist-archivesます。これらの操作にはさまざまな時間がかかることを考慮して、並行して実行することを計画しました。私のスクリプトの関数は次のようになります。downloadextractprocessbootstrap()

# program ./myscript
list-archives "${1}" \
    | parallel myscript -download \
    | parallel myscript -extract \
    | parallel myscript -process

そして、次のように呼び出されます。

./myscript "http://www.example.com"

私が達成しようとしているのは、独自の関数を並行して呼び出し、実行するすべてを記録できるプログラムを開始する方法です。これは、データが最後にいつフェッチされたかを判断したり、エラーをデバッグしたりするのに役立ちます。

また、サブコマンドで呼び出されたときにプログラムにログを記録させたいと思います。

# only list achives
>> ./myscript -list-archives "http://www.example.com"
# download this specific archive
>> ./myscript -download "http://www.example.com/archive.zip" 
# ...
4

2 に答える 2

2

これが問題だと思います:

echo "START" \
    | while read line; do ${SELFX} -one ${line}; done \
    | while read line; do ${SELFX} -two ${line}; done

最初のwhileループはステートメントSTARTから読み取ります。echo2 番目のwhileループは、最初のループの出力を処理しwhileます。しかし、スクリプトは stdout をファイルにリダイレクトしているため、2 番目のループには何もパイプされず、すぐに終了します。

何を達成しようとしているのかが明確ではないため、これを「修正」する方法がわかりません。パイプラインの次のコマンドに何かをフィードしたい場合は、元の stdout を保存するために慎重に使用した FD 3 にエコーすることができます。

于 2013-07-19T20:32:42.457 に答える