질문
합리적인 시간 내에 화면의 특정 창에서 실행 중인 프로세스를 찾아야 합니다.
상상하다
세션 이름과 창 제목을 사용하여 세션에서 실행 중인 프로세스를 찾아야 합니다. 너무 느릴 필요는 없습니다.
또한 주목할 만한 가치가 있을 것입니다. 저는 byobu를 화면 래퍼로 사용하고 있습니다.
내가 시도한 것
- 온라인으로 검색
- 화면에 나오는 매뉴얼 페이지를 읽어보세요(심약한 분들을 위한 것이 아닙니다).(물론, 전부 읽지는 않았지만 관련 부분을 대부분 읽었으며 도움이 될만한 내용을 철저하게 검색했습니다.)
- 내가 배운 것은:
- screen을 호출하여 screen에서 필요한 정보를 얻는 유일한 방법은 명령줄 플래그를 사용하는 것입니다.
- -Q를 사용하면 특정 명령을 쿼리할 수 있지만 이들 중 어느 것도 필요한 모든 것을 제공하지 않습니다. 제가 사용하고 있는 반품 창구 번호입니다.
- number - 창 번호를 얻는 데 사용하는 것
- windowlist - 사용자 정의 형식의 정보 문자열을 얻을 수 있지만 세션 PID는 요청할 수 있는 항목 중 하나가 아닙니다.
- echo, info, lastmsg, select, time, title 등은 기타 쓸모가 없는 것 같습니다.
- -ls는 활성 세션을 나열합니다. 세션 이름 앞에 PID를 추가하므로 이것이 현재 세션 PID를 얻는 방법입니다.
- -Q를 사용하면 특정 명령을 쿼리할 수 있지만 이들 중 어느 것도 필요한 모든 것을 제공하지 않습니다. 제가 사용하고 있는 반품 창구 번호입니다.
- 특정 창에서 실행 중인 셸의 PID가 있으면 WINDOW 환경 변수를 확인할 수 있습니다. 이 변수는 창 번호로 설정됩니다. 이것이 프로세스를 창에 일치시키는 데 사용하는 것입니다.
- 세션 PID와 창 제목과 창 번호 매핑을 반환하는 명령이 없습니다. 또한 호출 화면 외부에서 매핑되는 창 번호에 대한 세션 ID와 창 제목을 결정적으로 찾을 수 있는 방법을 찾을 수 없습니다.
- screen을 호출하여 screen에서 필요한 정보를 얻는 유일한 방법은 명령줄 플래그를 사용하는 것입니다.
- 내가 배운 것은:
- 시행착오/마이닝 환경 변수
- 스크립트
내 스크립트
문제를 성공적으로 해결한 것 같은 스크립트를 작성했는데, 실행하는데 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에서 수신 대기하고 실행 중임을 알 수 있습니다.screen
tty
/dev/pts/1
shark
ls -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