Handbook:Parts/Working/Initscripts/ko

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

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

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

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

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

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

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

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

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

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

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

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

이제 init 는 어떤 실행 레벨을 실행할 지 설정 파일을 확인합니다. 에서 다음 줄을 읽어 들들이고 실행할 실행 레벨을 결정합니다.

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

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

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

존재하는 실행 레벨
이전 절에서, init에서 어떤 실행 레벨을 활성화 할지 결정하는 숫자 방식을 활용함을 보았습니다. 실행 레벨은 시스템이 실행중인 상태를 나타내며, 실행 레벨에 진입하거나 벗어날때 실행해야 할 여러가지 스크립트(실행 레벨 스크립트 또는 초기화 스크립트)를 가지고 있습니다.

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

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

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

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

서비스를 중단하고 싶지만 다른 관련 서비스는 그대로 둔다면  매개 변수를 stop 명령과 함께 사용할 수 있습니다.

서비스의 상태(시작함, 중단함, 멈춤, 등)가 어떤지 보려면 status 인자를 사용하십시오:

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

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

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

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

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

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

서비스 추가/삭제
이전 설치과정에서 "default" 실행 레벨에 초기화 스크립트를 추가했습니다. 그 때 여러분은 "default"가 왜 있는지 눈치채지 못하셨겠지만 이제는 알아차리셨을겁니다. rc-update 스크립트는 add, del, show 동작 중 하나를 두번째 매개 변수로 필요로 합니다.

초기화 스크립트를 추가하거나 제거하려면  스크립트에 add나 del 매개 변수를 추가하고, 초기화 스크립트 이름과 실행 레벨을 제시하시면 됩니다. 예를 들자면 다음과 같습니다.

명령은 사용할 수 있는 실행할 초기화 스크립트와 실행 레벨의 목록을 보여줍니다.

(-v를 뺀) 를 실행하여 활성화 한 초기화 스크립트와 실행 레벨만을 보실 수 있습니다.

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

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

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

이런 설정 파일에는 서비스 설정을 쉽게 하는 ( 같은)변수만 들어있습니다. 변수에 대한 더 자세한 정보도(주석을 통해) 제공해줄 수 있습니다.

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

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

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

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

의존성
There are two dependency-alike settings that can be defined which influence the start-up or sequencing of init scripts: use and need. Next to these two, there are also two order-influencing methods called before and after. These last two are no dependencies per se - they do not make the original init script fail if the selected one isn't scheduled to start (or fails to start).


 * The use settings informs the init system that this script uses functionality offered by the selected script, but does not directly depend on it. A good example would be use logger or use dns. If those services are available, they will be put in good use, but if the system does not have a logger or DNS server the services will still work. If the services exist, then they are started before the script that uses them.
 * The need setting is a hard dependency. It means that the script that is needing another script will not start before the other script is launched successfully. Also, if that other script is restarted, then this one will be restarted as well.
 * When using before, then the given script is launched before the selected one if the selected one is part of the init level. So an init script xdm that defines before alsasound will start before the alsasound script, but only if alsasound is scheduled to start as well in the same init level. If alsasound is not scheduled to start too, then this particular setting has no effect and xdm will be started when the init system deems it most appropriate.
 * Similarly, after informs the init system that the given script should be launched after the selected one if the selected one is part of the init level. If not, then the setting has no effect and the script will be launched by the init system when it deems it most appropriate.

It should be clear from the above that need is the only "true" dependency setting as it affects if the script will be started or not. All the others are merely pointers towards the init system to clarify in which order scripts can be (or should be) launched.

Now, look at many of Gentoo's available init scripts and notice that some have dependencies on things that are no init scripts. These "things" we call virtuals.

A virtual dependency is a dependency that a service provides, but that is not provided solely by that service. An init script can depend on a system logger, but there are many system loggers available (metalogd, syslog-ng, sysklogd, ...). As the script cannot need every single one of them (no sensible system has all these system loggers installed and running) we made sure that all these services provide a virtual dependency.

For instance, take a look at the postfix dependency information:

As can be seen, the postfix service:
 * requires the (virtual) net dependency (which is provided by, for instance, )
 * uses the (virtual) logger dependency (which is provided by, for instance, )
 * uses the (virtual) dns dependency (which is provided by, for instance, )
 * provides the (virtual) mta dependency (which is common for all mail servers)

순서 처리
As described in the previous section, it is possible to tell the init system what order it should use for starting (or stopping) scripts. This ordering is handled both through the dependency settings use and need, but also through the order settings before and after. As we have described these earlier already, let's take a look at the portmap service as an example of such init script.

It is possible to use the "*" glob to catch all services in the same runlevel, although this isn't advisable.

If the service must write to local disks, it should need localmount. If it places anything in such as a pidfile, then it should start after bootmisc:

표준 함수
Next to the depend functionality, it is also necessary to define the start function. This one contains all the commands necessary to initialize the service. It is advisable to use the ebegin and eend functions to inform the user about what is happening:

Both --exec and --pidfile should be used in start and stop functions. If the service does not create a pidfile, then use --make-pidfile if possible, though it is recommended to test this to be sure. Otherwise, don't use pidfiles. It is also possible to add --quiet to the start-stop-daemon options, but this is not recommended unless the service is extremely verbose. Using --quiet may hinder debugging if the service fails to start.

Another notable setting used in the above example is to check the contents of the RC_CMD variable. Unlike the previous init script system, the newer openrc system does not support script-specific restart functionality. Instead, the script needs to check the contents of the RC_CMD variable to see if a function (be it start or stop) is called as part of a restart or not.

For more examples of the start function, please read the source code of the available init scripts in the directory.

Another function that can (but does not have to) be defined is stop. The init system is intelligent enough to fill in this function by itself if start-stop-daemon is used.

If the service runs some other script (for example, bash, python, or perl), and this script later changes names (for example, foo.py to foo), then it is necessary to add --name to start-stop-daemon. This must specify the name that the script will be changed to. In this example, a service starts foo.py, which changes names to foo:

start-stop-daemon has an excellent man page available if more information is needed:

Gentoo's init script syntax is based on the POSIX Shell so people are free to use sh-compatible constructs inside their init scripts. Keep other constructs, like bash-specific ones, out of the init scripts to ensure that the scripts remain functional regardless of the change Gentoo might do on its init system.

개별 옵션 추가
If the initscript needs to support more options than the ones we have already encountered, then add the option to the extra_commands variable, and create a function with the same name as the option. For instance, to support an option called restartdelay:

서비스 설정 변수
In order to support configuration files in, no specifics need to be impleneted: when the init script is executed, the following files are automatically sourced (i.e. the variables are available to use):

Also, if the init script provides a virtual dependency (such as net), the file associated with that dependency (such as ) will be sourced too.

누가 이득을 볼까요
Many laptop users know the situation: at home they need to start net.eth0, but they don't want to start net.eth0 while on the road (as there is no network available). With Gentoo ythe runlevel behaviour can be altered at will.

For instance, a second "default" runlevel can be created which can be booted that has other init scripts assigned to it. At boottime, the user can then select what default runlevel to use.

소프트 레벨 사용
First of all, create the runlevel directory for the second "default" runlevel. As an example we create the offline runlevel:

Add the necessary init scripts to the newly created runlevel. For instance, to have an exact copy of the current default runlevel but without net.eth0:

Even though net.eth0 has been removed from the offline runlevel, udev might want to attempt to start any devices it detects and launch the appropriate services, a functionality that is called hotplugging. By default, Gentoo does not enable hotplugging.

To enable hotplugging, but only for a selected set of scripts, use the  variable in :

Edit the bootloader configuration and add a new entry for the offline runlevel. In that entry, add  as a boot parameter.

부트 레벨 사용
Using bootlevel is completely analogous to softlevel. The only difference here is that a second "boot" runlevel is defined instead of a second "default" runlevel.