"Trans:GentooX86Handbook2-4"의 두 판 사이의 차이

Gentoo Korea Wiki
둘러보기로 가기 검색하러 가기
(새 문서: == Init 스크립트 == === 런레벨 === ==== 시스템 부팅하기 ==== 시스템을 부팅하면 수많은 텍스트가 떠다닙니다. 더 자세히 들여다보면 여러분...)
 
 
(같은 사용자의 중간 판 38개는 보이지 않습니다)
1번째 줄: 1번째 줄:
== Init 스크립트 ==
+
== 초기화 스크립트 ==
  
 
=== 런레벨 ===
 
=== 런레벨 ===
11번째 줄: 11번째 줄:
 
마지막으로 모든 스크립트를 실행하고 나면, {{blue|init}} 에서 터미널(대부분의 경우 {{blue|Alt-F1}}, {{blue|Alt-F2}} 키로 숨겨놓은 가상 콘솔입니다)을 활성화하고 {{blue|agetty}}라고 하는 특별한 프로세스를 터미널과 붙입니다. 이 과정에서 {{blue|login}}을 실행하여 이들 터미널을 통해 로그온을 할 수 있는지 확인할 것입니다.
 
마지막으로 모든 스크립트를 실행하고 나면, {{blue|init}} 에서 터미널(대부분의 경우 {{blue|Alt-F1}}, {{blue|Alt-F2}} 키로 숨겨놓은 가상 콘솔입니다)을 활성화하고 {{blue|agetty}}라고 하는 특별한 프로세스를 터미널과 붙입니다. 이 과정에서 {{blue|login}}을 실행하여 이들 터미널을 통해 로그온을 할 수 있는지 확인할 것입니다.
  
==== Init 스크립트 ====
+
==== 초기화 스크립트 ====
 
여기서 {{blue|init}}는 /etc/init.d/에 있는 스크립트를 임의의 순서대로 실행하는 것이 아닙니다. 게다가 /etc/init.d에 있는 모든 스크립트를 실행하는 것도 아니며 실행하라고 지시한 스크립트만 실행합니다. 이는 /etc/runlevels를 확인하여 어떤 스크립트를 실행할 지 결정합니다.
 
여기서 {{blue|init}}는 /etc/init.d/에 있는 스크립트를 임의의 순서대로 실행하는 것이 아닙니다. 게다가 /etc/init.d에 있는 모든 스크립트를 실행하는 것도 아니며 실행하라고 지시한 스크립트만 실행합니다. 이는 /etc/runlevels를 확인하여 어떤 스크립트를 실행할 지 결정합니다.
  
29번째 줄: 29번째 줄:
 
이 줄은 시스템을 초기화 하는 {{blue|/sbin/rc sysinit}}을 실행해야 한다고 {{blue|init}}에 일러줍니다. /sbin/rc 스크립트는 초기화를 다루므로 {{blue|init}}이 더 이상의 일을 못하도록 여러분이 알려야 합니다. -- 이는 시스템이 초기화 작업을 하도록 다른 프로세스에 일임합니다.
 
이 줄은 시스템을 초기화 하는 {{blue|/sbin/rc sysinit}}을 실행해야 한다고 {{blue|init}}에 일러줍니다. /sbin/rc 스크립트는 초기화를 다루므로 {{blue|init}}이 더 이상의 일을 못하도록 여러분이 알려야 합니다. -- 이는 시스템이 초기화 작업을 하도록 다른 프로세스에 일임합니다.
  
두번째로, {{blue|init}}은 /etc/runlevels/boot에 심볼릭 링크를 걸어둔 모든 스크립트를 실행합니다. 이는 다음 줄에서 설정되더 있습니다.
+
두번째로, {{blue|init}}은 /etc/runlevels/boot에 심볼릭 링크를 걸어둔 모든 스크립트를 실행합니다. 이는 다음 줄에서 설정되어 있습니다.
 
{{Example|코드 예제 1.2: 시스템 초기화(계속)|rc::bootwait:/sbin/rc boot
 
{{Example|코드 예제 1.2: 시스템 초기화(계속)|rc::bootwait:/sbin/rc boot
 
}}
 
}}
  
 +
다시 말씀드리지만 {{blue|rc}} 스크립트는 필요한 작업을 수행합니다. 참고로 {{blue|rc}} (boot) 에 주어진 옵션은 이것이 사용하는 /etc/runlevels의 하위 디렉터리와 같습니다.
 +
 +
이제 {{blue|init}} 는 어떤 ''런레벨''을 실행해야 하는지 설정 파일을 확인합니다. 이를 결정하려고 /etc/inittab에서 다음 줄을 읽어 들입니다.
 +
 +
{{Example|코드 예제 1.3: initdefault 줄|id:3:initdefault:
 +
}}
 +
 +
이 경우 (대부분의 젠투 사용자들이 사용할 경우), ''런레벨'' id는 3입니다. 이 정보를 사용하여 {{blue|init}} 은 ''런레벨'' 3을 시작하기 위해 무엇을 실행해야 하는지 확인합니다.
 +
 +
{{Example|코드 예제 1.4: 런레벨 정의|l0:0:wait:/sbin/rc shutdown<br/>
 +
l1:S1:wait:/sbin/rc single<br/>
 +
l2:2:wait:/sbin/rc nonetwork<br/>
 +
l3:3:wait:/sbin/rc default<br/>
 +
l4:4:wait:/sbin/rc default<br/>
 +
l5:5:wait:/sbin/rc default<br/>
 +
l6:6:wait:/sbin/rc reboot
 +
}}
 +
 +
다시 말해 런레벨 3를 설정하는 줄에서 서비스를 시작하기 위해 (이 시점의 인자는 ''default''입니다) {{blue|rc}}스크립트를 사용합니다. 강조해서 말하지만 {{blue|rc}} 인자는 /etc/runlevels의 하위 디렉토리 이름과 같습니다.
 +
 +
{{blue|rc}} 실행이 끝나면 {{blue|init}}은 어떤 가상 콘솔을 활성화 할지, 각각의 콘솔에서 실행할 필요가 있는 명령이 어떤 것인지를 결정합니다.
 +
 +
{{Example|코드 예제 1.5: 가상 콘솔 정의|c1:12345:respawn:/sbin/agetty 38400 tty1 linux<br/>
 +
c2:12345:respawn:/sbin/agetty 38400 tty2 linux<br/>
 +
c3:12345:respawn:/sbin/agetty 38400 tty3 linux<br/>
 +
c4:12345:respawn:/sbin/agetty 38400 tty4 linux<br/>
 +
c5:12345:respawn:/sbin/agetty 38400 tty5 linux<br/>
 +
c6:12345:respawn:/sbin/agetty 38400 tty6 linux
 +
}}
 +
 +
==== 런레벨이란? ====
 +
 +
여러분은 {{blue|init}}가 어떤 ''런레벨''을 활성화 해야 할지 결정할 번호 매김 방식을 사용하는 것을 보았습니다. ''런레벨''은 여러분의 시스템에서 실행중이며 런레벨을 진입하거나 나갈 때 실행해야 하는 스크립트(런레벨 스크립트나 ''초기화 스크립트'')의 모음을 포함하고 있는 상태입니다.
 +
 +
젠투에서는 세가지의 내부 런레벨, 네가지의 사용자 정의 런레벨 즉, 일곱가지 런레벨을 정의했습니다. 내부 런레벨은 ''sysinit'', ''shutdown'', ''reboot''가 있고 이들 이름이 함축하는 일을 정확하게 수핵합니다. 시스템을 초기화 하고 시스템을 종료하며 시스템을 다시 시작합니다.
 +
 +
사용자 런레벨은 /etc/runlevels의 하위 디렉터리 boot, default, nonetwork, single과 연관됩니다. boot 런레벨은 모든 기타 런레벨에서 사용하는 전체 시스템에서 필요한 서비스를 시작합니다. 나머지 세가지 런레벨은 어떤 서비스를 시작하느냐에 따라 차이가 있습니다. default는 항상 실행할때 사용하고, nonetwork는 네트워크 연결이 필요하지 않을 때 사용하며, single은 시스템을 복구해야 할 필요가 있을 때 사용합니다.
 +
 +
==== 초기화 스크립트로 작업하기 ====
 +
 +
{{blue|rc}} 프로세스를 시작하는 스크립트를 ''초기화 스크립트''라고 부릅니다. /etc/init.d에 있는 각각의 스크립트는 다음 인자, ''start'', ''stop'', ''restart'', ''pause'', ''zap'', ''status'', ''ineed'', ''iuse'', ''needsme'', ''usesme'', ''broken''과 함께 실행할 수 있습니다.
 +
 +
서비스(와 관련 서비스들)를 시작, 중지, 다시 시작하려면 {{blue|start}}, {{blue|stop}}, {{blue|restart}}를 사용합니다.
 +
 +
{{Example|코드 예제 1.6: Postfix 시작하기|<nowiki># /etc/init.d/postfix start</nowiki>
 +
}}
 +
 +
{{Note|주어진 서비스에서 ''필요''한 요건은 중지된 상태나 재시작한 상태입니다. 다른 관련 서비스 (서비스를 ''사용''하지만 필요하지 않은) 는 건드리지 않은 상태로 남아있습니다.
 +
}}
 +
 +
서비스를 중단하고 싶지만 다른 관련 서비스는 그대로 두려면 {{blue|pause}} 인자를 사용할 수 있습니다.
 +
 +
{{Example|코드 예제 1.7: Postfix를 멈추지만 실행중인 관련 서비스는 유지하기|<nowiki># /etc/init.d/postfix pause</nowiki>
 +
}}
 +
 +
서비스의 상태(시작함, 중단함, 멈춤, 등)가 어떤지 보려면 {{blue|status}} 인자를 사용할 수 있습니다.
 +
 +
{{Example|코드 예제 1.8: Postfix 상태 정보|<nowiki># /etc/init.d/postfix status</nowiki>
 +
}}
 +
 +
상태 정보에서 서비스가 동작중이라고 알리고 있지만, 실제로 동작중이 아님을 알고 있을 경우 {{blue|zap}} 인자를 사용하여 상태 정보를 "중지됨"으로 되돌릴 수 있습니다.
 +
 +
{{Example|코드 예제 1.9: Postfix 상태 정보 되돌리기|<nowiki># /etc/init.d/postfix zap</nowiki>
 +
}}
 +
 +
또한 관련 서비스가 무엇인지 알아보려면 {{blue|iuse}}나 {{blue|ineed}}를 사용할 수 있습니다. {{blue|ineed}}를 사용하면 서비스가 올바른 기능을 다하는데 실제로 필요한 서비스를 볼 수 있습니다. 반면에 {{blue|iuse}}를 사용하면 서비스에서 사용할 수 있지만 올바른 동작을 하는데 필요하지는 않은 서비스를 보여줍니다.
 +
 +
{{Example|코드 예제 1.10: Postfix가 의존하는 모든 필요한 서비스 목록 요청하기|<nowiki># /etc/init.d/postfix ineed</nowiki>
 +
}}
 +
 +
이와 비슷하게 어떤 서비스를 필요로 하는지({{blue|needsme}}) 어떤 서비스를 사용할 수 있는지({{blue|usesme}}) 확인할 수 있습니다.
 +
 +
{{Example|코드 예제 1.11: Postfix에서 필요로 하는 모든 서비스 목록 요청하기|<nowiki># /etc/init.d/postfix needsme</nowiki>
 +
}}
 +
 +
마지막으로 서비스에서 필요로 하는 것중에 빠진 의존성이 무엇인지 확인할 수 있습니다.
 +
 +
{{Example|코드 예제 1.12: Postfix의 빠진 의존 목록 요청하기|<nowiki># /etc/init.d/postfix broken</nowiki>
 +
}}
  
 
=== rc-update로 작업하기 ===
 
=== rc-update로 작업하기 ===
 +
==== rc-update란? ====
 +
 +
젠투의 init 시스템은 어떤 서비스를 먼저 시작해야 할지 결정하기 위해 의존 트리를 사용합니다. 사용자 여러분들이 이 지루한 작업을 하지 않도록 런레벨과 초기화 스크립트 관리를 쉽게 하는 도구를 만들었습니다.
 +
 +
{{blue|rc-update}}를 사용하면 초기화 스크립트를 런레벨에서 추가하고 제거할 수 있습니다. {{blue|rc-update}} 도구는 그 다음 의존 트리를 다시 만들기 위해 {{blue|depscan.sh}}를 자동으로 요청할 것입니다.
  
 +
==== 서비스 추가하고 제거하기 ====
 +
여러분은 이미 젠투 설치과정에서 "default" 런레벨에 초기화 스크립트를 추가했습니다. 그 때 여러분은 "default"가 왜 있는지에 대한 실마리를 눈치채지 못하셨겠지만 이제는 알아차리셨을겁니다. {{blue|rc-update}}스크립트는 두번째 인자로서 ''add'', ''del'', ''show'' 동작 중 하나를 필요로 합니다.
 +
 +
초기화 스크립트를 추가하거나 제거하려면 {{blue|rc-update}} 스크립트에 {{blue|add}}나 {{blue|del}} 인자를 추가하고, 초기화 스크립트 이름과 런레벨을 제시하시면 됩니다. 예를 들자면 다음과 같습니다.
 +
 +
{{Example|코드 예제 2.1: default 런레벨에서 Postfix 제거하기|<nowiki># rc-update del postfix default</nowiki>
 +
}}
 +
 +
{{blue|rc-update -v show}} 명령은 사용할 수 있는 초기화 스크립트와 실행할 런레벨의 목록을 보여줄 것입니다.
 +
 +
{{Example|코드 예제 2.2: 초기화 스크립트 정보 받기|<nowiki># rc-update -v show</nowiki>
 +
}}
 +
 +
활성화 한 초기화 스크립트와 런레벨만을 보려면 ({{blue|-v}}를 뺀) {{blue|rc-update show}}로 실행하실 수 있습니다.
  
 
=== 서비스 설정하기 ===
 
=== 서비스 설정하기 ===
 +
==== 왜 추가 설정이 필요한가? ====
 +
 +
초기화 스크립트는 조금 복잡할 수 있습니다. 때문에 오류에 취약하게 만들 수가 있어 사용자가 초기화 스크립트를 올바르게 하는데 썩 바람직하진 않습니다. 그러나 서비스를 설정할 수 있는 방법에 있어서는 중요합니다. 예를 들어 여러분이 서비스 자체에 더 많은 옵션을 주고 싶어할 수도 있습니다.
  
=== Init 스크립트 작성하기 ===
+
두번째 이유로는 초기화 스크립트의 외부 설정을 보유하려면, 바꾼 설정을 되돌릴 수 없다는 두려움을 없애고 초기화 스크립트를 업데이트할 수 있어야 하기 때문입니다.
 +
 
 +
==== /etc/conf.d 디렉터리 ====
 +
 
 +
젠투에서는 서비스를 설정하는 쉬운 방법을 제공합니다: 모든 초기화 스크립트는 /etc/conf.d 에 있는 파일로 설정할 수 있습니다. 예를 들어 (/etc/init.d/apache2라고 하는) apache2 초기화 스크립트는 Apache 2서버를 시작할 때 주고 싶은 옵션을 넣을 수 있는 /etc/conf.d/apache2 라고 하는 설정 파일을 지니고 있습니다.
 +
 
 +
{{Example|코드 예제 3.1: /etc/conf.d/apache2에 정의한 변수|<nowiki>APACHE2_OPTS="-D PHP5"</nowiki>
 +
}}
 +
 
 +
이런 설정 파일에는 변수를 포함하며 서비스를 쉽게 설정할 수 있게 하는 단독 변수(/etc/portage.make.conf와 같은)도 포함합니다. 이를 통해 변수에 대한 더 자세한 정보를 (주석을 통해) 제공해줄 수 있습니다.
 +
 
 +
=== 초기화 스크립트 작성하기 ===
 +
==== 이걸 꼭 해야 하나요? ====
 +
 
 +
아닙니다. 초기화 스크립트 작성은 보통 젠투가 모든 제공하는 서비스에 대해 준비된 초기화 스크립트를 제공하는 만큼 필요하지 않습니다 그러나 포티지를 사용하지 않는 서비스를 설치할 경우가 있는데, 이 때에는 초기화 스크립트를 거의 만들 필요가 있을 것입니다.
 +
 
 +
젠투용으로 확실하게 작성한 것이 아니라면 서비스에서 제공하는 init 스크립드를 사용하지 마십시오. 젠투의 초기화 스크립트는 다른 배포판에서 사용하는 초기화 스크립트와 호환되지 않습니다!
 +
 
 +
==== 배치 ====
 +
 
 +
초기화 스크립트의 기본 배치는 아래와 같습니다.
 +
 
 +
{{Example|코드 예제 4.1: 초기화 스크립트의 기본 배치|<nowiki>#!/sbin/runscript</nowiki><br/>
 +
<br/>
 +
depend() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;{{red|(의존성 정보)}}<br/>
 +
}<br/>
 +
<br/>
 +
start() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;{{red|(서비스를 시작하는데 필요한 명령)}}<br/>
 +
}<br/>
 +
<br/>
 +
stop() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;{{red|(서비스를 멈추는데 필요한 명령)}}<br/>
 +
}
 +
}}
 +
 
 +
어떤 초기화 스크립트든지 {{blue|start()}} 함수의 정의가 ''필요합니다''. 다른 모든 부분은 부가적입니다.
 +
 
 +
==== 의존성 ====
 +
초기화 스크립트를 시작하거나 연달아 실행하는데 영향을 주도록 설정할 수 있는 의존성향 유사 설정은 두 가지가 있는데 {{blue|use}}와 {{blue|need}}입니다. 이들 다음으로는 {{blue|before}}와 {{blue|after}}라고 하는 두가지 방식의 순서 영향 메소드가 있습니다. 마지막 두가지 각각의 요소는 의존성을 지니지 않습니다. 선택한 초기화 스크립트가 시작하도록 계획되지 못했(거나 시작에 실패했)을경우 본래 초기화 스크립트의 실행을 실패하도록 하지 않습니다.
 +
 
 +
* {{blue|use}} 설정은 선택한 스크립트의 기능 제공을 이 스크립트가 ''사용''하지만 직접적인 의존성을 지니지 않도록 init 시스템에 알려줍니다. 좋은 본보기로 {{blue|use logger}}나 {{blue|use dns}}를 들 수 있습니다. 이 서비스가 존재한다면 사용하기 좋은 상태로 두겠지만 로거나 DNS 서버가 없다 하더라도 서비스는 여전히 동작할 것입니다. 서비스가 존재한다면 {{blue|use}}에 있는 스크립트보다 먼저 서비스를 시작할 것입니다.
 +
 
 +
* {{blue|need}} 설정은 강한 의존성입니다. 이는 다른 스크립트를 {{blue|need}}(필요)로 하는 스크립트는 명시한 다른 스크립트를 성공적으로 실행하기 전에는 시작하지 않음을 의미합니다. 또한 언급한 다른 스크립트를 재시작하면 마찬가지로 해당 스크립트도 재시작 할 것입니다.
 +
 
 +
* {{blue|before}}를 사용하면, 선택한 요소가 init 레벨의 일부''일 경우'' 선택한 요소를 실행하기 전에 주어진 스크립트를 실행합니다. 그래서 {{blue|before alsasound}}를 정의한 xdm init스크립트는 alsasound 스크립트를 실행하기 전에 시작하겠지만, alsasound가 동일한 init 레벨에서 실행하도록 계획되었을 경우에만 해당합니다. alsasound를 시작하도록 계획하지 않았다면, 일부 설정은 효력이 없을 것이며, 스크립트 자신이 가장 적당하다고 여기는 시점에 xdm을 실행할 것입니다.
 +
 
 +
* 이와 마찬가지로 {{blue|after}}를 사용하면, 선택한 요소가 init 레벨의 일부''일 경우'' 선택한 요소를 실행한 다음에 주어진 스크립트를 실행합니다. 아니면 설정이 효력이 없을 것이며, 적당하다고 여기는 시점에 init 시스템이 스크립트를 실행할 것입니다.
 +
 
 +
위에서 분명히 해야 할 것은 {{blue|need}}는 스크립트를 시작하든 아니든 영향을 주는 "진성" 의존성 설정이라는 것입니다. 다른 모든 요소들은 명령 스크립트를 실행(할 수 있거나 해야)할 때 init 시스템에 대해 분명하게 가리킬 뿐입니다.
 +
 
 +
이제 여러분이 젠투에서 사용할 수 있는 수많은 초기화 스크립트를 보았다면 없는 초기화 스크립트에 대해 의존성을 가진 것을 주목하실 것입니다. 이것들을 ''가상요소''라고 부릅니다.
 +
 
 +
''가상'' 의존성은 서비스를 제공하는 의존성이지만 서비스가 유일하게 제공해주는 것은 아닙니다. 여러분의 초기화 스크립트는 시스템 로거에 의존할 수 있는데 수많은 시스템 로거가 존재합니다(metalogd, syslog-ng, sysklogd, ...). 여러분은 각각의 모든 단일 요소를 {{blue|need}}에 넣을 수 없지만 (설치하고 실행중인 모든 시스템 로거를 갖춘 합리적인 시스템은 없습니다), 이 모든 서비스들이 가상 의존성을 {{blue|provide}}(제공)하는지 확인합니다.
 +
 
 +
이제 Postfix 서비스에 대한 의존성 정보를 보도록 하겠습니다.
 +
 
 +
{{Example|코드 예제 4.2: Postfix의 의존 정보|depend() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;need net<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;use logger dns<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;provide mta<br/>
 +
}
 +
}}
 +
 
 +
여러분이 보시는 바와 같이 Postfix서비스에 다음과 같은 것들이 있습니다.
 +
 
 +
* (가상){{blue|net}} 의존 요소를 필요로 합니다 (/etc/init.d/net.eth0와 같은 요소로 제공합니다)
 +
* (가상){{blue|logger}} 의존 요소를 사용합니다 (/etc/init.d/syslog-ng와 같은 요소로 제공합니다)
 +
* (가상){{blue|dns}} 의존 요소를 사용합니다 (/etc/init.d/named와 같은 요소로 제공합니다)
 +
* (가상){{blue|mta}} 의존 요소를 제공합니다 (모든 메일 서버의 공통요소 입니다)
 +
 
 +
==== 순서 제어하기 ====
 +
 
 +
이전 장에서 설명한 바와 같이 스크립트를 시작(하고 중지)하기 위한 순서를 어떻게 할 것인지 init 시스템에 알려줄 수 있습니다. 이 순서는 {{blue|use}}와 {{blue|need}} 의존 설정을 통해 다룰 뿐만 아니라 {{blue|before}}와 {{blue|after}}로도 순서 설정을 다루기도 합니다. 역시 앞에서 미리 설명한 것과 마찬가지로 초기화 스크립트 중 하나의 예제로서 Portmap 서비스를 살펴보도록 하겠습니다.
 +
 
 +
{{Example|코드 예제 4.3: Portmap 서비스의 depend() 함수|depend() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;need net<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;before inetd<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;before xinetd<br/>
 +
}
 +
}}
 +
 
 +
비록 별로 도움이 되는 이야기는 아니겠지만, 동일한 런레벨의 모든 서비스를 포함하려면 "*"를 사용하실 수도 있습니다.
 +
 
 +
{{Example|코드 예제 4.4: 런레벨의 첫번째 스크립트로 초기화 스크립트를 실행하기|depend() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;before *<br/>
 +
}
 +
}}
 +
 
 +
서비스가 반드시 지역 디스크에 기록을 해야 한다면 {{blue|localmount}}가 필요합니다. pid 파일 같은 것을 /var/run에 두었다면 {{blue|bootmisc}} 다음 실행해야 합니다.
 +
 
 +
{{Example|코드 예제 4.5: depend() 함수 예제|depend() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;need localmount<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;after bootmisc<br/>
 +
}
 +
}}
 +
 
 +
==== 표준 함수 ====
 +
 
 +
{{blue|depend()}} 함수 다음에, {{blue|start()}} 함수의 정의가 필요합니다. 이 함수에는 서비스를 시작하는데 필요한 모든 명령어를 담고 있습니다. 사용자에게 무슨 일이 일어나고 있는지를 알리기 위해 {{blue|ebegin}}과 {{blue|eend}}함수를 사용하는 것이 좋습니다.
 +
 
 +
{{Example|코드 예제 4.6: start() 함수 예제|start() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>if [ "${RC_CMD}" = "restart" ];</nowiki><br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;then<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{red|<nowiki># 다시 시작할 때 stop, start 할 때보다 더 실행해야 할 명령</nowiki><br/>}}
 +
&nbsp;&nbsp;&nbsp;&nbsp;fi<br/>
 +
<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;ebegin "Starting my_service"<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;start-stop-daemon --start --exec /path/to/my_service \<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--pidfile /path/to/my_pidfile<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;eend $?<br/>
 +
}
 +
}}
 +
 
 +
{{blue|--exec}} 와 {{blue|--pidfile}} start와 stop 함수에서 사용합니다. 서비스에서 pidfile을 만들지 못할 경우, 제대로 동작하는지 테스트 하는 겸에 되도록이면 {{blue|--make-pidfile}}를 사용합니다. 그렇지 않으면 pidfile를 사용하지 않습니다. 또한 {{blue|start-stop-daemon}}의 옵션으로 {{blue|--quiet}}를 추가할 수 있지만 서비스에서 너무 많은 메시지를 뿌려대지 않은 이상 추천하는 방법은 아닙니다. {{blue|--quiet}}를 사용하면 서비스 시작에 실패했을 때 디버깅 내용을 못보게 될 수도 있습니다.
 +
 
 +
위의 예제에서 사용한 눈에 보이는 설정으로서 {{blue|RC_CMD}}변수의 내용을 확인하는 것입니다. 이전 초기화 스크립트 시스템과는 다르게 새로운 {{blue|openrc}} 시스템에서는 스크립트 기반 다시 시작 기능을 사용하지 못합니다. 대신 함수({{blue|start()}}나 {{blue|stop()}})가 다시 시작 과정의 일부로 호출 되었든지 아니든지간에 {{blue|RC_CMD}} 변수의 내용을 스크립트에서 확인할 필요가 있습니다.
 +
 
 +
{{Note|{{blue|--exec}}가 실제로 서비스를 실행하는 쉘 스크립트를 실행하고 나가는 것이 아니라 서비스를 호출하는지 확인하십시오. 어떤 초기화 스크립트를 실행할지 고려하는 것입니다.}}
 +
 
 +
{{blue|start()}}함수에 대한 더 많은 예제를 보시려면 /etc/init.d 디렉터리에 있는 초기화 스크립트의 소스코드를 보시기 바랍니다.
 +
 
 +
여러분이 정의할 수 있는 또다른 함수로는 {{blue|stop()}}이 있습니다. 이 함수를 꼭 정의할 필요는 없습니다! init 시스템은 여러분이 {{blue|start-stop-daemon}}을 사용한다면 자체적으로 내용을 채울 정도로 충분히 똑똑합니다.
 +
 
 +
{{blue|stop()}}함수의 예제는 다음과 같습니다.
 +
 
 +
{{Example|코드 예제 4.7: stop() 함수 예제|stop() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;ebegin "Stopping my_service"<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;start-stop-daemon --stop --exec /path/to/my_service \<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--pidfile /path/to/my_pidfile<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;eend $?<br/>
 +
}
 +
}}
 +
 
 +
서비스에서 (bash, python, perl과 같은) 다른 스크립트를 실행하고 나중에 이 스크립트의 이름을 ({{blue|foo.py}}를 {{blue|foo}}로) 바꾼다면 {{blue|start-stop-daemon}}에 {{blue|--name}}을 추가할 필요가 있습니다. 여러분의 스크립트를 지정할 때 바꿀 이름으로 반드시 지정해야 합니다. 이 경우 서비스에서는 {{blue|foo}}로 이름을 바꾸는 {{blue|foo.py}}를 시작합니다.
 +
 
 +
{{Example|코드 예제 4.8: foo 스크립트를 시작하는 서비스|start() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;ebegin "Starting my_script"<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;start-stop-daemon --start --exec /path/to/my_script \<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--pidfile /path/to/my_pidfile --name foo<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;eend $?<br/>
 +
}
 +
}}
 +
 
 +
여러분이 더 많은 내용을 필요로 할 것을 대비해 {{blue|start-stop-daemon}}에 대한 뛰어난 man 페이지를 보유하고 있습니다.
 +
 
 +
{{Example|코드 예제 4.9: start-stop-daemon에 대한 man 페이지 가져오기|$ man start-stop-daemon
 +
}}
 +
 
 +
젠투의 초기화 스크립트 문법은 본 어게인 쉘(bash) 문법을 기반으로 하기 때문에 여러분은 자유롭게 초기화 스크립트에 bash 호환 문법 스크립트를 사용할 수 있습니다. 다만, POSIX 호환 문법으로 초기화 스크립트를 작성하시고 싶을지도 모릅니다. 앞으로의 초기화 스크립트 시스템에서는 bash 말고도 다른 쉘에 대해 /bin/sh를 심볼릭 링크로 걸수 있도록 할 것입니다. 이렇게 하면 bash 고유 기능에 의존하는 초기화 스크립트가 이들 설정을 깰 것입니다.
 +
 
 +
==== 사용자정의 옵션 추가하기 ====
 +
 
 +
여러분의 초기화 스크립트에 앞서 우리가 언급했던것보다 더 맣은 옵션을 지원하도록 하려면 {{blue|extra_commands}} 변수에 옵션을 추가하고, 옵션 이름과 동일한 함수를 만들어야 합니다. 실례로 {{blue|restartdelay}}라고 하는 옵션을 지원하게 해보겠습니다.
 +
 
 +
{{Example|코드 예제 4.10: restartdelay 옵션 지원하기|<nowiki>extra_commands="restartdelay"</nowiki><br/>
 +
<br/>
 +
restartdelay() {<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;stop<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;sleep 3&nbsp;&nbsp;&nbsp;&nbsp;{{red|# 다시 시작하기 전에 3초를 기다립니다}}<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;start<br/>
 +
}
 +
}}
 +
 
 +
{{Important| {{blue|restart()}} 함수는 openrc에서 덮어쓸 수 없습니다! }}
 +
 
 +
==== 서비스 설정 변수 ====
 +
 
 +
여러분은 /etc/conf.d의 설정 파일을 지원하기 위한 그 어떤 설정도 필요 없습니다. 초기화 스크립트를 실행하면 다음 파일을 자동으로 참조합니다. (예: 사용할 수 있는 변수)
 +
 
 +
* /etc/conf.d/<your init script>
 +
* /etc/conf.d/basic
 +
* /etc/rc.conf
 +
 
 +
또한 여러분의 초기화 스크립트에 ({{blue|net}}과 같은)가상 의존성을 지원제공하면, (/etc/conf.d/net과 같은) 의존성과 관련한 파일도 참조할 것입니다.
  
 
=== 런레벨 동작 바꾸기 ===
 
=== 런레벨 동작 바꾸기 ===
 +
==== 이걸로 이득 볼 사람이 있을까요? ====
 +
많은 랩톱 사용자들은 이런 상황을 알고 있을 것입니다. 밖에서 (사용할 수 있는 네트워크가 없을 때) {{blue|net.eth0}}를 시작하고 싶지 않은 반면에 집에서는 {{blue|net.eth0}}를 시작하려 할 것입니다. 젠투에서는 여러분이 실행할 런레벨 동작을 바꿀 수 있습니다.
 +
 +
예를 들어 다른 초기화 스크립트를 할당하여 부트할 수 있는 두번째 "default" 런레벨을 만들 수 있습니다. 그렇게 하고 나면 여러분이 사용하려는 기본 런레벨이 무엇인지 부팅 시간에 선택할 수 있습니다.
 +
 +
==== 소프트레벨 사용하기 ====
 +
제일 먼저, 두번째 "default" 런레벨에 대한 런레벨 디렉터리를 만듭니다. 다음의 예제에서 offline 런레벨을 만들어보도록 하겠습니다.
 +
 +
{{Example|코드 예제 5.1: 런레벨 디렉터리 만들기|<nowiki># mkdir /etc/runlevels/offline</nowiki>
 +
}}
 +
 +
다음 새로이 만든 런레벨에 필요한 초기화 스크립트를 추가합니다. 예를 들어 현재 {{blue|default}}런레벨에서 {{blue|net.eth0}}를 제외한 나머지 복사본을 정확하게 가지려면 다음과 같이 실행합니다.
 +
 +
{{Example|코드 예제 5.2: 필요한 초기화 스크립트 추가하기|{{red|(default 런레벨에서 offline 런레벨로 모든 서비스 복사)}}<br/>
 +
<nowiki># cd /etc/runlevels/default</nowiki><br/>
 +
<nowiki># for service in *; do rc-update add $service offline; done</nowiki><br/>
 +
{{red|(offline 런레벨에서 원하지 않는 서비스 제거)}}<br/>
 +
<nowiki># rc-update del net.eth0 offline</nowiki><br/>
 +
{{red|(offline 런레벨에서 활성화된 서비스 표시)}}<br/>
 +
<nowiki># rc-update show offline</nowiki><br/>
 +
{{red|(일부 본보기 출력)}}<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>acpid | offline</nowiki><br/>
 +
&nbsp;&nbsp;<nowiki>domainname | offline</nowiki><br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>local | offline</nowiki><br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>net.eth0 |</nowiki>
 +
}}
 +
 +
{{blue|net.eth0}}을 offline 런레벨에서 제거했지만서도, {{blue|udev}}가 아마 감지한 장치를 시작하고 적당한 서비스와 ''핫 플러그''라는 기능을 실행하려 들 것입니다. 기본적으로 젠투는 핫 플러그를 활성화 하지 않습니다.
 +
 +
핫 플러그 기능을 활성화 하지만 선택한 스크립트 모음에 한정하려면, /etc/rc.conf의 {{blue|rc_hotplug}} 변수를 사용하십시오.
 +
 +
{{Example|코드 예제 5.3: /etc/rc.conf에서 장치 초기화 서비스 비활성화 하기|{{red|<nowiki># Allow net.wlan as well as any other service, except those matching net.*</nowiki>}}<br/>
 +
{{red|<nowiki># to be hotplugged</nowiki>}}<br/>
 +
<nowiki>rc_hotplug="net.wlan !net.*"</nowiki>
 +
}}
 +
 +
{{Note|장치 초기화 서비스에 대한 자세한 내용을 보시려면 /etc/rc.conf의 주석을 참고하시기 바랍니다.}}
 +
 +
이제 부트로더 설정을 편집하고 {{blue|offline}} 런레벨에 대한 새로운 엔트리를 추가합니다. 예를 들어 /etc/grub/grub.conf에 다음과 같이 입력합니다.
 +
 +
{{Example|코드 예제 4.3: offline 런레벨에 대한 항목 추가하기|title Gentoo Linux Offline Usage<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;root (hd0,0)<br/>
 +
&nbsp;&nbsp;&nbsp;&nbsp;kernel (hd0,0)/kernel-2.4.25 <nowiki>root=/dev/hda3</nowiki> {{blue|<nowiki>softlevel=offline</nowiki>}}
 +
}}
 +
 +
보시죠. 다 끝났죠? 시스템을 부팅하고 부팅할 때 새로운 항목을 선택하면 {{blue|offline}} 런레벨을 {{blue|default}} 대신 사용할 것입니다.
 +
 +
==== 부트레벨 사용하기 ====
 +
{{blue|bootlevel}}을 사용하는 것은 {{blue|softlevel}}과 완전히 유사합니다. 유일한 차이점이라면 두번째 "default" 런레벨 대신에 두번째 "boot" 런레벨을 정의하는 것입니다.
 +
 +
[[Category:GentooTrans]]

2013년 3월 27일 (수) 20:28 기준 최신판

초기화 스크립트

런레벨

시스템 부팅하기

시스템을 부팅하면 수많은 텍스트가 떠다닙니다. 더 자세히 들여다보면 여러분이 다시 부팅할 때마다 이 텍스트가 같은 내용이 항상 나오는 것을 보실 수 있습니다. 이 동작의 순서를 부트 시퀀스라고 하며, (더 혹은 덜) 정적으로 정의합니다.

먼저 부트로더는 CPU한테 커널을 실행하라고 알린 다음에 부트로더 설정에 지정되어 있는 커널 이미지를 메모리에 불러올 것입니다. 커널을 불러와서 실행하면 모든 커널 관련 구조를 초기화 하고 init 과정을 시작할 것입니다.

이 프로세스는 (/etc/fstab에 지정한) 모든 파일 시스템을 마운트 했는지 사용할 준비가 되었는지를 확인합니다. 그 다음 시스템을 성공적으로 부팅하기 위해 필요한 시작할 서비스인, /etc/init.d에 위치한 많은 스크립트를 실행합니다.

마지막으로 모든 스크립트를 실행하고 나면, init 에서 터미널(대부분의 경우 Alt-F1, Alt-F2 키로 숨겨놓은 가상 콘솔입니다)을 활성화하고 agetty라고 하는 특별한 프로세스를 터미널과 붙입니다. 이 과정에서 login을 실행하여 이들 터미널을 통해 로그온을 할 수 있는지 확인할 것입니다.

초기화 스크립트

여기서 init는 /etc/init.d/에 있는 스크립트를 임의의 순서대로 실행하는 것이 아닙니다. 게다가 /etc/init.d에 있는 모든 스크립트를 실행하는 것도 아니며 실행하라고 지시한 스크립트만 실행합니다. 이는 /etc/runlevels를 확인하여 어떤 스크립트를 실행할 지 결정합니다.

먼저 init는 /etc/runlevels/boot에 있는 심볼릭 링크가 되어 있는 /etc/init.d/의 모든 스크립트를 실행합니다. 보통 철자순으로 스크립트를 실행하겠지만 어떤 스크립트의 경우 이들 스크립트를 실행하기 전에 다른 스크립트를 먼저 실행해야 한다고 시스템에 일러주는 의존성 정보를 가지고 있습니다.

/etc/runlevels/boot가 참조하는 스크립트를 실행하고 나면 init는 /etc/runlevels/default에 심볼릭 링크되어 있는 스크립트의 실행을 계속합니다. 다시 한 번 말씀드리지만, 어떤 스크립트를 먼저 실행할 지는 유효한 시작 순서를 제공하도록 순서를 바꾸는 의존성 정보를 가지고 있지 않는 한 철자순서를 사용하여 결정할 것입니다.

동작 방식

물론 init 에서 모든 사항을 자체적으로 결정하지 못합니다. 어떤 동작을 취해야 할지 지적하는 설정 파일이 필요합니다. 이 설정 파일은 /etc/inittab입니다.

우리가 적은대로 부팅 순서를 기억한다면, 여러분이 기억하기로는 init에서 처음 하는 동작은 모든 파일 시스템을 마운트 하는 것입니다. 이는 /etc/inittab의 다음 줄에 설정되어 있습니다.


코드 예제 1.1:/etc/inittab에 있는 시스템 초기화 줄
si::sysinit:/sbin/rc sysinit


이 줄은 시스템을 초기화 하는 /sbin/rc sysinit을 실행해야 한다고 init에 일러줍니다. /sbin/rc 스크립트는 초기화를 다루므로 init이 더 이상의 일을 못하도록 여러분이 알려야 합니다. -- 이는 시스템이 초기화 작업을 하도록 다른 프로세스에 일임합니다.

두번째로, init은 /etc/runlevels/boot에 심볼릭 링크를 걸어둔 모든 스크립트를 실행합니다. 이는 다음 줄에서 설정되어 있습니다.


코드 예제 1.2: 시스템 초기화(계속)
rc::bootwait:/sbin/rc boot


다시 말씀드리지만 rc 스크립트는 필요한 작업을 수행합니다. 참고로 rc (boot) 에 주어진 옵션은 이것이 사용하는 /etc/runlevels의 하위 디렉터리와 같습니다.

이제 init 는 어떤 런레벨을 실행해야 하는지 설정 파일을 확인합니다. 이를 결정하려고 /etc/inittab에서 다음 줄을 읽어 들입니다.


코드 예제 1.3: initdefault 줄
id:3:initdefault:


이 경우 (대부분의 젠투 사용자들이 사용할 경우), 런레벨 id는 3입니다. 이 정보를 사용하여 init런레벨 3을 시작하기 위해 무엇을 실행해야 하는지 확인합니다.


코드 예제 1.4: 런레벨 정의
l0:0:wait:/sbin/rc shutdown

l1:S1:wait:/sbin/rc single
l2:2:wait:/sbin/rc nonetwork
l3:3:wait:/sbin/rc default
l4:4:wait:/sbin/rc default
l5:5:wait:/sbin/rc default
l6:6:wait:/sbin/rc reboot


다시 말해 런레벨 3를 설정하는 줄에서 서비스를 시작하기 위해 (이 시점의 인자는 default입니다) rc스크립트를 사용합니다. 강조해서 말하지만 rc 인자는 /etc/runlevels의 하위 디렉토리 이름과 같습니다.

rc 실행이 끝나면 init은 어떤 가상 콘솔을 활성화 할지, 각각의 콘솔에서 실행할 필요가 있는 명령이 어떤 것인지를 결정합니다.


코드 예제 1.5: 가상 콘솔 정의
c1:12345:respawn:/sbin/agetty 38400 tty1 linux

c2:12345:respawn:/sbin/agetty 38400 tty2 linux
c3:12345:respawn:/sbin/agetty 38400 tty3 linux
c4:12345:respawn:/sbin/agetty 38400 tty4 linux
c5:12345:respawn:/sbin/agetty 38400 tty5 linux
c6:12345:respawn:/sbin/agetty 38400 tty6 linux


런레벨이란?

여러분은 init가 어떤 런레벨을 활성화 해야 할지 결정할 번호 매김 방식을 사용하는 것을 보았습니다. 런레벨은 여러분의 시스템에서 실행중이며 런레벨을 진입하거나 나갈 때 실행해야 하는 스크립트(런레벨 스크립트나 초기화 스크립트)의 모음을 포함하고 있는 상태입니다.

젠투에서는 세가지의 내부 런레벨, 네가지의 사용자 정의 런레벨 즉, 일곱가지 런레벨을 정의했습니다. 내부 런레벨은 sysinit, shutdown, reboot가 있고 이들 이름이 함축하는 일을 정확하게 수핵합니다. 시스템을 초기화 하고 시스템을 종료하며 시스템을 다시 시작합니다.

사용자 런레벨은 /etc/runlevels의 하위 디렉터리 boot, default, nonetwork, single과 연관됩니다. boot 런레벨은 모든 기타 런레벨에서 사용하는 전체 시스템에서 필요한 서비스를 시작합니다. 나머지 세가지 런레벨은 어떤 서비스를 시작하느냐에 따라 차이가 있습니다. default는 항상 실행할때 사용하고, nonetwork는 네트워크 연결이 필요하지 않을 때 사용하며, single은 시스템을 복구해야 할 필요가 있을 때 사용합니다.

초기화 스크립트로 작업하기

rc 프로세스를 시작하는 스크립트를 초기화 스크립트라고 부릅니다. /etc/init.d에 있는 각각의 스크립트는 다음 인자, start, stop, restart, pause, zap, status, ineed, iuse, needsme, usesme, broken과 함께 실행할 수 있습니다.

서비스(와 관련 서비스들)를 시작, 중지, 다시 시작하려면 start, stop, restart를 사용합니다.


코드 예제 1.6: Postfix 시작하기
# /etc/init.d/postfix start



참고: 주어진 서비스에서 필요한 요건은 중지된 상태나 재시작한 상태입니다. 다른 관련 서비스 (서비스를 사용하지만 필요하지 않은) 는 건드리지 않은 상태로 남아있습니다.


서비스를 중단하고 싶지만 다른 관련 서비스는 그대로 두려면 pause 인자를 사용할 수 있습니다.


코드 예제 1.7: Postfix를 멈추지만 실행중인 관련 서비스는 유지하기
# /etc/init.d/postfix pause


서비스의 상태(시작함, 중단함, 멈춤, 등)가 어떤지 보려면 status 인자를 사용할 수 있습니다.


코드 예제 1.8: Postfix 상태 정보
# /etc/init.d/postfix status


상태 정보에서 서비스가 동작중이라고 알리고 있지만, 실제로 동작중이 아님을 알고 있을 경우 zap 인자를 사용하여 상태 정보를 "중지됨"으로 되돌릴 수 있습니다.


코드 예제 1.9: Postfix 상태 정보 되돌리기
# /etc/init.d/postfix zap


또한 관련 서비스가 무엇인지 알아보려면 iuseineed를 사용할 수 있습니다. ineed를 사용하면 서비스가 올바른 기능을 다하는데 실제로 필요한 서비스를 볼 수 있습니다. 반면에 iuse를 사용하면 서비스에서 사용할 수 있지만 올바른 동작을 하는데 필요하지는 않은 서비스를 보여줍니다.


코드 예제 1.10: Postfix가 의존하는 모든 필요한 서비스 목록 요청하기
# /etc/init.d/postfix ineed


이와 비슷하게 어떤 서비스를 필요로 하는지(needsme) 어떤 서비스를 사용할 수 있는지(usesme) 확인할 수 있습니다.


코드 예제 1.11: Postfix에서 필요로 하는 모든 서비스 목록 요청하기
# /etc/init.d/postfix needsme


마지막으로 서비스에서 필요로 하는 것중에 빠진 의존성이 무엇인지 확인할 수 있습니다.


코드 예제 1.12: Postfix의 빠진 의존 목록 요청하기
# /etc/init.d/postfix broken


rc-update로 작업하기

rc-update란?

젠투의 init 시스템은 어떤 서비스를 먼저 시작해야 할지 결정하기 위해 의존 트리를 사용합니다. 사용자 여러분들이 이 지루한 작업을 하지 않도록 런레벨과 초기화 스크립트 관리를 쉽게 하는 도구를 만들었습니다.

rc-update를 사용하면 초기화 스크립트를 런레벨에서 추가하고 제거할 수 있습니다. rc-update 도구는 그 다음 의존 트리를 다시 만들기 위해 depscan.sh를 자동으로 요청할 것입니다.

서비스 추가하고 제거하기

여러분은 이미 젠투 설치과정에서 "default" 런레벨에 초기화 스크립트를 추가했습니다. 그 때 여러분은 "default"가 왜 있는지에 대한 실마리를 눈치채지 못하셨겠지만 이제는 알아차리셨을겁니다. rc-update스크립트는 두번째 인자로서 add, del, show 동작 중 하나를 필요로 합니다.

초기화 스크립트를 추가하거나 제거하려면 rc-update 스크립트에 adddel 인자를 추가하고, 초기화 스크립트 이름과 런레벨을 제시하시면 됩니다. 예를 들자면 다음과 같습니다.


코드 예제 2.1: default 런레벨에서 Postfix 제거하기
# rc-update del postfix default


rc-update -v show 명령은 사용할 수 있는 초기화 스크립트와 실행할 런레벨의 목록을 보여줄 것입니다.


코드 예제 2.2: 초기화 스크립트 정보 받기
# rc-update -v show


활성화 한 초기화 스크립트와 런레벨만을 보려면 (-v를 뺀) rc-update show로 실행하실 수 있습니다.

서비스 설정하기

왜 추가 설정이 필요한가?

초기화 스크립트는 조금 복잡할 수 있습니다. 때문에 오류에 취약하게 만들 수가 있어 사용자가 초기화 스크립트를 올바르게 하는데 썩 바람직하진 않습니다. 그러나 서비스를 설정할 수 있는 방법에 있어서는 중요합니다. 예를 들어 여러분이 서비스 자체에 더 많은 옵션을 주고 싶어할 수도 있습니다.

두번째 이유로는 초기화 스크립트의 외부 설정을 보유하려면, 바꾼 설정을 되돌릴 수 없다는 두려움을 없애고 초기화 스크립트를 업데이트할 수 있어야 하기 때문입니다.

/etc/conf.d 디렉터리

젠투에서는 서비스를 설정하는 쉬운 방법을 제공합니다: 모든 초기화 스크립트는 /etc/conf.d 에 있는 파일로 설정할 수 있습니다. 예를 들어 (/etc/init.d/apache2라고 하는) apache2 초기화 스크립트는 Apache 2서버를 시작할 때 주고 싶은 옵션을 넣을 수 있는 /etc/conf.d/apache2 라고 하는 설정 파일을 지니고 있습니다.


코드 예제 3.1: /etc/conf.d/apache2에 정의한 변수
APACHE2_OPTS="-D PHP5"


이런 설정 파일에는 변수를 포함하며 서비스를 쉽게 설정할 수 있게 하는 단독 변수(/etc/portage.make.conf와 같은)도 포함합니다. 이를 통해 변수에 대한 더 자세한 정보를 (주석을 통해) 제공해줄 수 있습니다.

초기화 스크립트 작성하기

이걸 꼭 해야 하나요?

아닙니다. 초기화 스크립트 작성은 보통 젠투가 모든 제공하는 서비스에 대해 준비된 초기화 스크립트를 제공하는 만큼 필요하지 않습니다 그러나 포티지를 사용하지 않는 서비스를 설치할 경우가 있는데, 이 때에는 초기화 스크립트를 거의 만들 필요가 있을 것입니다.

젠투용으로 확실하게 작성한 것이 아니라면 서비스에서 제공하는 init 스크립드를 사용하지 마십시오. 젠투의 초기화 스크립트는 다른 배포판에서 사용하는 초기화 스크립트와 호환되지 않습니다!

배치

초기화 스크립트의 기본 배치는 아래와 같습니다.


코드 예제 4.1: 초기화 스크립트의 기본 배치
#!/sbin/runscript


depend() {
    (의존성 정보)
}

start() {
    (서비스를 시작하는데 필요한 명령)
}

stop() {
    (서비스를 멈추는데 필요한 명령)
}


어떤 초기화 스크립트든지 start() 함수의 정의가 필요합니다. 다른 모든 부분은 부가적입니다.

의존성

초기화 스크립트를 시작하거나 연달아 실행하는데 영향을 주도록 설정할 수 있는 의존성향 유사 설정은 두 가지가 있는데 useneed입니다. 이들 다음으로는 beforeafter라고 하는 두가지 방식의 순서 영향 메소드가 있습니다. 마지막 두가지 각각의 요소는 의존성을 지니지 않습니다. 선택한 초기화 스크립트가 시작하도록 계획되지 못했(거나 시작에 실패했)을경우 본래 초기화 스크립트의 실행을 실패하도록 하지 않습니다.

  • use 설정은 선택한 스크립트의 기능 제공을 이 스크립트가 사용하지만 직접적인 의존성을 지니지 않도록 init 시스템에 알려줍니다. 좋은 본보기로 use loggeruse dns를 들 수 있습니다. 이 서비스가 존재한다면 사용하기 좋은 상태로 두겠지만 로거나 DNS 서버가 없다 하더라도 서비스는 여전히 동작할 것입니다. 서비스가 존재한다면 use에 있는 스크립트보다 먼저 서비스를 시작할 것입니다.
  • need 설정은 강한 의존성입니다. 이는 다른 스크립트를 need(필요)로 하는 스크립트는 명시한 다른 스크립트를 성공적으로 실행하기 전에는 시작하지 않음을 의미합니다. 또한 언급한 다른 스크립트를 재시작하면 마찬가지로 해당 스크립트도 재시작 할 것입니다.
  • before를 사용하면, 선택한 요소가 init 레벨의 일부일 경우 선택한 요소를 실행하기 전에 주어진 스크립트를 실행합니다. 그래서 before alsasound를 정의한 xdm init스크립트는 alsasound 스크립트를 실행하기 전에 시작하겠지만, alsasound가 동일한 init 레벨에서 실행하도록 계획되었을 경우에만 해당합니다. alsasound를 시작하도록 계획하지 않았다면, 일부 설정은 효력이 없을 것이며, 스크립트 자신이 가장 적당하다고 여기는 시점에 xdm을 실행할 것입니다.
  • 이와 마찬가지로 after를 사용하면, 선택한 요소가 init 레벨의 일부일 경우 선택한 요소를 실행한 다음에 주어진 스크립트를 실행합니다. 아니면 설정이 효력이 없을 것이며, 적당하다고 여기는 시점에 init 시스템이 스크립트를 실행할 것입니다.

위에서 분명히 해야 할 것은 need는 스크립트를 시작하든 아니든 영향을 주는 "진성" 의존성 설정이라는 것입니다. 다른 모든 요소들은 명령 스크립트를 실행(할 수 있거나 해야)할 때 init 시스템에 대해 분명하게 가리킬 뿐입니다.

이제 여러분이 젠투에서 사용할 수 있는 수많은 초기화 스크립트를 보았다면 없는 초기화 스크립트에 대해 의존성을 가진 것을 주목하실 것입니다. 이것들을 가상요소라고 부릅니다.

가상 의존성은 서비스를 제공하는 의존성이지만 서비스가 유일하게 제공해주는 것은 아닙니다. 여러분의 초기화 스크립트는 시스템 로거에 의존할 수 있는데 수많은 시스템 로거가 존재합니다(metalogd, syslog-ng, sysklogd, ...). 여러분은 각각의 모든 단일 요소를 need에 넣을 수 없지만 (설치하고 실행중인 모든 시스템 로거를 갖춘 합리적인 시스템은 없습니다), 이 모든 서비스들이 가상 의존성을 provide(제공)하는지 확인합니다.

이제 Postfix 서비스에 대한 의존성 정보를 보도록 하겠습니다.


코드 예제 4.2: Postfix의 의존 정보
depend() {

    need net
    use logger dns
    provide mta
}


여러분이 보시는 바와 같이 Postfix서비스에 다음과 같은 것들이 있습니다.

  • (가상)net 의존 요소를 필요로 합니다 (/etc/init.d/net.eth0와 같은 요소로 제공합니다)
  • (가상)logger 의존 요소를 사용합니다 (/etc/init.d/syslog-ng와 같은 요소로 제공합니다)
  • (가상)dns 의존 요소를 사용합니다 (/etc/init.d/named와 같은 요소로 제공합니다)
  • (가상)mta 의존 요소를 제공합니다 (모든 메일 서버의 공통요소 입니다)

순서 제어하기

이전 장에서 설명한 바와 같이 스크립트를 시작(하고 중지)하기 위한 순서를 어떻게 할 것인지 init 시스템에 알려줄 수 있습니다. 이 순서는 useneed 의존 설정을 통해 다룰 뿐만 아니라 beforeafter로도 순서 설정을 다루기도 합니다. 역시 앞에서 미리 설명한 것과 마찬가지로 초기화 스크립트 중 하나의 예제로서 Portmap 서비스를 살펴보도록 하겠습니다.


코드 예제 4.3: Portmap 서비스의 depend() 함수
depend() {

    need net
    before inetd
    before xinetd
}


비록 별로 도움이 되는 이야기는 아니겠지만, 동일한 런레벨의 모든 서비스를 포함하려면 "*"를 사용하실 수도 있습니다.


코드 예제 4.4: 런레벨의 첫번째 스크립트로 초기화 스크립트를 실행하기
depend() {

    before *
}


서비스가 반드시 지역 디스크에 기록을 해야 한다면 localmount가 필요합니다. pid 파일 같은 것을 /var/run에 두었다면 bootmisc 다음 실행해야 합니다.


코드 예제 4.5: depend() 함수 예제
depend() {

    need localmount
    after bootmisc
}


표준 함수

depend() 함수 다음에, start() 함수의 정의가 필요합니다. 이 함수에는 서비스를 시작하는데 필요한 모든 명령어를 담고 있습니다. 사용자에게 무슨 일이 일어나고 있는지를 알리기 위해 ebegineend함수를 사용하는 것이 좋습니다.


코드 예제 4.6: start() 함수 예제
start() {

    if [ "${RC_CMD}" = "restart" ];
    then
        # 다시 시작할 때 stop, start 할 때보다 더 실행해야 할 명령
    fi

    ebegin "Starting my_service"
    start-stop-daemon --start --exec /path/to/my_service \
       --pidfile /path/to/my_pidfile
    eend $?
}


--exec--pidfile start와 stop 함수에서 사용합니다. 서비스에서 pidfile을 만들지 못할 경우, 제대로 동작하는지 테스트 하는 겸에 되도록이면 --make-pidfile를 사용합니다. 그렇지 않으면 pidfile를 사용하지 않습니다. 또한 start-stop-daemon의 옵션으로 --quiet를 추가할 수 있지만 서비스에서 너무 많은 메시지를 뿌려대지 않은 이상 추천하는 방법은 아닙니다. --quiet를 사용하면 서비스 시작에 실패했을 때 디버깅 내용을 못보게 될 수도 있습니다.

위의 예제에서 사용한 눈에 보이는 설정으로서 RC_CMD변수의 내용을 확인하는 것입니다. 이전 초기화 스크립트 시스템과는 다르게 새로운 openrc 시스템에서는 스크립트 기반 다시 시작 기능을 사용하지 못합니다. 대신 함수(start()stop())가 다시 시작 과정의 일부로 호출 되었든지 아니든지간에 RC_CMD 변수의 내용을 스크립트에서 확인할 필요가 있습니다.


참고: --exec가 실제로 서비스를 실행하는 쉘 스크립트를 실행하고 나가는 것이 아니라 서비스를 호출하는지 확인하십시오. 어떤 초기화 스크립트를 실행할지 고려하는 것입니다.


start()함수에 대한 더 많은 예제를 보시려면 /etc/init.d 디렉터리에 있는 초기화 스크립트의 소스코드를 보시기 바랍니다.

여러분이 정의할 수 있는 또다른 함수로는 stop()이 있습니다. 이 함수를 꼭 정의할 필요는 없습니다! init 시스템은 여러분이 start-stop-daemon을 사용한다면 자체적으로 내용을 채울 정도로 충분히 똑똑합니다.

stop()함수의 예제는 다음과 같습니다.


코드 예제 4.7: stop() 함수 예제
stop() {

    ebegin "Stopping my_service"
    start-stop-daemon --stop --exec /path/to/my_service \
        --pidfile /path/to/my_pidfile
    eend $?
}


서비스에서 (bash, python, perl과 같은) 다른 스크립트를 실행하고 나중에 이 스크립트의 이름을 (foo.pyfoo로) 바꾼다면 start-stop-daemon--name을 추가할 필요가 있습니다. 여러분의 스크립트를 지정할 때 바꿀 이름으로 반드시 지정해야 합니다. 이 경우 서비스에서는 foo로 이름을 바꾸는 foo.py를 시작합니다.


코드 예제 4.8: foo 스크립트를 시작하는 서비스
start() {

    ebegin "Starting my_script"
    start-stop-daemon --start --exec /path/to/my_script \
        --pidfile /path/to/my_pidfile --name foo
    eend $?
}


여러분이 더 많은 내용을 필요로 할 것을 대비해 start-stop-daemon에 대한 뛰어난 man 페이지를 보유하고 있습니다.


코드 예제 4.9: start-stop-daemon에 대한 man 페이지 가져오기
$ man start-stop-daemon


젠투의 초기화 스크립트 문법은 본 어게인 쉘(bash) 문법을 기반으로 하기 때문에 여러분은 자유롭게 초기화 스크립트에 bash 호환 문법 스크립트를 사용할 수 있습니다. 다만, POSIX 호환 문법으로 초기화 스크립트를 작성하시고 싶을지도 모릅니다. 앞으로의 초기화 스크립트 시스템에서는 bash 말고도 다른 쉘에 대해 /bin/sh를 심볼릭 링크로 걸수 있도록 할 것입니다. 이렇게 하면 bash 고유 기능에 의존하는 초기화 스크립트가 이들 설정을 깰 것입니다.

사용자정의 옵션 추가하기

여러분의 초기화 스크립트에 앞서 우리가 언급했던것보다 더 맣은 옵션을 지원하도록 하려면 extra_commands 변수에 옵션을 추가하고, 옵션 이름과 동일한 함수를 만들어야 합니다. 실례로 restartdelay라고 하는 옵션을 지원하게 해보겠습니다.


코드 예제 4.10: restartdelay 옵션 지원하기
extra_commands="restartdelay"


restartdelay() {
    stop
    sleep 3    # 다시 시작하기 전에 3초를 기다립니다
    start
}



중요: restart() 함수는 openrc에서 덮어쓸 수 없습니다!


서비스 설정 변수

여러분은 /etc/conf.d의 설정 파일을 지원하기 위한 그 어떤 설정도 필요 없습니다. 초기화 스크립트를 실행하면 다음 파일을 자동으로 참조합니다. (예: 사용할 수 있는 변수)

  • /etc/conf.d/<your init script>
  • /etc/conf.d/basic
  • /etc/rc.conf

또한 여러분의 초기화 스크립트에 (net과 같은)가상 의존성을 지원제공하면, (/etc/conf.d/net과 같은) 의존성과 관련한 파일도 참조할 것입니다.

런레벨 동작 바꾸기

이걸로 이득 볼 사람이 있을까요?

많은 랩톱 사용자들은 이런 상황을 알고 있을 것입니다. 밖에서 (사용할 수 있는 네트워크가 없을 때) net.eth0를 시작하고 싶지 않은 반면에 집에서는 net.eth0를 시작하려 할 것입니다. 젠투에서는 여러분이 실행할 런레벨 동작을 바꿀 수 있습니다.

예를 들어 다른 초기화 스크립트를 할당하여 부트할 수 있는 두번째 "default" 런레벨을 만들 수 있습니다. 그렇게 하고 나면 여러분이 사용하려는 기본 런레벨이 무엇인지 부팅 시간에 선택할 수 있습니다.

소프트레벨 사용하기

제일 먼저, 두번째 "default" 런레벨에 대한 런레벨 디렉터리를 만듭니다. 다음의 예제에서 offline 런레벨을 만들어보도록 하겠습니다.


코드 예제 5.1: 런레벨 디렉터리 만들기
# mkdir /etc/runlevels/offline


다음 새로이 만든 런레벨에 필요한 초기화 스크립트를 추가합니다. 예를 들어 현재 default런레벨에서 net.eth0를 제외한 나머지 복사본을 정확하게 가지려면 다음과 같이 실행합니다.


코드 예제 5.2: 필요한 초기화 스크립트 추가하기
(default 런레벨에서 offline 런레벨로 모든 서비스 복사)

# cd /etc/runlevels/default
# for service in *; do rc-update add $service offline; done
(offline 런레벨에서 원하지 않는 서비스 제거)
# rc-update del net.eth0 offline
(offline 런레벨에서 활성화된 서비스 표시)
# rc-update show offline
(일부 본보기 출력)
            acpid | offline
  domainname | offline
            local | offline
       net.eth0 |


net.eth0을 offline 런레벨에서 제거했지만서도, udev가 아마 감지한 장치를 시작하고 적당한 서비스와 핫 플러그라는 기능을 실행하려 들 것입니다. 기본적으로 젠투는 핫 플러그를 활성화 하지 않습니다.

핫 플러그 기능을 활성화 하지만 선택한 스크립트 모음에 한정하려면, /etc/rc.conf의 rc_hotplug 변수를 사용하십시오.


코드 예제 5.3: /etc/rc.conf에서 장치 초기화 서비스 비활성화 하기
# Allow net.wlan as well as any other service, except those matching net.*

# to be hotplugged
rc_hotplug="net.wlan !net.*"



참고: 장치 초기화 서비스에 대한 자세한 내용을 보시려면 /etc/rc.conf의 주석을 참고하시기 바랍니다.


이제 부트로더 설정을 편집하고 offline 런레벨에 대한 새로운 엔트리를 추가합니다. 예를 들어 /etc/grub/grub.conf에 다음과 같이 입력합니다.


코드 예제 4.3: offline 런레벨에 대한 항목 추가하기
title Gentoo Linux Offline Usage

    root (hd0,0)
    kernel (hd0,0)/kernel-2.4.25 root=/dev/hda3 softlevel=offline


보시죠. 다 끝났죠? 시스템을 부팅하고 부팅할 때 새로운 항목을 선택하면 offline 런레벨을 default 대신 사용할 것입니다.

부트레벨 사용하기

bootlevel을 사용하는 것은 softlevel과 완전히 유사합니다. 유일한 차이점이라면 두번째 "default" 런레벨 대신에 두번째 "boot" 런레벨을 정의하는 것입니다.