この "${@}" 1> >(2log) 2> >(2log2scr | tee >&2) の PID を取得できません。

この "${@}" 1> >(2log) 2> >(2log2scr | tee >&2) の PID を取得できません。

これを行う方法に関する情報を検索しましたが、解決策が見つかりませんでした。私は必要に応じてプロセス置換を使用します。続行する前に、すべての処理が完了するのを待ちたいです。

私のPIDをどのように取得しますか?以下の「ランナー」機能では、待ってもいいですか?

デフォルトでは、実行する作業は実行してからエラーとエラーを標準出力に書き込むことです。間違った応答を除いてうまくいきます。

"${@}" 1> >(2log) 2> >(2log2scr | tee >&2) 
pid=????                                      # <<< HERE
while [ -e /proc/"$pid" ]; do sleep 0.1; done # <<< HERE

次のようなことを試しましたが、うまくいきません。

  1. pid=$(exec sh -c "${@}" 1>>(2log) 2>>(2log2scr | tee >&2) )

  2. これは部分的に機能します。私の評価が壊れています。

>     runner success &
>     while [ -e /proc/$! ]; do sleep 0.1; done

出力

started running

FAILURE: **** 4.4.19(1)-release ****
 finished running

EVAL IS:

ご協力ありがとうございます。

テストに必要な場合、スクリプト全体は次のようになります。

#!/bin/bash
logfile='test.log'
logprep() {
    local in=$(cat)
    in=$(echo "$in" | perl -pe 's/\**//smig')   # for proc subst
    # Return prepped string
    echo -e "preped for logging: '$in'"
}   
2log() {
    local in=$(cat)
    if [ "$in" != '' ]; then 
        echo -e "$in" | logprep >>"$logfile"    # out to logfile
    fi
    return 0    
}
2log2scr() {
    local in=$(cat)
    # 2scr
    if [ "'$in'" != '' ]; then echo -e "$in"; fi

    # 2log
    if [ "$in" != '' ]; then 
        echo -e "$in" > >(logprep >>"$logfile") # out to logfile
    fi
    return 0
}
runner () {
    echo -e "started running\n"
    "${@}" 1> >(2log) 2> >(2log2scr | tee >&2)      # <<< RUNNER
    #while [ -e /proc/15435 ]; do sleep 0.1; done   # <<< HERE
    echo -e "finished running\n"
}
success() {
    eval 'version=$(echo "SUCCESS: **** ${BASH_VERSION} ****")'
    echo -e "$version"; return 0
}
failure() {
    eval 'version=$(echo "FAILURE: **** ${BASH_VERSION} ****")'
    echo -e "$version" 1>&2; return 64
}

runner success  # to test a successful command
runner failure  # to test a command that errs

echo "EVAL IS: $version"

答え1

バックグラウンドプロセスのpidは$!環境変数がバックグラウンドに配置されている場合(コマンドの最後に&を追加することによって)取得できます。

my-cmd &
echo $!

移動できるもう1つのオプションは、実行中のシェルで$ $(現在のシェルのpid)を使用することです。

exec sh -c 'echo $$ > t.pid && sleep 10' &
echo $!  # <-- pid of spawned shell
pid=$(cat t.pid)  # <-- pid of execed process in shell

これはt.pidという一時ファイルにpidを提供します。

答え2

EVALに違反せずに動作させる唯一の方法は次のとおりです。

runner () {
    echo -e "started running\n"
    "${@}" 1> >(2log) 2> >(2log2scr | tee >&2) 
    while [ -e /proc/$! ]; do sleep 0.1; done
    echo -e "$pid finished running\n"
}

ここでの違いは、$!事前の要件なしでただ訪問することです。すべての提案には、次のようにルーチンを呼び出すことでアクセスできる$!が記載されています。

my-cmd &
echo $!

これは必須ではないようです。$!複雑なルーチンの後に簡単にアクセスできます。"${@}" 1> >(2log) 2> >(2log2scr | tee >&2) どこでも「&」を使用しないでください

関連情報