스크린 세션에서 실행중인 활성 프로세스의 STDIN에 텍스트를 보낼 수 있습니까?


70

Linux 서버의 스크린 세션 내에 오래 실행되는 서버 프로세스가 있습니다. 그것은 약간 불안정합니다 (그리고 슬프게도 내 소프트웨어는 아니므로 해결할 수 없습니다!). 안정성을 돕기 위해 프로세스를 야간에 다시 시작하도록 스크립트하고 싶습니다. 정상적인 종료를 수행하는 유일한 방법은 화면 프로세스로 이동하여 실행중인 창으로 전환 한 다음 제어 콘솔에 "stop"문자열을 입력하는 것입니다.

cronjob이 매일 정해진 시간에 중지 명령을 보내도록 할 수있는 스마트 리디렉션 왜곡이 있습니까?

답변:


85

이 답변은 문제를 해결하지 못하지만 30 명 이상이 유용하다고 생각했기 때문에 여기에 남아 있습니다 . 그렇지 않으면 오랫동안 삭제했을 것입니다.

에 쓰십시오 /proc/*pid of the program*/fd/0. fd하위 디렉토리는 모든 열린 파일의 기술자를 포함하고 파일 기술자는 0표준 입력 (1 표준 출력과 2는 표준 에러입니다)입니다.

이를 사용하여 프로그램이 실행중인 tty에서 메시지를 출력 할 수 있지만 프로그램 자체에 쓸 수는 없습니다.

터미널 1:

[ciupicri@hermes ~]$ cat
shows on the tty but bypasses cat

터미널 2:

[ciupicri@hermes ~]$ pidof cat
7417
[ciupicri@hermes ~]$ echo "shows on the tty but bypasses cat" > /proc/7417/fd/0


2
+2 당신이 얼마나 많이 알고 있다고 생각하든 항상 배울 것이 더 많습니다 :) 매끈합니다.
troyengel

3
proc fd는 stdin의 소스로 사용되는 것으로 만 리디렉션됩니다. 예를 들어, 터미널 1에 무언가를 입력하면 다시 인쇄하여 (고양이 stdin에게 전송하고 고양이가 인쇄) 두 번 보게됩니다. 반면에 fd / 0으로 무언가를 보내면 콘솔로 보내지 만 고양이에게는 보내지 않으므로 한 번만 표시됩니다. cat이 예제를 사용하여 단순히 입력을 다시 인쇄하므로 입력 또는 출력이 인쇄되는지 여부를 실제로 알 수 없으므로 이러한 오해가 있습니다. / fd / 0은 콘솔 / pts를 가리 킵니다. 참조하십시오 ls -l /proc/7417/fd/0.
사키

4
실제 예 : gphoto2 --get-all-files를 시작했으며 100 번 확인을 요청합니다. "y"> / proc / PID / fd / 0을 에코하면 gphoto2가 진행되지 않지만 "y"가 터미널에 인쇄됩니다.
Thorsten Staerk

2
@ThorstenStaerk, 나는 그 노트를 추가 한 이유입니다. 당신은 gphoto2 실행 (예 :있는 터미널에 해당하는 장치 파일 만 작성하는 /dev/pts/19)의 y문자가 응용 프로그램 자체에 도달하지 않습니다. write (1) 명령 을 사용할 때 발생하는 것과 유사합니다 . 어쨌든, 다른 대답이나 xdotool 과 같은 그래픽 자동화 도구를 사용해보십시오 .
Cristian Ciupitu

36

스크린 기반 솔루션

다음과 같이 서버를 시작하십시오.

# screen -d -m -S ServerFault tr a-z A-Z # replace with your server

화면 이 분리 모드로 시작되므로 진행 상황을 보려면 다음을 실행하십시오.

# screen -r ServerFault

다음과 같이 서버를 제어하십시오.

# screen -S ServerFault -p 0 -X stuff "stop^M"
# screen -S ServerFault -p 0 -X stuff "start^M"
# screen -S ServerFault -p 0 -X stuff "^D" # send EOF

(이 답변은 텍스트 입력을 Unix & Linux 형제 사이트 에서 분리 된 화면 으로 보내는 것을 기반으로 합니다)

매개 변수 설명 :

-d -m
   Start screen in "detached" mode. This creates a new session but doesn't
   attach to it.  This is useful for system startup scripts.
-S sessionname
   When creating a new session, this option can be used to specify a meaningful
   name for the session.
-r [pid.tty.host]
-r sessionowner/[pid.tty.host]
   resumes a detached screen session.
-p number_or_name|-|=|+
   Preselect a window. This is useful when you want to reattach to a specific
   window or you want to send a command via the "-X" option to a specific
   window.
-X
   Send the specified command to a running screen session e.g. stuff.

물건 [문자열]

   Stuff the string string in the input  buffer of the current window.
   This is like the "paste" command but with much less overhead.  Without
   a parameter, screen will prompt for a string to stuff.

TMUX 기반 솔루션

다음과 같이 서버를 시작하십시오.

# tmux new-session -d -s ServerFault 'tr a-z A-Z' # replace with your server

tmux 는 분리 모드에서 시작하므로 진행중인 작업을 보려면 다음을 실행하십시오.

# tmux attach-session -t ServerFault

다음과 같이 서버를 제어하십시오.

# tmux send-keys -t ServerFault -l stop
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault -l start
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault C-d # send EOF

매개 변수 설명 :

 new-session [-AdDP] [-c start-directory] [-F format] [-n window-name] [-s
         session-name] [-t target-session] [-x width] [-y height]
         [shell-command]
         Create a new session with name session-name.

         The new session is attached to the current terminal unless -d is
         given.  window-name and shell-command are the name of and shell
         command to execute in the initial window.  If -d is used, -x and
         -y specify the size of the initial window (80 by 24 if not
         given).

 send-keys [-lR] [-t target-pane] key ...
               (alias: send)
         Send a key or keys to a window.  Each argument key is the name of
         the key (such as `C-a' or `npage' ) to send; if the string is not
         recognised as a key, it is sent as a series of characters.  The
         -l flag disables key name lookup and sends the keys literally.

4

이것을 시작하십시오 :

# screen
# cd /path/to/wd
# mkfifo cmd
# my_cmd <cmd
C-A d

그리고 이것은 죽일 것입니다 :

# cd /path/to/wd
# echo "stop" > cmd
# rm cmd

3
이것은 좋지만 프로그램이 실행되는 동안 다른 명령을 보낼 수 없다는 단점이 있습니다. stdin에서 EOF에 도달했을 때 프로그램이 중지되면 첫 번째 echo "xxx" > cmd프로그램에서 파이프가 닫히기 때문에 프로그램이 중지됩니다. 일부 프로그램은 rewind(3)EOF를 만났을 때 stdin 을 다시 열 수있을 정도로 똑똑 합니다.
Cristian Ciupitu

2

screen유틸리티 또는 다른 고급 유틸리티 를 실행하지 않고 입력 텍스트를 실행중인 프로세스로 보낼 수 있습니다 . 그리고이 입력 텍스트를 프로세스의 표준 입력 "file"로 보내서 수행 할 수 있습니다 /proc/PID#/fd/0.

그러나 입력 텍스트는 프로세스에서 읽을 수 있도록 특별한 방식으로 전송되어야합니다. 일반 파일 write방법을 통해 입력 텍스트를 보내더라도 프로세스가 텍스트를 수신하지 않습니다. 이는 "파일"에만 추가되지만 바이트를 읽는 프로세스는 트리거하지 않기 때문입니다.

바이트를 읽는 프로세스를 트리거하려면 모든 단일 바이트가 전송되도록 IOCTL유형 의 조작 을 수행해야합니다 TIOCSTI. 이것은 바이트를 프로세스의 표준 입력 큐에 넣습니다.

이것은 C, Perl 및 Python의 몇 가지 예와 함께 여기에서 설명됩니다.

https://unix.stackexchange.com/questions/48103/construct-a-command-by-putting-a-string-into-a-tty/48221

-

따라서 거의 9 년 전에 질문 한 원래 질문에 답하기 위해 cron 작업은 사람들이 다른 질문에 대해 작성한 예제와 유사한 작은 유틸리티 스크립트 / 프로그램을 실행해야합니다.이 문자열은 "stop \ n"문자열을 해당 서버 프로세스로 보냅니다. 질문에서 IOCTLtype 의 연산을 통해 5 바이트 각각을 전송 합니다 TIOCSTI.

물론 이것은 단지 지원하는 시스템에서 작동합니다 TIOCSTI IOCTL(리눅스 등) 작업 유형을, 만에서 root이러한 "파일"아래로, 사용자 계정 /proc/에 의해 "소유"하고 있습니다 root.


1

누군가에게 도움이되는 경우 :
비슷한 문제가 있었고 사용중인 프로세스가 screen또는 tmux에 없었기 때문에 다른 접근법을 사용해야했습니다.

나는 부착 gdb받는 xterm내 프로세스에서 실행중인 것을, 그리고 사용 call write(5, "stop\n", 5)에서 gdb마스터 PTY 파일 기술자에 기록 할 수 있습니다. 링크를
찾아 두 옵션 사이의 시행 착오 를 통해 데이터를 보낼 파일 설명자를 찾았습니다 (문자열을 일치하는 두 파일 설명자에 모두 보내는 것은 아무런 해를 끼치 지 않는 것 같습니다)./proc/<pid>/fd/dev/ptmx

편집하다

xterm내가 첨부 한 프로세스 spawn-new-terminal() xterm가 키 바인딩 의 작업 으로 생성되었으며 두 번째 ptmx파일 디스크립터는 닫히지 않은 ptmx상위 xterm프로세스의 프로세스였습니다.
따라서 시행 착오 호출은 다른 터미널로 출력을 보냈습니다.
대부분의 xterm프로세스에는 두 개의 ptmx파일 디스크립터 가 없습니다 .

편집 종료

이것은 그 문자열을 터미널에 효과적으로 입력했기 때문에 문자열을 그 아래에서 실행되는 프로세스로 보냈습니다.

nb 실행중인 프로세스에 다음과 같은 연결을 허용해야 할 수도 있습니다.
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"


0

크리스티안 시우 투투 (2010 년)의 답변 중 가장 잘 받아 들인 답을 언급 할 수 없기 때문에 별도의 답을 입력해야합니다.

이 질문은이 스레드에서 이미 해결되었습니다 : https : //.com/questions/5374255/how-to-write-data-to-existing-processs-stdin-from-external-process

한마디로 :

현재 입력이 쓰여질 때 막히거나 닫히지 않는 stdin 파이프로 프로세스를 시작해야합니다. 이것은 문제가없는 프로세스로 파이프되는 간단한 무한 루프로 구현 될 수 있습니다.

$ (while [ 1 ]; do sleep 1; done) | yourProgramToStart

나는 이것이 내 경우에는 작동하지 않은 파이프를 여는 krissi의 방법과 다르다는 것을 확인할 수 있습니다. 표시된 솔루션이 대신 작동했습니다.

그런 다음 프로세스의 ... / fd / 0 파일에 기록하여 명령을 보낼 수 있습니다. 유일한 단점은 서버가 종료 된 후 무한 루프를 실행하는 bash 프로세스를 종료해야한다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.