Bash를 사용하여 STDIN 주입을 위한 대화형 프로세스 래핑

Bash를 사용하여 STDIN 주입을 위한 대화형 프로세스 래핑

SIGTERM을 완전히 무시하는 게임 서버 프로그램(SRCDS)을 실행하고 있습니다. 서버를 완전히 종료하는 유일한 방법은 대화형으로 "quit"를 입력하는 것입니다.

SIGTERM을 포착하고 프로그램의 STDIN으로 "종료"를 보내는 bash 스크립트로 이 프로그램을 래핑할 수 있는 방법이 있습니까? 그렇지 않으면 일반 작업에서 래퍼는 STDIN 및 STDOUT이 전혀 존재하지 않는 것처럼 전달해야 합니다.

내가 달성하려는 목표에 대한 다이어그램:

일반 외과:

--- STDIN --->  |             |  --- STDIN --->  |                |
                | Bash Script |                  | Server Program |
<-- STDOUT ---  |             |  <-- STDOUT ---  |                |

SIGTERM은 다음을 보냅니다:

                                     "quit"
--- STDIN --->  |             |  --- STDIN --->  |                |
-- SIGTERM -->  | Bash Script |                  | Server Program |
<-- STDOUT ---  |             |  <-- STDOUT ---  |                |

답변1

프로그램이 터미널에서 실행될 것으로 예상되는지 여부에 따라 다릅니다. 그렇다면 이 작업을 수행할 수 없을 것 같습니다 bash. 비슷한 것을 사용해야 합니다 expect. 예:

래퍼.예상:

puts "<<< pid=[pid] >>>"
spawn {*}$argv
trap {send "quit\n"} SIGTERM
interact

BC를 예로 들어보겠습니다.

expect wrapper.expect bc -q

<<< pid=4771 >>>
spawn bc -q

kill 4771다른 창에서 A를 사용하면 행이 expect로 전송 됩니다 . 이는 하위 프로세스의 pid 가 아니라 프로세스의 pid입니다.quitbc4771expectbc

또 다른 옵션은 ioctl을 사용하여 TIOCSTI현재 터미널에 라인을 삽입하는 것입니다. quit그러나 이 작업은 쉘에서 수행할 수 없으며 여전히 작은 C(또는 Perl, Python 등) 프로그램이 필요합니다. 호출합니다 ioctl()( TIOCSTI이미 OpenBSD에서는 시스템에서 삭제됩니다).

답변2

이 시도:

#!/bin/bash

coproc cat -n  # replace 'cat -n' with actual server program to be launched

# first some necessary file-descriptors fiddling
exec {srv_input}>&${COPROC[1]}-
exec {srv_output}<&${COPROC[0]}-

# background commands to relay normal stdin/stdout activity
cat <&0 >&${srv_input} &
cat <&${srv_output} >&1 &

# set signal handler up
term_received=false ; trap 'term_received=true' SIGTERM

# endless loop waiting for events
while true; do
    # wait for server to exit or sigterm received
    wait ${COPROC_PID}
    exit_status=$?
    # if sigterm received:
    if [ $exit_status -gt 128 ] && $term_received ; then
        # kill proxy command relaying stdin to server
        kill %2
        # send quit to server's stdin
        echo $'\n'quit >&${srv_input}
        # close server's stdin
        exec {srv_input}<&-
        # wait for actual server to exit
        wait ${COPROC_PID}
        exit $?
    # something else happened: kill proxy commands and exit with server's own exit status
    else
        kill %2
        kill %3
    fi
    exit $exit_status
done

이 스크립트가 귀하의 질문에 답변하면 더 완전한 설명을 추가하겠습니다.

관련 정보