웹사이트 검색

Bash의 작업 제어를 사용하여 포그라운드 및 백그라운드 프로세스를 관리하는 방법


소개

이전 자습서에서 ps, killnice 명령을 사용하여 시스템의 프로세스를 제어하는 방법에 대해 설명했습니다. 이 가이드는 bash, Linux 시스템 및 터미널이 함께 모여 프로세스 및 작업 제어를 제공하는 방법을 강조합니다.

이 기사는 포그라운드 및 백그라운드 프로세스 관리에 초점을 맞추고 쉘의 작업 제어 기능을 활용하여 명령을 실행하는 방법에서 더 많은 유연성을 얻는 방법을 보여줍니다.

전제 조건

이 가이드를 따라하려면 bash 셸 인터페이스를 실행하는 컴퓨터에 액세스해야 합니다. bash는 많은 Linux 기반 운영 체제의 기본 셸이며 macOS를 포함한 많은 Unix 계열 운영 체제에서 사용할 수 있습니다. 이 자습서는 Ubuntu 20.04를 실행하는 Linux 가상 사설 서버를 사용하여 검증되었습니다.

이 가이드를 따르기 위해 원격 서버를 사용할 계획이라면 먼저 초기 서버 설정 가이드를 완료하는 것이 좋습니다. 이렇게 하면 sudo 권한이 있는 루트가 아닌 사용자와 UFW로 구성된 방화벽을 포함하여 보안 서버 환경을 설정하여 Linux 기술을 구축하는 데 사용할 수 있습니다.

포그라운드 프로세스 관리

Linux 시스템에서 시작하는 대부분의 프로세스는 포그라운드에서 실행됩니다. 명령이 실행을 시작하고 프로세스 기간 동안 셸 사용을 차단합니다. 프로세스는 사용자 상호 작용을 허용하거나 프로시저를 통해 실행한 다음 종료할 수 있습니다. 모든 출력은 기본적으로 터미널 창에 표시됩니다. 다음 하위 섹션에서 포그라운드 프로세스를 관리하는 기본 방법에 대해 설명합니다.

프로세스 시작

기본적으로 프로세스는 포그라운드에서 시작됩니다. 즉, 프로그램이 종료되거나 상태가 변경될 때까지 셸과 상호 작용할 수 없습니다.

일부 전경 명령은 매우 빠르게 종료되고 거의 즉시 셸 프롬프트로 돌아갑니다. 예를 들어 다음 명령은 터미널에 Hello World를 인쇄한 다음 명령 프롬프트로 돌아갑니다.

  1. echo "Hello World"
Output
Hello World

다른 포그라운드 명령은 실행하는 데 시간이 오래 걸리므로 해당 기간 동안 셸 액세스가 차단됩니다. 이는 명령이 더 광범위한 작업을 수행하거나 명시적으로 중지되거나 다른 사용자 입력을 받을 때까지 실행되도록 구성되었기 때문일 수 있습니다.

무기한으로 실행되는 명령은 top 유틸리티입니다. 시작하면 사용자가 프로세스를 종료할 때까지 계속 실행되고 디스플레이가 업데이트됩니다.

  1. top

q를 눌러 top을 종료할 수 있지만 일부 다른 프로세스에는 전용 종료 기능이 없습니다. 이를 막으려면 다른 방법을 사용해야 합니다.

프로세스 종료

명령줄에서 간단한 bash 루프를 시작한다고 가정합니다. 예를 들어 다음 명령은 10초마다 Hello World를 인쇄하는 루프를 시작합니다. 이 루프는 명시적으로 종료될 때까지 영원히 계속됩니다.

  1. while true; do echo "Hello World"; sleep 10; done

top과 달리 이와 같은 루프에는 "quit\ 키가 없습니다. 신호를 전송하여 프로세스를 중지해야 합니다. Linux에서 커널은 신호를 보낼 수 있습니다. 프로세스를 종료하거나 상태를 변경하라는 요청으로 실행 중인 프로세스 Linux 터미널은 일반적으로 사용자가 CTRL + C 키 조합 SIGINT 신호는 사용자가 키보드를 사용하여 종료를 요청했음을 프로그램에 알립니다.

시작한 루프를 중지하려면 CTRL 키를 누른 상태에서 C 키를 누릅니다.

CTRL + C

루프가 종료되고 제어가 셸로 반환됩니다.

CTRL + C 조합으로 보낸 SIGINT 신호는 프로그램에 보낼 수 있는 많은 신호 중 하나입니다. 대부분의 신호에는 연결된 키보드 조합이 없으며 대신 kill 명령을 사용하여 전송해야 합니다. 이에 대해서는 이 가이드의 뒷부분에서 다룰 것입니다.

프로세스 일시 중단

앞에서 언급했듯이 포그라운드 프로세스는 실행 기간 동안 셸에 대한 액세스를 차단합니다. 포그라운드에서 프로세스를 시작했지만 터미널에 액세스해야 한다는 사실을 깨달았다면 어떻게 해야 할까요?

보낼 수 있는 또 다른 신호는 "SIGTSTP\ 신호입니다. SIGTSTP는 "signal terminal stop\의 약자이며 일반적으로 신호 번호 20으로 표시됩니다. CTRL + Z를 누르면 터미널이 "일시 중지\ 명령을 등록한 다음 SIGTSTP 신호를 포그라운드 프로세스로 보냅니다. 기본적으로 이것은 명령 실행을 일시 중지하고 제어권을 터미널로 반환합니다.

설명을 위해 ping을 사용하여 5초마다 google.com에 연결합니다. 다음 명령은 ping 명령 앞에 command가 옵니다. 이렇게 하면 명령에 최대 개수를 인위적으로 설정하는 모든 셸 별칭을 무시할 수 있습니다.

  1. command ping -i 5 google.com

CTRL + C로 명령을 종료하는 대신 CTRL + Z를 누르십시오. 이렇게 하면 다음과 같은 출력이 반환됩니다.

Output
[1]+ Stopped ping -i 5 google.com

ping 명령이 일시적으로 중지되어 쉘 프롬프트에 다시 액세스할 수 있습니다. ps 프로세스 도구를 사용하여 다음을 표시할 수 있습니다.

  1. ps T
Output
PID TTY STAT TIME COMMAND 26904 pts/3 Ss 0:00 /bin/bash 29633 pts/3 T 0:00 ping -i 5 google.com 29643 pts/3 R+ 0:00 ps t

이 출력은 ping 프로세스가 여전히 나열되어 있지만 "STAT\ 열에 "T\가 있음을 나타냅니다. ps 매뉴얼 페이지에 따르면 이것은 "[a] 작업 제어 신호에 의해 중지된 작업\을 의미합니다.

이 가이드는 프로세스 상태를 더 자세히 변경하는 방법을 설명하지만 지금은 다음을 입력하여 포그라운드에서 명령 실행을 다시 시작할 수 있습니다.

  1. fg

프로세스가 재개되면 CTRL + C로 종료합니다.

백그라운드 프로세스 관리

포그라운드에서 프로세스를 실행하는 것에 대한 주요 대안은 프로세스가 백그라운드에서 실행되도록 허용하는 것입니다. 백그라운드 프로세스는 이를 시작한 특정 터미널과 연결되지만 셸에 대한 액세스를 차단하지 않습니다. 대신 백그라운드에서 실행되어 명령이 실행되는 동안 사용자가 시스템과 상호 작용할 수 있습니다.

포그라운드 프로세스가 터미널과 상호 작용하는 방식 때문에 모든 터미널 창에 대해 하나의 포그라운드 프로세스만 있을 수 있습니다. 백그라운드 프로세스는 프로세스가 완료될 때까지 기다리지 않고 즉시 제어권을 셸로 반환하기 때문에 많은 백그라운드 프로세스가 동시에 실행될 수 있습니다.

시작 프로세스

명령 끝에 앰퍼샌드 문자(&)를 추가하여 백그라운드 프로세스를 시작할 수 있습니다. 이것은 프로세스가 완료될 때까지 기다리지 않고 대신 실행을 시작하고 즉시 사용자에게 프롬프트로 돌아가도록 셸에 지시합니다. 명령의 출력은 여전히 터미널에 표시되지만(리디렉션되지 않는 한) 백그라운드 프로세스가 계속되는 동안 추가 명령을 입력할 수 있습니다.

예를 들어 다음을 입력하여 백그라운드에서 이전 섹션에서 동일한 ping 프로세스를 시작할 수 있습니다.

  1. command ping -i 5 google.com &

bash 작업 제어 시스템은 다음과 같은 출력을 반환합니다.

Output
[1] 4287

그러면 ping 명령의 정상 출력을 받게 됩니다.

Output
PING google.com (74.125.226.71) 56(84) bytes of data. 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms

그러나 동시에 명령을 입력할 수도 있습니다. 백그라운드 프로세스의 출력은 포그라운드 프로세스의 입력과 출력 사이에서 혼합되지만 포그라운드 프로세스의 실행을 방해하지는 않습니다.

백그라운드 프로세스 나열

중지되었거나 백그라운드에 있는 모든 프로세스를 나열하려면 jobs 명령을 사용할 수 있습니다.

  1. jobs

여전히 이전 ping 명령이 백그라운드에서 실행 중인 경우 jobs 명령의 출력은 다음과 유사합니다.

Output
[1]+ Running command ping -i 5 google.com &

이는 현재 단일 백그라운드 프로세스가 실행 중임을 나타냅니다. [1]는 명령의 작업 사양 또는 작업 번호를 나타냅니다. 작업 번호 앞에 백분율 기호를 표시하여 kill, fgbg와 같은 다른 작업 및 프로세스 제어 명령에서 이를 참조할 수 있습니다. 이 경우 이 작업을 %1로 참조합니다.

백그라운드 프로세스 중지

몇 가지 방법으로 현재 백그라운드 프로세스를 중지할 수 있습니다. 가장 간단한 방법은 관련된 작업 번호와 함께 kill 명령을 사용하는 것입니다. 예를 들어 다음을 입력하여 실행 중인 백그라운드 프로세스를 종료할 수 있습니다.

  1. kill %1

터미널이 구성된 방식에 따라 즉시 또는 다음에 ENTER를 누를 때 작업 종료 상태가 출력에 나타납니다.

Output
[1]+ Terminated command ping -i 5 google.com

jobs 명령을 다시 확인하면 현재 작업이 없습니다.

프로세스 상태 변경

이제 백그라운드에서 프로세스를 시작하고 중지하는 방법을 알았으므로 상태 변경에 대해 배울 수 있습니다.

이 가이드는 프로세스 상태를 변경하는 한 가지 방법인 CTRL + Z를 사용하여 프로세스를 중지하거나 일시 중단하는 방법을 이미 설명했습니다. 프로세스가 이 중지 상태에 있으면 포그라운드 프로세스를 백그라운드로 이동하거나 그 반대로 이동할 수 있습니다.

포그라운드 프로세스를 백그라운드로 이동

명령을 시작할 때 &로 종료하는 것을 잊은 경우에도 프로세스를 백그라운드로 이동할 수 있습니다.

첫 번째 단계는 다시 CTRL + Z로 프로세스를 중지하는 것입니다. 프로세스가 중지되면 bg 명령을 사용하여 백그라운드에서 다시 시작할 수 있습니다.

  1. bg

이번에는 앰퍼샌드가 추가된 작업 상태 줄을 다시 받게 됩니다.

Output
[1]+ ping -i 5 google.com &

기본적으로 bg 명령은 가장 최근에 중지된 프로세스에서 작동합니다. 여러 프로세스를 다시 시작하지 않고 연속으로 중지한 경우 해당 작업 번호로 특정 프로세스를 참조하여 올바른 프로세스를 백그라운드로 이동할 수 있습니다.

모든 명령을 배경화할 수 있는 것은 아닙니다. 일부 프로세스는 활성 터미널에 직접 연결된 표준 입력 및 출력으로 시작된 것을 감지하면 자동으로 종료됩니다.

백그라운드 프로세스를 포그라운드로 이동

fg를 입력하여 백그라운드 프로세스를 포그라운드로 이동할 수도 있습니다.

  1. fg

이것은 가장 최근에 백그라운드로 실행된 프로세스에서 작동합니다(jobs 명령 출력에서 +로 표시됨). 즉시 프로세스를 일시 중단하고 전경에 배치합니다. 다른 작업을 지정하려면 해당 작업 번호를 사용하십시오.

  1. fg %2

작업이 포그라운드에 있으면 CTRL + C를 사용하여 종료하거나 완료하거나 일시 중지하고 다시 백그라운드로 이동할 수 있습니다.

SIGHUP 다루기

프로세스가 백그라운드에 있든 포그라운드에 있든 프로세스를 시작한 터미널 인스턴스와 상당히 밀접하게 연결되어 있습니다. 터미널이 닫히면 일반적으로 터미널에 연결된 모든 프로세스(포그라운드, 백그라운드 또는 중지됨)에 SIGHUP 신호를 보냅니다. 이는 제어 터미널을 곧 사용할 수 없기 때문에 종료할 프로세스에 대한 신호입니다.

그러나 터미널을 닫고 백그라운드 프로세스를 계속 실행하려는 경우가 있을 수 있습니다. 이를 달성하는 방법에는 여러 가지가 있습니다. 보다 유연한 방법 중 하나는 dtach와 같은 터미널 멀티플렉서를 사용하는 것입니다.

그러나 이것이 항상 가능한 것은 아닙니다. 때때로 이러한 프로그램을 사용할 수 없거나 계속 실행하는 데 필요한 프로세스를 이미 시작했습니다. 때로는 이러한 작업이 수행해야 하는 작업에 비해 과도할 수도 있습니다.

nohup 사용

프로세스를 시작할 때 프로세스가 완료되기 전에 터미널을 닫고자 하는 경우 nohup 명령을 사용하여 시작할 수 있습니다. 이렇게 하면 시작된 프로세스가 SIGHUP 신호에 면역이 됩니다. 터미널이 닫혀도 계속 실행되며 init 시스템의 자식으로 다시 할당됩니다.

  1. nohup ping -i 5 google.com &

그러면 다음과 같은 라인이 반환되어 명령의 출력이 nohup.out이라는 파일에 작성됨을 나타냅니다.

Output
nohup: ignoring input and appending output to ‘nohup.out’

이 파일은 쓰기 가능한 경우 현재 작업 디렉토리에 배치되지만 그렇지 않으면 홈 디렉토리에 배치됩니다. 이는 터미널 창을 닫아도 출력이 손실되지 않도록 하기 위한 것입니다.

터미널 창을 닫고 다른 창을 열면 프로세스가 계속 실행됩니다. 각 터미널 인스턴스는 자체의 독립적인 작업 대기열을 유지하기 때문에 jobs 명령의 출력에서 찾을 수 없습니다. 터미널을 닫으면 ping 프로세스가 계속 실행 중이더라도 ping 작업이 소멸됩니다.

ping 프로세스를 종료하려면 해당 프로세스 ID(또는 "PID\)를 찾아야 합니다. pgrep 명령을 사용하여 이를 수행할 수 있습니다(또한 pkill 명령이지만 이 두 부분으로 구성된 방법은 의도한 프로세스만 종료하도록 합니다.) pgrep-a 플래그를 사용하여 검색합니다. 실행 파일의 경우:

  1. pgrep -a ping
Output
7360 ping -i 5 google.com

그런 다음 반환된 PID(첫 번째 열의 숫자)를 참조하여 프로세스를 종료할 수 있습니다.

  1. kill 7360

더 이상 필요하지 않은 경우 nohup.out 파일을 제거할 수 있습니다.

부인 사용

nohup 명령은 유용하지만 프로세스를 시작할 때 필요하다는 것을 알고 있는 경우에만 유용합니다. bash 작업 제어 시스템은 내장된 disown 명령으로 유사한 결과를 달성하는 다른 방법을 제공합니다.

disown 명령은 기본 구성에서 터미널의 작업 대기열에서 작업을 제거합니다. 즉, fg, bg, CTRL + Z, <코드>CTRL + C. 대신 작업이 jobs 출력의 목록에서 즉시 제거되고 더 이상 터미널과 연결되지 않습니다.

명령은 작업 번호를 지정하여 호출됩니다. 예를 들어 작업 2를 즉시 거부하려면 다음을 입력할 수 있습니다.

  1. disown %2

이렇게 하면 제어 터미널이 닫힌 후 nohup 프로세스와 다르지 않은 상태로 프로세스가 남습니다. 예외는 파일로 리디렉션되지 않는 경우 제어 터미널이 닫힐 때 모든 출력이 손실된다는 것입니다.

일반적으로 터미널 창을 즉시 닫지 않는 경우 작업 제어에서 프로세스를 완전히 제거하고 싶지는 않습니다. 프로세스가 SIGHUP 신호를 무시하도록 표시하기 위해 대신 -h 플래그를 disown 프로세스에 전달할 수 있지만 그렇지 않으면 일반 작업으로 계속 진행됩니다.

  1. disown -h %1

이 상태에서 일반적인 작업 제어 메커니즘을 사용하여 터미널을 닫을 때까지 프로세스를 계속 제어할 수 있습니다. 터미널을 닫을 때 시작할 때 파일로 리디렉션하지 않으면 다시 한 번 출력할 곳이 없는 프로세스에 갇히게 됩니다.

이 문제를 해결하기 위해 이미 실행 중인 프로세스의 출력을 리디렉션할 수 있습니다. 이것은 이 가이드의 범위를 벗어나지만 이 게시물에서는 이를 수행하는 방법에 대한 설명을 제공합니다.

huponexit 셸 옵션 사용

bash에는 자식 프로세스에 대한 SIGHUP 문제를 피하는 또 다른 방법이 있습니다. huponexit 셸 옵션은 종료 시 bash가 하위 프로세스에 SIGHUP 신호를 보낼지 여부를 제어합니다.

참고: huponexit 옵션은 셸 자체 내에서 셸 세션 종료가 시작될 때 SIGHUP 동작에만 영향을 미칩니다. 이것이 적용되는 몇 가지 예는 세션 내에서 exit 명령 또는 CTRL + D를 누르는 경우입니다.

셸 세션이 터미널 프로그램 자체를 통해 종료되면(창 닫기 등을 통해) huponexit 명령은 영향을 미치지 않습니다. bash가 SIGHUP 신호를 보낼지 여부를 결정하는 대신 터미널 자체에서 SIGHUP 신호를 bash로 보내면 신호가 자식 프로세스에 올바르게 전파됩니다.

앞서 언급한 주의 사항에도 불구하고 huponexit 옵션은 아마도 관리하기 가장 쉬운 옵션 중 하나일 것입니다. 다음을 입력하여 이 기능이 켜져 있는지 꺼져 있는지 확인할 수 있습니다.

  1. shopt huponexit

켜려면 다음을 입력하십시오.

  1. shopt -s huponexit

이제 exit를 입력하여 세션을 종료하면 모든 프로세스가 계속 실행됩니다.

  1. exit

이것은 프로그램 출력에 대한 마지막 옵션과 동일한 주의 사항이 있으므로 중요한 경우 터미널을 닫기 전에 프로세스의 출력을 리디렉션했는지 확인하십시오.

결론

작업 제어와 포그라운드 및 백그라운드 프로세스를 관리하는 방법을 배우면 명령줄에서 프로그램을 실행할 때 더 큰 유연성을 얻을 수 있습니다. 많은 터미널 창이나 SSH 세션을 열 필요 없이 프로세스를 조기에 중지하거나 필요에 따라 백그라운드로 이동하는 경우가 많습니다.