특정 GNU 화면 창에서 실행 중인 프로세스를 어떻게 찾을 수 있나요?

특정 GNU 화면 창에서 실행 중인 프로세스를 어떻게 찾을 수 있나요?

질문

합리적인 시간 내에 화면의 특정 창에서 실행 중인 프로세스를 찾아야 합니다.

상상하다

세션 이름과 창 제목을 사용하여 세션에서 실행 중인 프로세스를 찾아야 합니다. 너무 느릴 필요는 없습니다.

또한 주목할 만한 가치가 있을 것입니다. 저는 byobu를 화면 래퍼로 사용하고 있습니다.

내가 시도한 것

  • 온라인으로 검색
  • 화면에 나오는 매뉴얼 페이지를 읽어보세요(심약한 분들을 위한 것이 아닙니다).(물론, 전부 읽지는 않았지만 관련 부분을 대부분 읽었으며 도움이 될만한 내용을 철저하게 검색했습니다.)
    • 내가 배운 것은:
      • screen을 호출하여 screen에서 필요한 정보를 얻는 유일한 방법은 명령줄 플래그를 사용하는 것입니다.
        • -Q를 사용하면 특정 명령을 쿼리할 수 있지만 이들 중 어느 것도 필요한 모든 것을 제공하지 않습니다. 제가 사용하고 있는 반품 창구 번호입니다.
          • number - 창 번호를 얻는 데 사용하는 것
          • windowlist - 사용자 정의 형식의 정보 문자열을 얻을 수 있지만 세션 PID는 요청할 수 있는 항목 중 하나가 아닙니다.
          • 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

보시다시피 문제의 명령은 두 개의 화면 명령입니다. 세션 이름으로 시작된 화면 프로세스를 검색하여 그 중 하나를 제거할 수 있지만 이는 약간 이상한 느낌이 들고 결정적인지 확실하지 않습니다.

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

보시다시피 두 번째 사용자는 자신이 연결된 소켓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

관련 정보