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
제가 이해하는 한, 귀하의 요구 사항은 다음과 같습니다.
- 프로그램의 여러 인스턴스를 동시에 실행합니다.
- 언제든지 모든 인스턴스에 대한 터미널 제어권을 확보하세요.
- 인스턴스가 이를 출력한 직후 백그라운드로 다시 전송됩니다.
이 접근 방식을 고수한다면 &
그렇습니다. (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