저는 리눅스를 배우고 있어요. 프로세스를 터미널에 붙일 수 있다는 아이디어가 떠올랐습니다. 터미널(TTY)에 프로세스를 연결한다는 것은 무엇을 의미합니까? 왜 이 일을 해야 합니까?
답변1
노트: Unix의 작업 제어를 더 잘 이해하기 위해 해당 주제에 대한 Wikipedia 페이지로 안내하겠습니다.작업 제어(Unix).
추가 터미널?
"터미널에 연결"이라는 문구는 일반적으로 쉘 컨텍스트에서 작업에 대해 말할 때 듣는 것입니다. 그러나 그것은 다른 의미도 가지고 있습니다. "터미널에 프로세스 연결"이라는 문구는 또는 gdb
특정 프로세스 ID(PID)에 연결하고 정보를 나열하거나 모니터링하는 것과 같은 strace
도구를 사용하는 것을 의미할 수도 있습니다.lsof
이 두 가지에 대해 모두 논의할 예정이지만 먼저 작업 대기열에 대해 논의하겠습니다. 왜냐하면 그것이 여러분이 찾고 있는 대기열이라고 생각하기 때문입니다.
배경 - 작업 대기열
Unix 계열 운영 체제에서는 일반적으로 작업이라는 개념을 볼 수 있습니다. 일반적으로 내가 사용한 대부분의 Unix 계열 운영 체제에서 비슷한 방식으로 작동합니다. 즉, 백그라운드에서 실행될 수 있고 대기열(작업 대기열)에 번호가 할당될 수 있으며 해당 작업 대기열에 있는 번호의 컨텍스트에 따라 작동될 수 있습니다.
작업 대기열에 무언가를 넣기 위해 종종 이 동작을 백그라운드 처리라고 부릅니다. 이미 백그라운드에서 실행 중인 작업을 재개하는 경우 이를 포그라운드 처리라고 합니다. 이를 수행하는 일반적인 명령 bg
은 입니다 fg
. &
실행하는 명령 끝에 "&" 기호를 사용하여 작업을 백그라운드로 즉시 전환 할 수도 있습니다 .
예
일하다
$ sleep 2 &
[1] 19189
여기서는 sleep 명령을 2초 동안 실행하고 백그라운드에 넣어두었습니다. 출력에서는 작업 대기열 번호( [1]
) 및 백그라운드 작업의 프로세스 ID 19189와 같은 유용한 정보를 즉시 제공합니다.
이 작업이 최종적으로 종료되면 실행 중인 터미널에 다음과 같은 메시지가 인쇄됩니다.
$
[1]+ Done sleep 2
전경과 배경
백그라운드 작업에 대한 작업을 수행하려면 다음을 수행하십시오.
$ sleep 20 &
[1] 19207
$ fg
sleep 20
^C
여기서는 작업을 백그라운드( &
)로 보낸 다음 다시 포그라운드( )로 가져온 fg
다음 Ctrl+ C( ^C
) 명령을 사용하여 작업을 종료합니다.
백그라운드 작업이 여러 개인 경우:
$ sleep 20 &
[1] 19224
$ sleep 20 &
[2] 19225
$ sleep 20 &
[3] 19226
$ jobs
[1] Running sleep 20 &
[2]- Running sleep 20 &
[3]+ Running sleep 20 &
우리는 명령을 사용하여 그것들을 볼 수 있습니다 jobs
. #3 과 #2 옆에 있는 작은 합계를 확인하세요 +
. 작업 대기열 번호를 지정하지 않고 명령 -
을 실행하면 fg
마지막 작업이 작업 대기열( )에 추가됩니다 +
. 예를 들어:
$ fg
sleep 20
^C
$ jobs
[1]- Running sleep 20 &
[2]+ Running sleep 20 &
죽이다
작업 대기열 번호를 사용하여 작업을 처리할 수 있습니다. 한 가지 방법은 그들을 죽이는 것입니다. 작업 대기열 번호를 참조하려면 %
다른 명령과 함께 참조하려는 경우 해당 번호 앞에 접두사를 붙일 수 있습니다 kill
. 물론, kill
한 번에 둘 이상을 사용할 수도 있고 하나만 사용할 수도 있습니다.
$ kill %3 %4 %5
$ jobs
[3] Terminated sleep 20
[4] Terminated sleep 20
[5]- Terminated sleep 20
[6]+ Running sleep 20 &
PID에 연결된 배경
프로세스를 터미널에 연결한다는 것은 다음을 의미할 수도 있습니다. 이것은 내 쉘의 PID입니다.
$ echo $$
23543
다른 셸에서는 strace
프로세스를 실행하고 연결하여 어떤 시스템 호출이 수행되고 있는지 확인합니다.
$ strace -p 23543
strace: Process 23543 attached
read(0,
노트:read
여기에서 for 명령을 기다리고 있는 것을 볼 수 있습니다 . 이것이 터미널/셸의 용도입니다.
여기서 우리는 명령을 입력하기 시작했고 ls
쉘이 이것을 시스템 호출의 형태로 쉘에 다시 에코하는 것을 볼 수 있습니다 write()
.
read(0, "l", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "l", 1) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "s", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "s", 1) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0,
이는 터미널에 프로세스를 연결하는 또 다른 형태입니다.
다른 형태
프로세스를 터미널에 연결하는 것에 대한 보다 모호한 참조 중 하나를 여기서도 가정할 수 있습니다. 이 U&L Q&A의 질문은 다음과 같습니다.분리된 프로세스에 터미널을 연결하는 방법은 무엇입니까?이 콘텐츠의 모든 형태가 포함됩니다.
이 형식의 인용의 기본 전제는 백그라운드 작업을 완료하고 현재 셸에서 해당 작업을 "연결 해제"했다는 것입니다. 또는 명령을 사용하여 nohup
이를 수행 할 수 있습니다 disown
.
프로세스가 거부되면 더 이상 jobs
, fg
또는 bg
명령을 사용하여 작업을 수행할 수 없습니다. 더 이상 현재 쉘의 PID와 연결되지 않습니다.
reptyr
이전에 거부된 프로세스를 다시 획득하는 전통적인 방법 은 PID를 기존 셸에 다시 연결하는 것과 같은 도구를 사용하는 것입니다 . 예를 들어, 우리가 2개의 작업을 시작했고 그 작업이 다음과 같다고 가정해 보겠습니다 nohup
.
$ nohup sleep 200 &
[1] 19720
$ nohup sleep 200 &
[2] 19721
여전히 터미널의 작업 대기열에 연결되어 있습니다 disown
. 다음을 수행해 보겠습니다.
$ jobs
[1]- Running nohup sleep 200 &
[2]+ Running nohup sleep 200 &
$ disown -a
이제 그들은 사라졌습니다:
$ jobs
$
이들은 여전히 원래 셸 PID(23543)의 하위 항목으로 나열됩니다.
$ ps -eaf|grep -E "19720|19721"
vagrant 19720 23543 0 18:29 pts/1 00:00:00 sleep 200
vagrant 19721 23543 0 18:29 pts/1 00:00:00 sleep 200
이제 로그아웃했다가 다시 로그인하면 이러한 프로세스가 이제 기본 PID 1의 상위로 나열되는 것을 볼 수 있습니다.
$ ps -eaf|grep -E "19720|19721"
vagrant 19720 1 0 18:29 ? 00:00:00 sleep 200
vagrant 19721 1 0 18:29 ? 00:00:00 sleep 200
nohup
이러한 프로세스는 우리가 편집하고 편집하기 때문에 이를 수행할 수 있습니다 disown
. 그 중 하나를 다시 연결해 보겠습니다.
$ reptyr -s 19720
[-] Timed out waiting for child stop.
^C
노트:위에서는 PID 19720을 쉘에 다시 연결한 다음 Ctrl+ 를 통해 종료합니다 C. 이제 사라진 것을 볼 수 있습니다.
$ ps -eaf|grep -E "19720|19721"
vagrant 19721 1 0 18:29 ? 00:00:00 sleep 200