2부작 튜토리얼의 두 번째 파트인 이번 글에서는 Linux 서비스를 재부팅 또는 시스템 충돌 후 자동으로 시작되도록 설정하는 방법에 대해 설명하며, init 시스템을 자세히 다룰 것입니다. 다음을 참조할 수 있습니다: 시리즈의 1부: 재부팅 또는 시스템 충돌 후 Linux 서비스가 자동 시작되도록 설정하는 방법: 실제 예제는 여기에서.
이번 튜토리얼은 이론적인 내용이 많습니다. 따라서 Linux에서 init 시스템이 작동하는 방식을 더 깊이 이해하기 위한 참고 자료로 활용하시기 바랍니다. 이 튜토리얼의 첫 번째 파트에서는 init 시스템이 시작할 때 읽는 몇 가지 코드 스니펫과 시작 스크립트를 공유했습니다. 또한, MySQL를 예로 들어 충돌 또는 재부팅 후 Linux 서비스가 자동으로 시작되도록 활성화 및 비활성화하는 방법을 배웠습니다. 이 2부작 튜토리얼의 첫 번째 파트에서 배웠듯이, Linux의 다양한 배포판에서 사용되는 세 가지 init 시스템이 있습니다: System V, Upstart, Systemd. 특정 init 시스템을 사용하도록 설정된 배포판 및 버전을 이해하려면 이 튜토리얼의 첫 번째 파트를 참조할 수 있습니다..
이 튜토리얼에서는 튜토리얼의 첫 번째 파트에서 사용한 코드를 설명할 것입니다. init 시스템이 사용하는 명령과 설정 파일에 대해 자세히 설명하겠습니다. 시작해 볼까요!
사전 요구 사항
이 2부작 튜토리얼의 첫 번째 파트 결론에서 세 대의 테스트 서버를 계속 실행해 두어야 한다고 언급했습니다. 만약 삭제하셨다면, 다시 돌아가서 새로 생성하셔도 됩니다. 이렇게 하면 튜토리얼을 따라가는 데 도움이 됩니다. 준비해야 할 세 대의 테스트 서버는 다음과 같습니다:
- Ubuntu 9.04 및 이전 버전, 또는 Debian 6 x64 (System V init 시스템을 시연하는 데 사용합니다)
- Ubuntu 14.04 x64 (Upstart를 시연하는 데 사용합니다). 다음은 Ubuntu 서버를 쉽게 설정하는 방법에 대한 튜토리얼입니다..
- CentOS 7 x64 (Systemd를 시연하는 데 사용합니다).
명령을 실행하는 데 사용할 각 서버에 sudo 권한이 있는 사용자가 있어야 합니다. 이 Linux sudoers 파일을 설정하는 방법에 대한 튜토리얼이 도움이 될 수 있습니다.
참고: 튜토리얼의 명령은 시스템 서비스에 영향을 미칩니다. 따라서 실제 운영 서버에는 적용하지 마십시오.
런레벨(Runlevels)
A runlevel은 이용 가능한 서비스와 관련하여 Linux 시스템의 현재 상태를 설명하는 작동 수준입니다. 이 개념은 System V init에서 유래되었습니다. Linux 시스템이 부팅되면 커널을 초기화하고, 하나의 런레벨로 진입하며, 해당 런레벨과 관련된 시작 스크립트를 실행합니다. 시작 시에는 하나의 런레벨만 실행할 수 있습니다.
런레벨의 다른 예로는 종료 상태, 재시작 모드, 단일 사용자 모드 등이 있습니다. 각 레벨은 해당 상태에서 실행할 서비스를 결정합니다. 일부 서비스는 둘 이상의 레벨에서 실행될 수 있지만, 다른 서비스는 그렇지 않을 수 있습니다.
0부터 6까지 총 7개의 런레벨이 있습니다. 아래는 7개 런레벨에 대한 정의입니다:
- 런레벨 0: 시스템 종료
- 런레벨 1: 단일 사용자 및 복구 모드
- 런레벨 2, 3, 4: 네트워킹이 활성화된 다중 사용자 및 텍스트 모드
- 런레벨 5: 다중 사용자, 네트워크 활성화 및 그래픽 모드
- 런레벨 6: 시스템 재부팅
런레벨이 반드시 순차적으로 실행되는 것은 아닙니다. 런레벨 2, 3, 4는 실행 중인 Linux 배포판에 따라 다릅니다. 일부 배포판에서는 런레벨 4를 구현할 수 있지만 다른 배포판에서는 구현할 수 없습니다. 1부에서 설명한 대로 서비스를 자동 시작하도록 설정했을 때, 실제로는 해당 서비스를 런레벨에 추가한 것입니다. System V에서 OS는 특정 런레벨로 시작하며, 시작하는 동안 해당 런레벨과 관련된 모든 서비스를 시작하려고 시도합니다. 런레벨은 Systemd의 타겟(target)에 해당하며, 이에 대해서는 Systemd 섹션에서 논의할 것입니다.
Init 및 PID 1
init 시스템은 Linux 시스템이 부팅되고 커널이 메모리에 로드될 때 실행되는 가장 첫 번째 프로세스입니다. 사용자 프로세스나 시스템 서비스가 로드되는 방식, 순서, 자동 시작 여부를 결정하는 등 다양한 작업을 수행합니다. 모든 Linux 배포판에서 모든 프로세스는 프로세스 ID(PID)로 식별되며, init은 1번 PID를 가집니다. 이는 시스템이 부팅되면서 차례로 시작되는 다른 모든 프로세스의 부모 프로세스입니다.
init의 역사
최근 Linux 배포판에서 발견되는 init 시스템은 원래 시스템을 개선한 것입니다. 초기 버전의 Linux 배포판은 이와 유사하게 Unix 시스템에서 사용되었던 System V init을 사용했습니다. Linux가 발전함에 따라 Upstart init 데몬이 구현되었으며, 이는 Ubuntu에 의해 만들어졌습니다. 현재(이 튜토리얼을 작성하는 시점인 2021년)는 Systemd init 데몬이 있으며, 이는 Fedora에서 처음 구현되었습니다. Linux 시스템이 계속 발전함에 따라 더 새로운 init 시스템이 등장할 수도 있습니다. 이 튜토리얼에서는 System V, Upstart, Systemd의 세 가지에 대해 논의할 것입니다.
최근 Linux 버전에는 기본적으로 Systemd init 시스템이 탑재되어 있습니다. 하지만 하위 호환성을 위해 다른 이전 init 시스템도 유지하고 있습니다. 다른 변종 Linux에서 사용할 수 있는 System V의 다양한 구현이 존재합니다. 예를 들어, UNIX의 변종인 FreeBSD는 BSD init을 사용합니다. 이전 버전의 Debian은 SysVinit을 사용합니다. 둘 다 System V에서 파생되었습니다.
각 버전의 init 데몬이 서비스를 관리하는 방식은 다릅니다. 각 버전에 추가된 개선 사항은 Linux 시스템이 서비스, 장치, 포트 및 기타 리소스에서 필요로 하는 모든 것을 처리할 수 있는 강력한 서비스 관리 도구를 지향했습니다. 리소스를 병렬로 로드할 수 있고 시스템 충돌로부터 정상적으로 복구할 수 있는 강력한 시스템이 필요했습니다.
System V Init 시퀀스
System V는 초기화 지침을 보관하기 위해 inittab 파일을 사용합니다. Upstart는 하위 호환성을 위해 inittab 파일을 유지합니다. 다음은 System V의 시작 흐름입니다:
- init 시스템은 바이너리 파일 /sbin/init.
- 에서 시작됩니다. init 시스템이 메모리에 로드되면 가장 먼저 다음 위치의 파일을 읽습니다: /etc/inittab.
- 이 파일의 항목 중 하나는 머신이 부팅되어야 하는 런레벨을 결정합니다. 예를 들어, 런레벨 값이 5로 지정되면 Linux는 네트워크가 활성화된 다중 사용자 그래픽 모드(데스크톱용으로 설계된 배포판에서 일반적임)로 부팅됩니다. 여기에 지정된 런레벨은 항상 사용되는 값이기 때문에 기본 런레벨로 알려져 있습니다.
- 그런 다음 init 시스템은 /etc/inittab 파일을 더 자세히 살펴보고 해당 런레벨에 대해 실행해야 하는 init 스크립트를 읽습니다.
주어진 런레벨에 대해 실행할 스크립트를 찾음으로써, init 시스템은 시작해야 할 서비스를 찾게 됩니다. 이러한 init 스크립트는 이 튜토리얼의 첫 번째 부분에서 MySQL 서비스를 구성한 것과 동일한 방식으로 개별 서비스의 시작 동작을 구성하는 곳입니다.
System V Init 스크립트 구조
이 섹션에서는 init 스크립트에 대해 자세히 살펴보겠습니다. System V 구성 파일 또는 init 스크립트는 서비스를 제어하는 역할을 합니다. Init 스크립트는 서비스를 초기화(initialize) 하므로 init 스크립트라는 이름이 붙었습니다.
각 서비스에는 자체 init 스크립트가 있습니다. 예를 들어, MySQL init 스크립트는 MySQL 서버를 제어합니다. 애플리케이션 벤더는 특정 애플리케이션에 대한 init 스크립트를 제공하는 반면, 네이티브 Linux 서비스는 운영 체제 설치 시 함께 제공됩니다. 사용자 정의 애플리케이션을 만들 때 해당 애플리케이션을 위한 사용자 정의 init 스크립트를 직접 만들 수도 있습니다.
MySQL 서버와 같은 서비스를 시작하려면 먼저 해당 바이너리 프로그램이 메모리에 로드됩니다. 구성에 따라 프로그램은 클라이언트 연결을 계속 수락하기 위해 백그라운드에서 계속 실행될 수 있습니다. 서비스의 init 스크립트는 바이너리 애플리케이션을 시작, 중지 또는 재로드하는 작업을 처리합니다. System V의 init 스크립트는 쉘 스크립트입니다. 이들의 또 다른 이름은 rc(run command) 스크립트입니다.
System V 디렉터리 구조
init 스크립트의 상위 디렉터리는 /etc 디렉터리입니다. /etc/init.d 디렉터리는 init 쉘 스크립트의 실제 디렉터리입니다. 스크립트들은 rc 디렉터리로 심볼릭 링크(symlink)되어 있습니다.
여러 rc 디렉터리가 /etc 디렉터리 내에 존재하며, 각 디렉터리 이름에는 숫자가 포함되어 있습니다. 이 숫자는 서로 다른 런레벨을 나타냅니다. 디렉터리의 내용을 나열하면 다음과 같은 이름을 볼 수 있습니다: /etc/rc0.d, /etc/rc1.d, /etc/rc2.d 등.
각 rc 디렉터리의 내용을 보면 다음과 같이 시작하는 파일을 볼 수 있습니다: K 또는 S이 파일 이름에 포함되어 있고, 그 뒤에 두 자리 숫자가 붙습니다. 이 파일들은 실제 프로그램의 실제 init 셸 스크립트를 가리키는 심볼릭 링크를 포함하고 있습니다. 문자 K 및 S는 약어입니다. K는 Kill 또는 Stop을 의미하며, S는 Start를 나타냅니다. 파일 이름의 두 자리 숫자는 실행 순서를 나타냅니다. 만약 다음과 같은 이름의 파일을 본다면 K05script_name은 다음과 같은 이름의 파일보다 먼저 실행됩니다. K09script_name.
시작
시작 시퀀스를 계속 진행하면서, init 스크립트가 어떻게 호출되는지 살펴보겠습니다.
S 및 K 스크립트는 init 시스템에 의해 직접 호출되지 않습니다. 대신 다른 스크립트인 /etc/init.d/rc 스크립트에 의해 호출됩니다. /etc/inittab 파일은 init 데몬에게 시스템이 기본적으로 어떤 런레벨로 부팅되어야 하는지 지시합니다. 지정된 런레벨에 따라 /etc/inittab 파일의 한 줄이 /etc/init.d/rc 스크립트를 호출하고 기본 런레벨을 매개변수로 전달합니다. 이 매개변수를 사용하여 스크립트는 해당하는 /etc/rcN.d 디렉터리 아래의 파일을 호출합니다. 여기서 N은 런레벨을 나타냅니다. 예를 들어, 서버가 런레벨 5로 부팅되면 해당하는 /etc/rc5.d 디렉터리 아래의 파일들이 호출됩니다.
Inside the rc 디렉터리 내부에서 모든 K 스크립트는 숫자 순서대로 실행되며, 인수로 stop이 전달됩니다. 반면 모든 S 스크립트도 유사하게 start 인수를 사용하여 실행됩니다. /etc/rcN.d 심볼릭 링크가 가리키는 프로그램의 실제 init 셸 스크립트가 각각 stop 및 start 매개변수와 함께 호출됩니다.
간단히 말해, 리눅스 시스템이 특정 런레벨로 진입하거나 전환될 때마다 일어나는 일은 일부 서비스를 중지하기 위해 특정 스크립트가 실행되고, 다른 서비스를 시작하기 위해 다른 스크립트가 실행된다는 것입니다. 이 프로세스는 주어진 리눅스 상태에서 실행되어서는 안 되는 모든 프로세스를 중지하고, 실행되어야 하는 모든 프로세스를 자동으로 시작하도록 보장합니다.
System V 자동 시작
부팅 시 서비스가 자동으로 시작되도록 설정하면 init 동작을 직접 수정하게 됩니다. 예를 들어, 런레벨 2에서 서비스가 자동 시작되도록 구성하면 init 프로세스는 /etc/rc2.d 디렉터리에 적절한 심볼릭 링크를 생성합니다. 이해를 돕기 위해 예를 들어 설명하겠습니다.
System V 예시
실제적인 예를 보여드리기 위해 1부의 MySQL 서비스 구성을 사용하겠습니다. 따라서 ssh(또는 Windows를 사용하는 경우 putty)를 사용하여 sudo/root 사용자로 Debian 6 VPS에 로그인하고 다음 단계를 진행하십시오.
1단계: inittab 파일 열기 및 검사
먼저 터미널에서 다음 명령을 입력하여 inittab 파일의 내용을 확인합니다.
|
1 |
cat /etc/inittab | grep initdefault |
파일의 내용은 다음과 같아야 합니다.
|
1 |
id:2:initdefault: |
숫자 2는 시스템이 시작하는 런레벨을 나타냅니다. 이 경우 런레벨 2가 기본값이므로 이 Debian 시스템은 다중 사용자, 텍스트 모드인 런레벨 2로 시작됩니다. 확인하려면 다음 명령을 실행할 수 있습니다.
|
1 |
cat /etc/inittab | grep Runlevel |
다음과 유사한 출력이 표시됩니다.
|
1 2 3 4 |
# Runlevel 0 is halt. # Runlevel 1 is single-user. # Runlevels 2-5 are multi-user. # Runlevel 6 is reboot. |
2단계: rc 디렉터리 검사
다음으로 rc 디렉터리를 나열하려면 다음 명령을 실행합니다.
|
1 |
ls -ld /etc/rc*.d |
다음은 출력의 스크린샷입니다.

앞서 inittab 파일에서 보았듯이 시스템은 runlevel 2로 부팅되도록 구성되어 있으므로, /etc/rc2.d 아래의 스크립트가 시스템 시작 시 실행됩니다. 다음 명령을 사용하여 이 디렉터리의 내용을 나열할 수 있습니다.
|
1 |
ls -l /etc/rc2.d |
출력에서 볼 수 있듯이, 파일들은 단지 /etc/init.d 아래의 실제 스크립트 파일을 가리키는 심볼릭 링크일 뿐입니다. 다음은 출력의 일부입니다.

이 디렉터리에는 K 스크립트가 없고 S(시작) 스크립트만 있습니다. 스크립트는 여기에 링크된 서비스를 시작합니다. 예: rsync. 다음 소주제에서 다룰 mysql 서비스가 나열되어 있는 것도 확인할 수 있습니다.
3단계: Init 스크립트 검사
System V를 준수하는 서비스가 설치되면 /etc/init.d 디렉터리 아래에 셸 스크립트가 생성됩니다. 다음 명령어를 입력하여 MySQL 셸 스크립트의 사용 가능 여부를 확인할 수 있습니다:
|
1 |
ls -l /etc/init.d/my* |
아래와 같은 출력이 표시됩니다:

파일 크기가 상당히 큽니다. 다음 명령어를 입력하여 내용을 볼 수 있습니다:
|
1 |
cat /etc/init.d/mysql | less |
4단계: chkconfig 또는 sysv-rc-conf 사용하기
Chkconfig는 다음과 같은 RHEL 기반 배포판에서 CentOS System V 호환 서비스를 활성화하거나 비활성화하는 데 사용할 수 있는 명령어입니다. 또한 설치된 서비스와 각각의 런레벨을 나열하는 데 사용할 수도 있습니다. 이를 위한 명령어는 다음과 같습니다(CentOS에서 작동):
|
1 |
chkconfig --list | grep service_name |
데비안 배포판에는 이러한 유틸리티가 기본적으로 존재하지 않습니다. 데비안 시스템의 update-rc.d는 런레벨에서 서비스를 설치하고 제거하기만 합니다. 데비안 시스템에 chkconfig 기능을 가져오는 데 사용할 수 있는 사용자 정의 도구가 있습니다. 다음 명령어를 입력하여 설치하십시오:
|
1 |
sudo apt-get install sysv-rc-conf –y |
설치가 완료되면 다음 명령어를 실행하여 다양한 서비스의 런레벨 동작을 볼 수 있습니다:
|
1 |
sudo sysv-rc-conf |
이 명령어의 출력은 왼쪽에 서비스 이름이 표시되고 서비스가 실행되는 런레벨이 표시되는 표 형식으로 구성됩니다:

X는 서비스가 실행될 런레벨을 나타냅니다. 이 도구를 사용하면 방향키와 스페이스바를 사용하여 특정 런레벨에 대해 서비스를 비활성화하거나 활성화할 수 있습니다. 도구를 종료하려면 Q를 누르십시오.
5단계: 시스템 부팅 중 MySQL 시작 동작 테스트
위의 스크린샷에서 mysql 서비스가 런레벨 2, 3, 4, 5에서 활성화되어 있는 것을 볼 수 있습니다. 다음 명령어를 사용하여 MySQL을 비활성화할 수 있습니다:
|
1 |
sudo update-rc.d mysql disable |
출력은 다음과 같습니다. 모든 런레벨에서 서비스가 중지되었음을 확인하십시오:

디렉터리의 내용을 보려면 아래 명령어를 실행하십시오:
|
1 |
ls -l /etc/rc2.d |
아래 출력에서 mysql 줄을 확인하십시오:
|
1 |
lrwxrwxrwx 1 root root 15 Dec 11 05:28 K01mysql -> ../init.d/mysql |
출력은 심볼릭 링크가 Kill(중지)을 의미하는 K로 변경되었음을 보여줍니다. 따라서 MySQL은 기본적으로 런레벨 2에서 자동 시작되지 않습니다. System V에서 서비스를 활성화하거나 비활성화할 때마다 이러한 일이 발생합니다. 서비스의 기본 런레벨 디렉터리 아래에 S(시작) 스크립트가 있는 한, init 데몬은 시스템 부팅 중에 해당 서비스를 시작합니다.
서비스를 다시 활성화하려면 다음 명령어를 입력하십시오:
|
1 |
sudo update-rc.d mysql enable |
6단계: 시스템 크래시 후 MySQL 시작 동작 테스트
이 섹션에서는 System V가 서비스 크래시를 처리하는 방법에 대해 설명합니다. 이 지식을 사용하여 크래시 발생 후 사용자 정의 서비스의 동작을 구성할 수 있습니다.
이 튜토리얼의 첫 번째 부분에서 크래시 발생 후 MySQL이 자동으로 시작되도록 /etc/inittab 파일을 변경했습니다. 이 동작을 활성화하기 위해 다음 줄을 추가했습니다:
|
1 |
ms:2345:respawn:/bin/sh /usr/bin/mysqld_safe |
몇 가지 테스트를 수행하여 이 동작을 확인할 수 있습니다. 먼저 다음 명령어를 입력하여 VPS를 재부팅하십시오:
|
1 |
sudo reboot |
재부팅 후 mysql_safe 및 mysqld가 어떤 프로세스 ID로 실행 중인지 확인하려면 다음 명령어를 입력하여 프로세스 ID를 가져옵니다:
|
1 |
ps -ef | grep mysql |
우리가 얻은 출력은 다음과 같습니다:
|
1 2 |
hackins 1836 1 0 07:30 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe mysql 186338 907 0 07:30 ? 00:00:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306 |
프로세스 ID를 기록해 두세요. 저희의 경우 1836과 186338이었습니다. 이제 다음 명령을 입력하여 -9 스위치로 프로세스를 종료하여 충돌을 시뮬레이션합니다. 본인의 프로세스 ID로 대체해야 합니다:
|
1 2 |
sudo kill -9 1836 sudo kill -9 186338 |
몇 분 후, 다음 명령을 실행하여 MySQL의 상태를 확인합니다:
|
1 |
sudo service mysql status |
출력 결과는 MySQL이 실행 중임을 나타내며, 이는 시뮬레이션된 충돌 후 다시 생성(respawn)되었음을 의미합니다. 만약 ps -ef | grep mysql 명령을 다시 실행하면, mysqld_safe 및 mysqld 프로세스가 모두 실행 중인 것을 확인할 수 있습니다. 단, 새로운 ID로 실행됩니다.
프로세스를 여러 번 종료해 보아도 몇 분 후에 다시 생성될 것입니다. 이 동작은 우리가 /etc/inittab 파일에 추가한 행 덕분에 가능합니다. 이것이 System V에서 충돌 후 서비스를 자동으로 재시작하도록 구성하는 방법입니다. 구문을 다시 보려면 이 튜토리얼의 파트 1을 참조하십시오.
일부 사용자 정의 서비스에는 버그가 있어 여러 번 시도한 후에도 다시 생성되지 않을 수 있습니다. init 데몬은 서비스를 다시 생성하려고 시도하지만, 2분 이내에 10번 이상 실패하면 Linux 시스템은 최대 5분 동안 해당 서비스를 비활성화합니다. 이는 시스템을 안정적으로 유지하고 충돌하는 서비스에 시스템 리소스가 낭비되지 않도록 하는 데 도움이 됩니다. 수정해야 할 사용자 정의 애플리케이션의 문제를 식별하기 위해 시스템 로그를 확인하는 것이 좋습니다.
Upstart 소개
System V init 시스템은 오랫동안 Linux 배포판에서 매우 중요했습니다. 그러나 기술이 그렇듯 계속 발전하고 있습니다. 오픈 소스 커뮤니티의 지원 덕분에 Linux 생태계는 엄청나게 성장했습니다. System V는 작업과 서비스를 직렬 방식으로 로드하므로 복잡성이 발생하고 시간이 소모됩니다. 또한 System V가 설계되지 않았던 현대적인 플러그형 저장 매체의 도입으로 인해 다른 init 시스템의 필요성이 대두되었습니다.
Ubuntu의 개발자들은 또 다른 초기화 시스템을 개발하기 시작했습니다. 이 init 시스템은 OS의 더 빠른 로딩을 처리하고, 충돌한 서비스의 정상적인 정리를 보장하며, 시스템 서비스 간의 종속성을 예측 가능하게 유지하고, 플러그형 저장 매체를 고려하도록 설계되었습니다. 그렇게 Upstart 데몬이 탄생했습니다.
Upstart init은 다음과 같은 점에서 System V init에 비해 몇 가지 장점이 있습니다:
- Upstart는 System V처럼 서비스를 직렬로 로드하지 않으므로 시스템의 부팅 시간을 단축합니다.
- 정상적인 정리 및 서비스 재생성(respawn)을 통해 충돌한 서비스를 더 잘 처리하도록 설계되었습니다.
- Upstart는 유연한 이벤트 시스템을 사용하여 다양한 상태의 서비스 처리를 사용자 정의합니다.
- 이 init은 System V와 같이 서비스를 로드하고 관리하기 위한 복잡한 셸 스크립트를 피합니다. Upstart는 이해하고 수정하기 쉬운 간단한 구성 파일을 사용합니다.
- Upstart는 하위 호환성을 염두에 두고 구축되었습니다. 네이티브 System V 서비스를 관리하기 위해 /etc/init.d/rc 스크립트가 여전히 실행됩니다.
- 모두 동일한 스크립트를 가리키는 불필요한 심볼릭 링크를 유지하지 않습니다.
Upstart 이벤트
Upstart는 이벤트 기반이므로 여러 이벤트를 동일한 서비스와 연결할 수 있습니다. 이 이벤트 기반 아키처는 유연한 서비스 관리를 보장합니다. 각 이벤트는 해당 이벤트에 특정한 셸 스크립트를 호출할 수 있습니다.
Upstart 이벤트는 다음과 같습니다:
- Starting
- Started
- Stopping
- Stopped
이벤트 사이에 서비스는 다음을 포함하되 이에 국한되지 않는 다양한 상태에 있을 수 있습니다:
- Waiting
- Pre-start
- Starting
- Post-start
- Running
- Pre-stop
- Stopping
- Post-stop
Upstart init은 이러한 각 상태에 대해 조치를 취하도록 구성할 수 있으므로 디자인이 유연합니다.
Upstart Init 시작 시퀀스
Upstart init은 System V와 마찬가지로 시작 시 /etc/init.d/rc 스크립트를 실행합니다. 이 스크립트는 하위 호환성을 보장하기 위해 모든 System V init 스크립트를 정상적으로 실행합니다.
Upstart 구성 파일은 /etc/init 디렉토리에 위치하므로 기본적으로 해당 디렉토리를 찾아보고 이 디렉토리 아래의 구성 파일에 있는 셸 명령을 실행합니다.
Upstart 구성 파일
Upstart init은 System V에서 사용되는 bash 스크립트와 달리 서비스 구성 파일을 사용하여 서비스를 제어합니다. 이러한 서비스 구성 파일의 명명 표준은 service_name.conf.
이 파일들은 스탠자(stanza)라고 불리는 다양한 섹션으로 나뉜 일반 텍스트 콘텐츠를 포함하고 있습니다. 각 스탠자는 서비스의 서로 다른 상태와 동작을 설명합니다. 서로 다른 스탠자는 서비스의 서로 다른 이벤트를 제어합니다. 예를 들어, waiting, pre-start, start, pre-stop, stopping 등이 있습니다.
스탠자에는 셸 명령어가 포함되어 있어 각 서비스의 각 이벤트에 대해 여러 작업을 시작할 수 있습니다. 또한, 각 서비스 구성 파일은 다음 두 가지를 지정합니다:
- 서비스가 시작되고 중지되어야 하는 런레벨.
- 서비스가 충돌하여 종료될 경우 자동 재시작(respawn)할지 여부.
Upstart 디렉터리 구조
Upstart 서비스 구성 파일은 다음 디렉터리 아래에 위치합니다: /etc/init 디렉터리. 이것을 다음 디렉터리와 혼동하지 마십시오: /etc/init.d.
Upstart 예제
이 예제에서는 시스템 부팅 중 및 충돌이 발생했을 때 Upstart가 서비스를 처리하는 방법을 살펴보겠습니다. 이 튜토리얼의 첫 번째 부분에서 보여준 실용적인 예제를 더 자세히 설명하겠습니다.
1단계: Ubuntu 14.0.4 서버에 로그인
먼저, Upstart를 테스트하기 위해 Ubuntu 14.0.4를 실행하는 두 번째 VPS를 사용하겠습니다. 이 Linux 배포판은 Upstart를 기본적으로 구현하기 때문입니다. Windows를 사용하는 경우 ssh 또는 putty를 사용하십시오. root 또는 sudo 권한이 있는 사용자로 로그인해야 합니다. 저에게는 hackins라는 사용자가 있으므로 다음과 같이 로그인합니다:
|
1 |
ssh hackins@my_server_ip |
사용자의 root/sudo 사용자 및 서버의 공인 IP 주소로 대체하십시오. 그런 다음 Enter 키를 누르고 비밀번호 또는 암호를 입력하십시오.
2단계: init 및 rc 디렉터리 검사
Upstart 구성 파일은 /etc/init 디렉터리에 저장됩니다. 이 디렉터리는 새 서비스 구성 파일을 생성할 때 사용할 디렉터리입니다.
/etc/init 디렉터리의 구성 파일 이름을 나열하려면 다음 명령을 실행하십시오:
|
1 |
sudo ls -l /etc/init/ | less |
위 명령의 출력에서 볼 수 있듯이 많은 서비스가 Upstart에서 실행 중입니다. less를 종료하려면 Q를 누르십시오.
rc 디렉터리에서 System V용 서비스 구성 파일을 나열하기 위해 다음을 실행하면 몇 개만 표시됩니다:
|
1 |
sudo ls -l /etc/rc3.d/* | less |
3단계: Upstart 파일 검사
이 튜토리얼의 첫 번째 파트에서 우리는 서버 구성에 대해 배우기 위해 mysql.conf 파일을 사용했습니다. 지식을 넓히기 위해 다른 구성을 사용해 보겠습니다. cron 구성 파일이 좋은 후보입니다. 파일을 열려면 다음 명령을 입력하십시오:
|
1 |
sudo nano /etc/init/cron.conf |
아래 스크린샷과 유사한 출력을 얻어야 합니다:

스크립트는 매우 간단합니다. 다음과 같은 중요한 필드에 유의하십시오: start on, stop on, fork, 그리고 respawn. 이 지시어들이 무엇을 하는지 정의해 보겠습니다:
- start on은 시스템이 런레벨 2, 3, 4 또는 5에 진입할 때 Ubuntu가 cron 데몬을 시작하도록 지시합니다. 여기에 지정되지 않은 다른 런레벨(즉, 0, 1 또는 6)에서는 실행되지 않습니다.
- stop on은 Ubuntu에 실행 중인 데몬을 중지하도록 지시합니다. 그러나 이 경우에는 느낌표(!)가 있으며, 이는 부정 기호입니다. 스크립트는 느낌표 뒤의 런레벨인 2, 3, 4, 5에서 중지되지 않아야 합니다.
- fork 지시어는 Upstart에 프로세스를 콘솔에서 분리하고 백그라운드에서 계속 실행하도록 지시합니다.
- respawn 지시어는 어떤 이유로든 cron이 충돌하여 종료될 경우 자동으로 시작하도록 시스템에 지시합니다.
아무것도 입력하지 않고 편집기를 종료하려면 Ctrl X를 누르십시오.
다른 Upstart 구성 파일도 start, stop, respawn에 대한 스탠자가 있는 동일한 구조를 따릅니다. 일부 구성 파일에는 pre-start, pre-stop, post-start 등을 위한 추가 스크립트 블록이 있을 수 있습니다. 이러한 코드 블록은 프로세스가 정의된 상태 중 하나에 있을 때 시스템이 실행할 작업을 알려줍니다.
4단계: 시스템 부팅 후 MySQL 서비스 시작 동작 테스트
MySQL은 기본적으로 시스템이 부팅된 후 자동으로 시작되도록 설정되어 있습니다. 이를 비활성화하고 동작을 확인해 보겠습니다. Upstart에서는 다음과 같은 이름의 파일을 생성하여 서비스를 비활성화할 수 있습니다: service_name.override (위치: /etc/init/ 디렉터리). 파일 내용은 단 한 단어입니다: manual.
이 명령을 사용하여 MySQL 서비스를 비활성화하는 방법을 알아보겠습니다. 다음 명령을 입력하여 nano 편집기로 파일을 엽니다:
|
1 |
sudo nano /etc/init/mysql.override |
열린 파일에 다음 줄을 추가합니다:
|
1 |
Manual |
Ctrl + O를 누른 다음 Enter를 눌러 변경 사항을 저장합니다. Ctrl + X를 눌러 편집기를 종료합니다. 다음 명령을 실행하여 서버를 재부팅합니다:
|
1 |
sudo reboot |
몇 분 동안 기다린 후 다시 로그인합니다. 다시 로그인한 후, 다음 명령을 입력하여 MySQL 서비스의 상태를 테스트합니다:
|
1 |
sudo initctl status mysql |
출력 결과는 서비스가 실행 중이 아님을 나타냅니다:
|
1 |
mysql stop/waiting |
이는 시스템 부팅 후 MySQL이 자동으로 시작되지 않았음을 나타냅니다. 다음으로, MySQL 설정 파일을 열고 start 지시어가 변경되었는지 확인합니다:
|
1 |
sudo cat /etc/init/mysql.conf | grep start\ on |
출력 결과는 아무것도 변경되지 않았음을 나타냅니다:
|
1 |
start on runlevel [2345] |
즉, 서비스가 자동 시작되지 않을 때 서비스의 설정 파일(service_name.conf)만 확인하면 오류를 찾지 못할 수 있습니다. 디렉터리에 service_name.override 파일이 존재하는지도 확인해야 합니다.
다음 명령을 입력하여 override 파일을 삭제하고 MySQL 서비스를 다시 활성화합니다. 그런 다음 서버를 재부팅합니다:
|
1 2 |
sudo rm -f /etc/init/mysql.override sudo reboot |
서버가 부팅되면 MySQL 서비스의 상태를 다시 테스트합니다:
|
1 |
sudo initctl status mysql |
MySQL 서비스가 자동으로 시작되었음을 보여주어야 합니다.
5단계: 시스템 크래시 후 MySQL 서비스 시작 동작 테스트
기본적으로 MySQL 서비스는 크래시가 발생하면 자동으로 재시작됩니다. 이 동작을 중지하기 위해 mysql.conf 파일을 편집하겠습니다. 다음 명령을 입력하여 nano 편집기로 파일을 엽니다:
|
1 |
sudo nano /etc/init/mysql.conf |
다음 respawn 지시어 줄을 찾아 아래와 같이 #:
|
1 2 |
# respawn # respawn limit 2 5 |
다음 명령을 실행하여 서비스를 재시작합니다:
|
1 2 |
sudo initctl stop mysql sudo initctl start mysql |
위의 명령을 사용하여 서비스를 중지하고 시작한 이유는 initctl restart 또는 initctl reload가 여기서는 작동하지 않기 때문입니다. MySQL 서비스를 시작하는 명령을 실행하면 출력에 다음과 같이 MySQL의 PID가 표시됩니다:
|
1 |
mysql start/running, process 1439 |
여기서 PID는 1439였습니다. 다음으로, 명령을 실행했을 때 얻은 PID를 기록해 두세요. 다음 단계에서 사용하겠습니다. 크래시를 시뮬레이션하려면 다음 명령을 사용하여 MySQL 프로세스를 강제 종료합니다. 위에서 설명한 대로 본인의 PID로 변경해야 합니다:
|
1 |
sudo kill -9 1439 |
크래시 후 MySQL이 재시작되었는지 확인하려면 몇 분 동안 기다린 후 다음 명령을 입력합니다:
|
1 |
sudo initctl status mysql |
출력 결과는 MySQL이 중지되었음을 나타냅니다:
|
1 |
mysql stop/waiting |
상태를 몇 번 더 확인하여 변화가 있는지 살펴보세요. MySQL이 계속 중지된 상태로 유지되는 것을 확인할 수 있습니다. 이는 서비스 설정 파일에 respawn 지시어(우리가 주석 처리한 지시어)가 없기 때문입니다. respawn 지시어에 대한 자세한 설명은 이 튜토리얼의 1부를 참조하세요.
시스템 부팅 또는 충돌 후 서비스의 자동 재시작을 비활성화하는 방법을 보여드린 이유는 무엇일까요? 이는 주로 문제 해결을 위한 것입니다. 예를 들어, 서비스가 시작된 후 계속 충돌이 발생하면 문제를 해결하고 시스템을 안정적으로 유지하기 위해 자동 재시작을 비활성화할 수 있습니다. 또한, 다음 섹션에서 다룰 systemd가 기본적으로 탑재된 새로운 Linux 배포판으로 업그레이드하는 경우, 일부 오래된 서비스 구성이 자동으로 재시작되는 것을 방지할 수도 있습니다.
Systemd 소개
Systemd는 최신 Linux 배포판에서 볼 수 있는 최신 init 시스템입니다. 여기에는 현대적인 Linux 시스템을 구성하는 많은 구성 요소가 포함되어 있습니다.
Systemd는 서비스뿐만 아니라 전체 Linux 시스템을 관리합니다. 이 섹션에서는 systemd가 시스템 부팅 또는 충돌 후 서비스의 동작을 제어하는 방법에 초점을 맞출 것입니다.
Systemd는 System V init 스크립트 및 명령과 하위 호환됩니다. 따라서 System V로 구성된 서비스가 있는 경우 Systemd에서도 실행됩니다. 대부분의 Upstart 및 System V 관리 명령은 Systemd와 작동하도록 변경되었습니다. Systemd는 부팅 시 자신의 이름을 init으로 바꿉니다. /sbin/init 파일이 존재하며, 이는 다음을 가리키는 심볼릭 링크입니다: /bin/systemd.
Systemd 구성 파일: 유닛 파일
Systemd 구성은 유닛 파일로 이루어집니다. 각 유닛 파일은 시스템 리소스를 나타냅니다. 다른 두 init 시스템(즉, System V 및 Upstart)은 Linux 시스템의 서비스를 관리하는 역할을 담당했지만, Systemd는 서비스 데몬뿐만 아니라 장치 운영 체제 경로, 소켓, 마운트 포인트 등과 같은 다른 유형의 시스템 리소스도 관리합니다. 유닛 파일은 리소스에 대한 정보를 저장합니다.
각 유닛 파일은 다음과 같은 명명 스타일로 특정 시스템 리소스를 나타냅니다: service_name.unit_type. 즉, home.mount, dbus.service, sshd.socket 등과 같은 파일을 찾을 수 있습니다. 유닛 파일은 이해하고 수정하기 쉬운 선언적 구문을 가진 단순한 텍스트 파일입니다.
디렉터리 구조
기본 유닛 파일의 주요 위치는 /lib/systemd/system/ 디렉터리입니다. 사용자가 생성하거나 시스템 관리자가 사용자 정의하여 생성한 유닛 파일 및 기타 수정된 기본 유닛 파일은 /etc/systemd/system 디렉터리에 저장됩니다.
동일한 이름의 유닛 파일이 /lib/systemd/system/ 및 /etc/systemd/system 디렉터리 모두에 존재하는 경우, systemd는 /etc 디렉터리 아래에 있는 파일을 사용합니다.
부팅 시 또는 다른 타겟/런레벨에서 서비스가 시작되도록 활성화하면, 다음 경로의 적절한 디렉터리 아래에 해당 서비스 유닛 파일에 대한 심볼릭 링크가 생성됩니다: /etc/systemd/system. /etc/systemd/system 디렉터리에 있는 유닛 파일은 /lib/systemd/system 디렉터리에 있는 유사한 이름의 파일에 대한 심볼릭 링크일 뿐입니다.
Systemd 초기화 시퀀: 타겟 유닛
타겟 유닛은 일반적으로 접미사 .target이 붙는 고유한 유형의 유닛 파일입니다. 타겟 유닛은 하나의 특정 리소스를 나타내지 않는다는 점에서 다른 유형의 유닛 파일과 다릅니다. 대신, 특정 시점의 전체 시스템 상태를 나타냅니다.
이를 위해 타겟 유닛은 특정 상태의 일부인 여러 유닛 파일을 그룹화하고 실행합니다. Systemd 타겟과 System V 런레벨은 대략적으로 비교할 수 있지만 동일하지는 않습니다. 타겟 유닛 파일은 숫자 대신 이름을 가집니다. 예를 들어, runlevel 3 대신 multi-user.target을, runlevel 6 대신 reboot.target을 볼 수 있습니다. Linux 시스템은 multi-user.target으로 부팅될 수 있습니다. 이 경우 기본적으로 서버를 런레벨 2, 3 또는 4로 전환하여 네트워킹이 활성화된 다중 사용자 텍스트 모드로 시스템을 시작합니다.
차이점은 서버를 해당 레벨로 전환하는 방식에 있습니다. System V는 서비스를 순차적으로 시작합니다. 반면, systemd는 시스템이 부팅될 때 다른 서비스나 리소스가 존재하는지 확인하고 로드 순서를 결정합니다.
systemd 타겟 유닛과 System V 런레벨의 또 다른 차이점은 System V를 사용하는 Linux 배포판은 단 하나의 런레벨로만 존재한다는 것입니다. 런레벨을 수정하면 단순히 해당 새로운 런레벨로 전환되어 존재하게 됩니다. 반면에 타겟 유닛 파일은 포괄적일 수 있습니다. 또한 타겟 유닛을 활성화하면 다른 타겟 유닛이 그 일부로 로드되도록 보장합니다. 예를 들어, 그래픽 사용자 인터페이스를 사용하여 Linux 시스템을 부팅하면 graphical.target이 활성화됩니다. 이는 결과적으로 자동으로 multi-user.target 역시 로드되고 활성화되도록 보장합니다.
다음은 런레벨과 타겟을 비교한 표입니다.
| 런레벨 (System V) | 타겟 유닛 (systemd) |
| 런레벨 0 | poweroff.target |
| 런레벨 1 | rescue.target |
| 런레벨 2,3,4 | multi-user.target |
| 런레벨 5 | graphical.target |
| 런레벨 6 | reboot.target |
Systemd default.target
systemd에서 default.target은 System V의 기본 런레벨에 해당하는 것입니다. System V의 기본 런레벨은 inittab 파일에 정의되어 있는 것을 보았습니다. systemd에는 default.target 파일이 있습니다. 기본 타겟 파일은 /etc/systemd/system 디렉토리에 저장됩니다. 이 파일은 /lib/systemd/system 아래의 타겟 유닛 파일 중 하나로 심볼릭 링크됩니다. 기본 타겟을 변경하는 것은 단순히 심볼릭 링크를 다시 생성하고 시스템의 런레벨을 수정하는 것을 의미합니다.
System V에서 inittab은 Linux가 init 스크립트를 찾을 디렉토리를 지정했습니다. 이는 앞서 설명한 rc 디렉토리 중 하나일 수 있습니다. 반면에 systemd 기본 타겟은 부팅 시 로드할 리소스 유닛을 결정합니다. 정의된 모든 유닛이 로드됩니다. 그러나 모든 유닛이 병렬로 로드되는 것은 아니며, 모든 유닛이 순차적으로 로드되는 것도 아닙니다. 리소스 유닛의 로드는 해당 유닛이 wants 또는 requires.
Systemd 종속성: Wants 및 Requires
이 섹션에서는 Systemd가 종속성을 처리하는 방법에 대해 설명합니다. Upstart를 사용하면 구성 파일을 사용할 때 서비스의 병렬 로드가 가능하다는 것을 보았습니다. 또한 System V가 런레벨을 사용하여 자동 시작할 서비스나 다른 서비스 또는 리소스가 준비될 때까지 대기할 서비스를 결정하는 방법도 논의했습니다. 마찬가지로, Systemd 서비스는 하나 이상의 타겟에서 로드되도록 구성하거나 다른 서비스 또는 리소스가 준비될 때까지 대기하도록 구성할 수 있습니다.
Systemd에서 다른 유닛을 requires하는 유닛은 필요한 유닛이 로드되고 활성화될 때까지 시작되지 않습니다. 첫 번째 유닛이 활성화되어 있는 동안 필요한 유닛이 로드되지 않으면 첫 번째 유닛이 중지됩니다.
이러한 동작은 시스템 안정성을 보장합니다. 특정 리소스(예: 포트)가 사용 가능하고 활성화되어 있기를 requires하는 서비스는 리소스를 사용할 수 있을 때까지(즉, 포트가 열릴 때까지) 대기하도록 만들 수 있습니다.
반면에 다른 유닛을 wants하는 유닛은 그러한 제한을 두지 않습니다. 호출하는 유닛이 여전히 활성화되어 있는 동안 원하는 유닛이 중지되더라도 중지되지 않습니다. 예를 들어, graphical-target 모드의 일부 필수적이지 않은 서비스가 이에 해당합니다.
Systemd 예제
systemd에서 서비스의 동작을 구성하는 방법을 살펴보겠습니다.
1단계: VPS 인스턴스에 로그인
실제 서비스로 MySQL을 사용하고 서버로 CentOS 7을 사용할 것입니다. 단계를 실제로 진행하고 개념을 이해하려면 CentOS 7 VPS에 로그인하거나 CloudSigma에서 하나를 생성하십시오. CentOS 7, Debian 7 또는 8, 또는 Ubuntu 15 이상의 배포판을 실행하는 VPS가 이 섹션에 적합합니다. 이들은 모두 systemd를 포함하고 있기 때문입니다. ssh 명령을 사용하여 로그인하거나, Windows를 사용하는 경우 PuTTY를 사용하십시오:
|
1 |
ssh hackins@your_server_ip |
2단계: default.target 파일 및 종속성 검사
Systemd의 시작 시퀀스는 긴 종속성 체인을 따르며, 이에 대해서는 이 섹션에서 자세히 설명하겠습니다.
- default.target
default.target 파일은 일반 부팅 중에 시작되는 서비스를 제어합니다. 다음 명령을 사용하여 기본 타겟 유닛 파일을 나열할 수 있습니다:
|
1 |
sudo ls -l /etc/systemd/system/default.target |
출력은 아래 스크린샷과 같이 표시됩니다:
![]()
스크린샷은 기본 타겟이 다음 디렉토리의 multi-user.target 파일로 심볼릭 링크되어 있음을 보여줍니다: /lib/systemd/system/ 디렉터리입니다. 이는 기본적으로 시스템이 다음에서 부팅됨을 의미합니다: multi-user.target, 이는 다음과 같습니다: runlevel 3.
- multi-user.target.wants
multi-user.target 파일이 필요로 하는 모든 서비스를 보려면 다음 명령을 입력하십시오:
|
1 |
sudo ls -l /etc/systemd/system/multi-user.target.wants/*.service |
출력에는 많은 줄이 포함되어 있으며, 다음은 그 일부입니다:
|
1 2 3 4 5 6 7 8 |
lrwxrwxrwx. 1 root root 38 Dec 25 10:32 /etc/systemd/system/multi-user.target.wants/mysqld.service -> /usr/lib/systemd/system/mysqld.service lrwxrwxrwx. 1 root root 36 Dec 16 19:10 /etc/systemd/system/multi-user.target.wants/ntpd.service -> /usr/lib/systemd/system/ntpd.service lrwxrwxrwx. 1 root root 39 Dec 16 19:08 /etc/systemd/system/multi-user.target.wants/postfix.service -> /usr/lib/systemd/system/postfix.service lrwxrwxrwx. 1 root root 46 Dec 16 19:08 /etc/systemd/system/multi-user.target.wants/rhel-configure.service -> /usr/lib/systemd/system/rhel-configure.service lrwxrwxrwx. 1 root root 39 Dec 16 19:08 /etc/systemd/system/multi-user.target.wants/rsyslog.service -> /usr/lib/systemd/system/rsyslog.service lrwxrwxrwx. 1 root root 36 Dec 16 19:08 /etc/systemd/system/multi-user.target.wants/sshd.service -> /usr/lib/systemd/system/sshd.service lrwxrwxrwx. 1 root root 37 Dec 16 19:08 /etc/systemd/system/multi-user.target.wants/tuned.service -> /usr/lib/systemd/system/tuned.service lrwxrwxrwx. 1 root root 40 Dec 16 19:14 /etc/systemd/system/multi-user.target.wants/yum-cron.service -> /usr/lib/systemd/system/yum-cron.service |
출력에서 볼 수 있듯이, 이들은 다음 디렉터리에 있는 실제 유닛 파일을 가리키는 심볼릭 링크입니다: /lib/systemd/system/ 디렉터리. 저희는 mysqld.service가 multi-user.target의 일부이기도 하다는 점을 알려드리기 위해 강조 표시했습니다. 특정 서비스가 시작 시 실행되도록 구성되어 있는지 확인하려면 해당 파일에 대한 명령을 수정할 수 있습니다. 예를 들어, 다음 명령을 사용하여 mysql 또는 cron 데몬을 찾도록 출력을 필터링할 수 있습니다:
|
1 |
sudo systemctl show --property "Wants" multi-user.target | fmt -10 | grep mysql |
출력은 다음과 같습니다:
|
1 |
mysqld.service |
cron 데몬에 대한 결과를 필터링하려면 다음 명령을 입력하십시오:
|
1 |
sudo systemctl show --property "Wants" multi-user.target | fmt -10 | grep cron |
출력은 다음과 같습니다:
|
1 |
crond.service |
Apart from the multi-user.target 외에도 다른 유형의 타겟이 존재합니다. 예: system-update.target 또는 basic.target.
multi-user 타겟이 의존하는 타겟이 무엇인지 보려면 다음 명령을 입력하십시오:
|
1 |
sudo systemctl show --property "Requires" multi-user.target | fmt -10 |
출력은 다음과 같습니다:
|
1 |
Requires=basic.target |
즉, basic-target이 먼저 로드되어야 시스템이 multi-user.target 모드로 시작할 수 있음을 의미합니다.
- basic-target
basic.target이 필요로 하는 다른 타겟이 무엇인지 보려면 다음 명령을 입력하십시오:
|
1 |
sudo systemctl show --property "Requires" basic.target | fmt -10 |
출력 결과는 다음과 같습니다:
|
1 |
Requires=sysinit.target |
- sysinit.target
다음 명령을 실행하여 다음에 필요한 대상(target)이 있는지 확인할 수 있습니다: sysinit.target. 명령의 구문은 동일합니다. 계속 진행하면서 다른 대상 유닛에 어떤 대상 유닛이 필요한지 확인하기 위해 명령을 계속 수정할 수 있습니다. 명령은 다음과 같습니다:
|
1 |
sudo systemctl show --property "Requires" sysinit.target | fmt -10 |
출력 결과에 다음에 필요한 유닛이 없다고 표시됩니다: sysinit.target. 다른 서비스와 대상이 요구(wanted)되는지 sysinit.target에서 다음 명령을 사용하여 확인할 수 있습니다:
|
1 |
sudo systemctl show --property "Wants" sysinit.target | fmt -10 |
출력 결과에는 다음에 의해 요구되는 서비스와 대상의 긴 목록이 표시됩니다: sysinit.target. 출력 결과의 일부는 아래에서 확인할 수 있습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Wants=systemd-tmpfiles-setup-dev.service systemd-binfmt.service systemd-journald.service rhel-loadmodules.service dev-hugepages.mount systemd-modules-load.service rhel-autorelabel-mark.service plymouth-read-write.service sys-fs-fuse-connections.mount systemd-machine-id-commit.service systemd-random-seed.service systemd-udevd.service systemd-sysctl.service plymouth-start.service rhel-autorelabel.service proc-sys-fs-binfmt_misc.automount local-fs.target rhel-import-state.service sys-kernel-config.mount dev-mqueue.mount kmod-static-nodes.service systemd-update-utmp.service |
system4를 통한 시스템 초기화 중에는 시스템이 하나의 대상에만 머물지 않습니다. 대신, 한 대상에서 다른 대상으로 이동하면서 의존적인 방식으로 서비스를 로드합니다.
3단계: 유닛 파일 검사
유닛 파일이 어떻게 생겼는지 살펴보겠습니다. 이 튜토리얼의 첫 번째 부분에서 MySQL 서비스 유닛 파일을 사용했으며, 여기서도 다시 사용할 것입니다. 하지만 다른 서비스 유닛 파일인 sshd 유닛 파일도 살펴볼 수 있습니다. 다음 명령을 입력하여 sshd 구성 파일을 엽니다:
|
1 |
sudo nano /etc/systemd/system/multi-user.target.wants/sshd.service |
아래는 파일의 줄을 보여주는 스크린샷입니다:

보시다시피 파일에 표시된 코드 블록 덕분에 필요할 때마다 쉽게 이해하고 수정할 수 있습니다. 아래는 이해해야 할 몇 가지 중요한 지시어입니다:
- After – After 절은 지정된 대상과 서비스가 로드된 후에만 서비스를 로드하도록 시스템에 지시합니다. 이 경우, SSHD 서비스는 네트워크 대상과 keygen 서비스가 로드된 후에 로드됩니다.
- Wants – Wants 절은 어떤 대상이 이 서비스를 원하는지 보여줍니다. 이 경우 ssh-keygen.service가 sshd.service를 원합니다. 그러나 sshd가 실패하거나 중단되더라도 ssh-keygen.service.
Ctrl + X를 눌러 편집기를 닫습니다.
4단계: 시스템 부팅 시 MySQL 서비스 시작 동작 테스트
이 섹션에서는 시스템 부팅 시 MySQL 서비스의 동작을 변경하고 테스트하는 방법을 보여줍니다. 이전 섹션에서 우리는 mysqld.service가 multi-user.target에 의해 요구되는 것을 보았습니다. 따라서 부팅 시 자동으로 시작됩니다.
다음 명령을 실행하여 서비스를 비활성화할 수 있습니다:
|
1 |
sudo systemctl disable mysqld.service |
명령을 실행하면 mysql 심볼릭 링크가 다음 디렉토리에서 제거되었음을 보여줍니다: /etc/systemd/system/multi-user.target.wants/ 디렉토리. 이를 테스트하려면 다음 명령을 실행하여 MySQL이 여전히 다음에 의해 요구되는지 테스트하십시오: multi-user.target:
|
1 |
sudo systemctl show --속성 "Wants" multi-user.target | fmt -10 | grep mysql |
명령어가 아무것도 반환하지 않습니다. 서버를 재부팅하고 MySQL 상태를 확인해 보면 실행 중이 아닐 것입니다. 즉, 부팅 시 자동 시작되지 않았음을 의미합니다.
이제 다음 명령어를 사용하여 서비스를 다시 활성화합니다:
|
1 |
sudo systemctl enable mysqld.service |
출력에 심볼릭 링크가 표시됩니다. 서버를 재부팅하면 MySQL이 자동으로 시작되어야 합니다. Systemd 서비스를 활성화하면 기본 대상(target)의 wants 디렉터리에 심볼릭 링크가 생성됩니다. Systemd 서비스를 비활성화하면 wants 디렉터리에서 심볼릭 링크가 제거됩니다.
5단계: 서비스 충돌 후 MySQL 서비스 시작 동작 테스트
기본적으로 MySQL 서비스는 충돌이 발생할 경우 자동으로 시작됩니다. MySQL용 Systemd 구성 파일에서 이 동작을 비활성화할 수 있습니다. 먼저 파일을 살펴보겠습니다. 다음 명령어를 입력하여 파일을 엽니다:
|
1 |
sudo nano /etc/systemd/system/multi-user.target.wants/mysqld.service |
아래 스크린샷은 출력 결과를 보여줍니다:

Restart 지시어의 값이 on-failure로 설정되어 있습니다. 이는 비정상적인 종료 코드, 타임아웃 또는 비정상적인 시그널이 발생한 후 MySQL 서비스가 재시작됨을 의미합니다. 아래는 man 페이지의 일부 재시작 매개변수를 보여주는 표입니다..
| 재시작 설정/종료 원인 | no | always | on-success | on-failure | on-abnormal | on-abort | on-watchdog |
| 정상 종료 코드 또는 시그널 | X | X | |||||
| 비정상 종료 코드 | X | X | |||||
| 비정상 시그널 | X | X | X | X | |||
| 타임아웃 | X | X | X | ||||
| 워치독 | X | X | X | X |
Systemd 유닛 파일에서 중요한 두 가지 지시어는 Restart 및 RestartSec입니다. 이 지시어들은 서비스의 충돌 동작을 제어합니다. Restart는 서비스가 언제 재시작되어야 하는지 지정하고, RestartSec는 충돌 후 재시작하기 전에 대기할 시간을 지정합니다. 재시작 동작을 비활성화하려면 다음과 같이 줄 시작 부분에 #을 추가하여 Restart 지시어를 주석 처리합니다:
|
1 |
# Restart=always |
이제 시스템 데몬을 다시 로드한 다음, mysqld 서비스를 다시 로드합니다:
|
1 2 |
sudo systemctl daemon-reload sudo systemctl restart mysqld.service |
다음으로, 다음 명령어를 실행하여 MySQL 서비스의 메인 PID를 찾습니다:
|
1 |
sudo systemctl status mysqld.service |

테스트에서의 메인 PID는 23809였습니다. 다음 명령어에서 사용할 수 있도록 본인의 PID를 기록해 두세요. kill -9 명령어를 사용하여 프로세스를 종료함으로써 충돌을 시뮬레이션합니다. 또한, 테스트에서 얻은 프로세스 번호로 변경하는 것을 잊지 마세요:
|
1 |
sudo kill -9 23809 |
MySQL 상태를 확인하는 명령어를 실행하면 활성 상태가 아니며 재시작에 실패했음을 확인할 수 있습니다:
|
1 |
sudo systemctl status mysqld.service |

Restart 지시어가 mysqld.service 구성 파일에서 주석 처리되어 있는 한 실패 상태로 유지됩니다. 이는 서비스가 중지되고 다시 시작되지 않는 충돌 상황을 에뮬레이트합니다.
서비스를 다시 활성화하려면 mysqld.service 구성 파일을 편집하여 Restart 지시어의 주석을 해제한 다음 저장하고 닫으면 됩니다. 이전과 마찬가지로 데몬을 다시 로드하고 서비스를 재시작합니다. 이렇게 하면 서비스가 초기 구성으로 돌아가며, 이제 충돌 후 자동으로 시작될 수 있습니다. 마지막으로, 충돌 후 서비스가 자동으로 시작되도록 구성하는 방법은 이것이 전부입니다. 충돌 후 서비스가 자동으로 시작되도록 구성하려면 서비스 유닛 파일의 Restart 지시어(원하는 경우 RestartSec 지시어도 추가 가능)를 [Service] 섹션 아래에 추가하기만 하면 됩니다.
결론
이 튜토리얼에서는 리눅스가 시작 중 또는 충돌 후에 서비스를 처리하는 방법에 대해 논의했습니다. 리눅스 시스템 초기화 프로세스를 이해하기 위해 리눅스가 사용하는 세 가지 init 시스템인 System V, Upstart, Systemd에 대해 알아보았습니다. 이들의 발전 과정과 시스템 재부팅 또는 충돌 후 서비스를 자동으로 시작하는 것과 관련하여 각 init 프로세스가 어떻게 작동하는지 살펴보았습니다.
init 데몬과 Linux 배포판 모두 시간이 흐르면서 계속 발전해 왔으므로, 사용 중인 Linux 배포판 버전을 확인하여 시스템이 기본적으로 어떤 init 데몬을 지원하는지 파악해 두시기 바랍니다.
Linux 네이티브 애플리케이션과 대부분의 서드파티 애플리케이션은 시스템 부팅 또는 충돌 후 이미 자동으로 시작되므로 사용자가 별도로 조치할 필요가 없습니다. 이 튜토리얼에서 다루는 지식은 자체 커스텀 서비스의 시작 및 재실행(respawn) 동작을 구성하거나, 지속적으로 충돌이 발생하는 서비스를 트러블슈팅할 때 매우 중요합니다.
즐거운 컴퓨팅 되세요!
댓글
아직 댓글이 없습니다. 첫 번째로 작성해 보세요.