特定のGNU画面ウィンドウで実行されているプロセスをどのように見つけることができますか?

特定のGNU画面ウィンドウで実行されているプロセスをどのように見つけることができますか?

質問

合理的な時間内に画面の特定のウィンドウで実行されているプロセスを見つける必要があります。

想像する

セッション名とウィンドウのタイトルを使用して、セッションで実行されているプロセスを見つける必要があります。遅すぎる必要はありません。

また注目すべき価値があるでしょう。私はbyobuをスクリーンラッパーとして使用しています。

私が試したこと

  • オンラインで検索
  • 画面に表示されるマニュアルページを読んでください(深刻な方のためではありません)。(もちろん、全部読んでいませんが、関連部分をほとんど読んで、役に立つ内容を徹底的に検索しました。)
    • 私が学んだことは:
      • screenを呼び出してscreenから必要な情報を取得する唯一の方法は、コマンドラインフラグを使用することです。
        • -Qを使用すると、特定のコマンドを照会できますが、これらのいずれも必要なものはすべて提供しません。私が使っている返品窓口番号です。
          • number - ウィンドウ番号を取得するために使用するもの
          • windowlist - カスタム形式の情報文字列を取得できますが、セッションPIDは要求できる項目の1つではありません。
          • echo、info、lastmsg、select、time、titleなどは他に役に立たないようです。
        • -ls はアクティブなセッションをリストします。セッション名の前にPIDを追加するので、これは現在のセッションPIDを取得する方法です。
      • 特定のウィンドウで実行されているシェルのPIDがある場合は、WINDOW環境変数を確認できます。この変数はウィンドウ番号に設定されます。これは、プロセスをウィンドウに一致させるために使用するものです。
      • セッションPIDとウィンドウのタイトルとウィンドウ番号のマッピングを返すコマンドはありません。また、呼び出し画面の外でマップされているウィンドウ番号のセッションIDとウィンドウのタイトルを決定的に見つける方法を見つけることができません。
  • 試行錯誤/マイニング環境変数
  • スクリプト

私のスクリプト

問題を正常に解決したようなスクリプトを作成しましたが、実行には0.75秒かかります。これは、私が達成する必要がある作業に比べて長すぎます。さらに重要なのは、サーバーがHTML要求への応答を送信するために完了するのを待っている間に長すぎるということです。

スクリプトは次のとおりです。

#!/bin/bash
# Accept the name of a GNU/screen session & window and return the process running in its shell
SessionName=$1
TabName=$2

# ====== Averages 0.370 seconds ======
# This finds the window number given the session name and window title
# The screen command queries screen for the window number of the specified 
# window title in the specified session.
# Example output of screen command: 1 (Main)
# Example output after cut command: 1
TargetTabNum=$(screen -S $SessionName -p $TabName -Q number | cut -d ' ' -f1)

# ====== Averages 0.370 seconds ======
# This finds the session PID given the session name.
# The screen command prints the list of session IDs
# Example output of screen command:
#     There is a screen on:
#             29676.byobu     (12/09/2019 10:23:19 AM)        (Attached)
#     1 Socket in /run/screen/S-{username here}.
# Example output after sed command: 29676
SessionPID=$(screen -ls | sed -n "s/\s*\([0-9]*\)\.$SessionName\t.*/\1/p")

# ====== The rest averages 0.025 seconds ======
# This gets all the processes that have the session as a parent,
# loops through them checking the WINDOW environment variable for
# each until it finds the one that matches the window title, and
# then finds the process with that process as a parent and prints its
# command and arguments (or null if there are no matching processes)
ProcessArray=( $(ps -o pid --ppid $SessionPID --no-headers) )
for i in "${ProcessArray[@]}"
do
    ProcTabNum=$(tr '\0' '\n' < /proc/$i/environ | grep ^WINDOW= | cut -d '=' -f2)
    if [ ! -z "$ProcTabNum" ] && [ "$TargetTabNum" -eq "$ProcTabNum" ]; then
        ProcInTab=$(ps -o cmd --ppid $i --no-headers)
        if [[ $? -eq 1 ]]; then
            ProcInTab=NULL
        fi
        echo $ProcInTab
        exit 0
    fi
done
echo "Couldn't find the specified Tab: $TabName" >&2
exit 1

ご覧のとおり、問題のコマンドは2つの画面コマンドです。セッション名で始まった画面プロセスを検索してそのうちの1つを削除することができますが、これは少し奇妙な感じで決定的なものかどうかはわかりません。

SessionPID=$(ps -eo pid,command --no-headers | grep -i "[0-9]* screen.*\-s $SessionName " | grep -v grep | cut -d ' ' -f1)

ターゲット

特定の画面ウィンドウで現在どのプロセスが実行されているかを確認するための迅速で信頼性の高い方法が必要です。私が何か不足しているようで、もし見つけてもらえたら本当に感謝します!

(私はStackExchangeをよく知っているので、質問に対するフィードバックを歓迎します!)

答え1

screenを呼び出してscreenから必要な情報を取得する唯一の方法は、コマンドラインフラグを使用することです。

いいえ。あなたは間違ったscreen方向を見ています。screen仮想擬似端末(したがって接続されている/dev/pts/*)であり、何百もの方法で対話できます。実行すると、対話できるscreen目に見えるソケットが生成されnetstat、このソケット通信の管理方法によって特定の交換にかかる時間が決まります。できるだけ早くこれらの通信を実行するための最良の方法は、要求を送信して応答を待つのではなく、すでに報告されているものを活用することです。

wあなたの場合は、次のコマンドを実行して問題を解決できます。

shark@tank:~$ sudo w
 20:39:11 up 2 days,  1:24,  2 users,  load average: 0.64, 0.41, 0.44
USER     TTY      FROM             LOGIN@   IDLE       WHAT
shark    tty7     :0               Sun19    2days      /usr/lib/xorg/Xorg :0 *
fish     pts/1    :pts/6:S.0       20:31    7:42       htop

見てわかるように、2番目のユーザーは自分が接続されているソケットfishで作業しており、実行によってソケットがユーザーに属し、ソケットが/ dev / pts / 6でリッスンして実行されていることがわかります。screentty/dev/pts/1sharkls -la /dev/pts/htop

これが実際に実際のソケット接続かどうかを再確認する方法は何ですか?以下を実行して:

sudo file /run/screen/*/*
/run/screen/S-fish/98633.pts-6.tank: socket

私たちが見る数字は

ps aux | grep 98633 -B 1 -A 1 
fish      98632  0.0  0.0   6732  2964 pts/6   S+   20:31   0:00 screen
fish      98633  0.0  0.0   7032  2576 ?        Ss   20:31   0:00 SCREEN
fish      98634  0.0  0.0   8660  5400 pts/1   Ss+  20:31   0:00 /bin/bash

コマンドは、以下を実行して表示できる最小ヒット率で/procこの情報をポーリングします。/var/run/utmp

$ sudo usr/bin/time -f "\t%E real\n\t%U user\n\t%S sys\n" w > /dev/null
    0:00.01 real
    0.00 user
    0.01 sys

関連情報