シェルジョブ番号をPIDにマッピングする

シェルジョブ番号をPIDにマッピングする

私はシェルジョブコントロールを使用して、長時間実行されているジョブをバックグラウンドにプッシュして、データの変動中にそのジョブを実行し続けることができます。

たとえば、実行中のジョブを表示できますjobs

jobs
[2]-  Running                 su - root -c "..." &  (wd: /backup/rsnapshot)
[3]+  Running                 sleep 60 &

次のコマンドを使用してこれらのいずれかを制御できます。% 作業仕様fg %suまたはのような構文kill %3

以下を使用すると、jobs -lPIDも取得されます。

jobs -l
[2]- 31736 Running                 su - root -c "..." &  (wd: /backup/rsnapshot)
[3]+  2269 Running                 sleep 60 &

bashI haveを使うjobs -xPOSIXではない。これが翻訳できる唯一の方法ですか?% 作業仕様それとも合理的な(より良い)選択肢がありますか?他の殻はどうですか?

jobs -x echo %3
2269

私の目標のユースケースは% 作業仕様拡張予定透明に%2次のように処理されるように、コマンドラインに適切なPIDを入力してください。31736

pidtree %2    # pidtree 31736

これは処理できますが、それほどjobs -x pidtree %2エレガントでも便利でもありません。

少なくとも1つの答えをTargetingしたいbashが、タスク制御を含む他のシェルへの貢献は歓迎されています。特にPOSIXソリューションがある場合はさらにそうです。

答え1

現在のタスクリストからbashカスタム設定変数を動的に提供することで、これに近づくことができます。$PROMPT_COMMAND

概念の証拠:

$ PROMPT_COMMAND='unset ${!j*}; eval "$(jobs -l | awk '\''{gsub("[^[:digit:] ]", ""); printf "j%d=%d\n", $1, $2}'\'')"'

その後、数字がないと仮定してpidtree $j2に置き換えます。それ以外の場合は引用符で囲む必要があるため、キーをもう一度入力する必要があります。pidtree %2$IFS$j2

答え2

いくつかのコマンドに対してのみこれを行う場合は、プログラム可能な完了がオプションになります。これはPOSIXではない可能性が高いですが、少なくともいくつかのシェルで動作します(そして基本的なメカニズムが同じである必要はありません)。

したがって、入力すると、pidtree %2Tabシェルはそれを次に変換します。

pidtree 31736

豪華で便利なようです。

欠点:これらのコマンドの既存の完了構成を維持するには、手動介入が必要です(たとえば、関数を最初に実行し、不一致がある場合は元の関数を呼び出すようにします)。

_pidtree () {
    local job pid
    if [[ ${COMP_WORDS[COMP_CWORD]} =~ ^%[1-9][0-9]* ]]; then
        job="${COMP_WORDS[COMP_CWORD]:1}"
        pid="$(jobs -l | awk -v job="$job" '$1 ~ "^\\[" job "\\]" { print $2; }')"
        COMPREPLY=("$pid")
    fi
}

complete -F _pidtree pidtree

これはうまくいきますbash。なしで行うことができawk、確かにより互換性のある方法で行うことができます。

改行を含む操作には問題がある可能性がありますが、これは対話型シェルなので、悪用される危険はないようです。

答え3

バックグラウンドジョブを作成するときにPIDだけを覚えておくのは最も簡単ではありませんか?

bash:

declare -a bgjobpids
[...]
do_some_thing &
pid=$!
index=${#bgjobpids[@]}
bgjobpids[index]=$pid
[...]
do_some_thing_else &
pid=$!
index=${#bgjobpids[@]}
bgjobpids[index]=$pid

関連情報