동일한 프로그램의 여러 인스턴스, 출력 가져오기

동일한 프로그램의 여러 인스턴스, 출력 가져오기

foo아무 버튼이나 누르면 상태 업데이트를 출력하는 Ubuntu 16.04라는 쉘 프로그램이 있습니다 . /usr/local/bin/foo어디서든지 프로그램을 호출할 수 있도록 위치해 있습니다 . 프로그램 작동 방식은 다음과 같습니다.

$ foo
Welcome

키를 누르면 다음과 같이 표시됩니다.

Time now is 01:23:45

를 누르면 Ctrl-C대부분의 다른 쉘 프로그램처럼 종료됩니다.

foo이 프로그램을 여러 인스턴스에서 실행하고 싶습니다 . GNU Screen 명령이 작업 간에 전환할 수 있다는 것을 알고 있지만 이것이 올바른 방법입니까?

또는 다음과 같이 프로그램을 백그라운드에서 실행할 수 있다는 것을 알고 있습니다.

$ foo &
[1]  123456

작업 ID 1은 백그라운드에서 생성되며 해당 작업 ID로 호출할 수 있습니다.

$ fg %1

그러나 프로그램의 최신 출력을 얻은 후에는 이를 다시 배경으로 두어야 합니다(아무 버튼이나 눌러야 합니다. 프로그래밍 방식으로 이를 수행할 수 있는 방법이 있습니까?). 이 목표를 어떻게 달성할 수 있나요?

답변1

제가 이해하는 한, 귀하의 요구 사항은 다음과 같습니다.

  1. 프로그램의 여러 인스턴스를 동시에 실행합니다.
  2. 언제든지 모든 인스턴스에 대한 터미널 제어권을 확보하세요.
  3. 인스턴스가 이를 출력한 직후 백그라운드로 다시 전송됩니다.

이 접근 방식을 고수한다면 &그렇습니다. (3)에 대한 지름길이 있습니다. 프로그램이 터미널을 제어할 때 신호를 사용하여 터미널을 백그라운드로 보낼 수 있습니다 SIGTSTP. 편리하게도 이것이 일반적으로 Ctrl+ Z가 하는 일입니다.

따라서 다음과 같은 것을 가질 수 있습니다.

$ foo &
Welcome
[1] 10

$ foo &
Welcome
[2] 11

$ fg %1
<ENTER>
Time now is 01:23:45
<Ctrl+Z>
[1]+ Stopped

내가 아는 한, 그러한 지름길은 없습니다 fg(어떤 인스턴스를 다시 가져올 것인지 어떻게 표시합니까?).

신호 는 SIGTSTP실제로 프로세스를 시작한 쉘에서 나올 필요는 없습니다. kill -TSTP두 번째 셸에서 PID를 통해 처리하는 경우 fg첫 번째 셸에서도 복원할 수 있습니다.

프로그램의 최신 출력을 얻은 후 이를 다시 배경으로 되돌려 놓아야 합니다. (아무 버튼이나 눌러야 합니다. 프로그래밍 방식으로 이를 수행할 수 있는 방법이 있습니까?)

통과되면프로그래밍 방식으로foo즉, 소스 코드에 액세스할 수 있고 방금 본 것을 사용할 수 있다는 의미 입니다. 프로그램은 raise시스템 호출을 사용하여 자신에게 신호를 보낼 수 있습니다. 매우 간단한 버전을 사용하면 foo다음과 같은 결과를 얻을 수 있습니다.

#include <stdio.h>
#include <signal.h>

int main(void)
{
    printf("Welcome");
    while(getchar()) { /* Use termios to switch to unbuffered mode */
        fprintf(stdout, "The time is... something");
        fflush(stdout);
        fflush(stdin);
        raise(SIGTSTP);
    }

    return 0;
}

이 모든 것이 매우 훌륭하지만 이것이 screen아마도 모든 작업을 수행하는 더 좋은 방법이라는 데 동의합니다. 주로 작업이나 프로세스 ID를 기억할 필요가 없도록 스크린 세션의 이름을 지정할 수 있기 때문입니다. 이 &방법과 마찬가지로 소스코드를 변경할 필요가 없다는 장점도 있습니다.

$ screen -S foo1
$ ./foo
Welcome
<Ctrl-a d>
[detached from 10.foo1]

$ screen -s foo1
<ENTER>
Time now is 01:23:45
<Ctrl-a d>
[detached from 10.foo1]

여기서 또 다른 장점은 분리하기 전에 프로그램을 중지할 필요가 없다는 것입니다. 보고 있지 않을 때 백그라운드에서 작업을 수행하려는 경우 매우 편리합니다. 이전 접근 방식에서는 bg중지될 때마다 실행해야 했습니다 foo.

를 사용하여 실행 중인 화면 목록을 얻을 수도 있습니다 screen -ls. 내 컴퓨터에서는 ~/.bashrc추가적인 게으름을 설명하기 위해 몇 가지 별칭을 설정했습니다 .

alias S='screen -S'
alias s='screen -r'
alias sls='screen -ls'

S foo1이 방법을 사용하면 , ...와 같은 작업을 간단히 수행할 수 있습니다. s foo1어떤 사람들은 명령에서 공백이나 다른 항목을 잘못 배치할 때 단일 문자 별칭이 약간 짜증날 수 있다고 주장할 수 있지만 screen이것이 그러한 프로그램 중 하나라고 생각합니다.너무 편리하다당신은 예외를 만드는 능력이 있습니다.

이제 이러한 접근 방식을 취한다고 가정하면 screen키를 세션으로 보내고 셸에서 마지막 출력 줄을 가져오는 방법은 다음과 같습니다. 이를 조정할 수 있는 몇 가지 방법이 있습니다(몇 가지 지름길을 사용하도록 허용했습니다). 그러나 무엇이든 가능합니다. 다음 함수를 정의할 수 있습니다 ~/.bashrc.

screen_key_tail() {
    screen -S $1 -X stuff "^M"
    tmp="$(mktemp)"
    screen -S $1 -X hardcopy "$tmp"
    grep -v ^$ "$tmp" | tail -n1
    rm "$tmp"
}

다음을 사용하여 호출합니다.

$ screen_key_tail foo1

대상으로 삼으려는 세션의 이름은 어디에 있습니까 foo1?screen

관련 정보