%% $Id: freenix2001.mgp,v 1.1 2001/07/29 12:11:43 lukem Exp $ %% %% This document is Copyright (c) 2001, Luke Mewburn. %% %deffont "standard" xfont "helvetica-medium-r", tfont "arial.ttf", tmfont "wadalab-gothic.ttf" %deffont "thick" xfont "helvetica-bold-r", tfont "arialbd.ttf", tmfont "wadalab-gothic.ttf" %deffont "ital" xfont "helvetica-bold-i", tfont "ariali.ttf", tmfont "wadalab-gothic.ttf" %deffont "typewriter" xfont "courier-medium-r", tfont "courbd.ttf", tmfont "wadalab-gothic.ttf" %% %default 1 leftfill, size 2, fore "white", back "black", font "thick" %default 2 size 7, vgap 10, prefix " " %default 3 size 2, bar "gray70", vgap 10 %default 4 size 5, fore "white", vgap 30, prefix " ", font "standard" %% %tab 1 size 6, vgap 60, prefix " ", icon arc "cyan" 50 %tab 2 size 5, vgap 50, prefix " ", icon delta3 "green" 50 %tab 3 size 4, vgap 40, prefix " ", icon box "orange" 40 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page %nodefault %font "standard", fore "white", back "black" %center %size 7, font "thick" The Design and Implementation of the NetBSD rc.d system %size 5, font "standard" Luke Mewburn %size 4 NetBSD Core Team %font "typewriter" %font "standard" Wasabi Systems %font "typewriter" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Overview History Design Considerations Aftermath Technical details Future work Conclusion %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page History (1/3) Examine 4.4BSD (the parent of NetBSD), Solaris 7 (a common SVR4), and NetBSD prior to 1.5 4.4BSD At boot, kernel runs %cont, font "typewriter" init(8) %font "standard" init runs /etc/rc, which calls /etc/netstart (to configure network) and /etc/rc.local for local services At shutdown where init gets SIGTERM, init sends SIGHUP to each process with a controlling terminal %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page History (2/3) Solaris 7 System can be in one of 8 run states, changeable at run time At boot, kernel runs init, which spawns processes listed in /etc/inittab that match the current run state Default run state defined in /etc/inittab /sbin/rcX controls the run state change for state X; executes all of /etc/rcX.d/K* with "stop", then /etc/rcX.d/S* with "start" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page History (3/3) NetBSD before 1.5 Derived from 4.4BSD NetBSD 1.3 added /etc/rc.conf Contains variables to control each service Separates scripts from configuration information NetBSD 1.4 added /etc/rc.shutdown Run by shutdown (not halt or reboot) Similar implementation to /etc/rc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Design Considerations: Problems No control over individual services "/etc/rc.d/foo start" is easier than the manual process No dependency ordering Little support for third party services, especially starting them elsewhere in the boot sequence %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Design Considerations: Requirements Manipulation of individual services Dependency ordering Independence from lexigraphical filename ordering Ability to insert third party scripts anywhere into the sequence Not bloating /bin and /sbin (i.e., '/') Use dynamic dependency ordering make or tsort not robust enough, required moving to / Chose dedicated program - rcorder %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Requirements (2/4) Support third party scripts Maintain /etc/rc.conf Pre-existing mechanism, and popular SYSV init.d mechanism of creating links to control service startup is difficult to manage Promote code reuse Support service shutdown Via manual manipulation (q.v.) At shutdown time (a la /etc/rc.shutdown) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Requirements (3/4) Avoid mandatory run states and /etc/inittab Too contentious Lack of consistency between existing implementations Have equivalents for most SYSV run states in existing system %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Requirements (4/4) Other design issues Used /etc/rc.d instead of /etc/init.d System isn't exactly SYSV, different name highlights this A symlink from /etc/init.d to rc.d can provide compatibility Originally supported three schemes; /etc/rc, SYSV style /etc/rcN.d, and /etc/rc.d Multiple systems is a support and maintenance nightmare Lack of dynamic dependency ordering in the first two schemes This decision was contentious "Nochangeniks" are a very vocal minority and the most skilled to privately maintain their preferred mechanism Those who want SYSV init.d can trivially add to rc.d %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Configuration improvements /etc/rc.conf mechanism was enhanced Default system settings were moved to /etc/defaults/rc.conf FreeBSD had prior art on this, and their experience was favourable The distributed rc.conf reads defaults/rc.conf, and local config settings are added to the end of rc.conf to override the defaults An optional per-service config override /etc/rc.conf.d/foo, which is read after rc.conf Useful for automated tools to control service startup Retains rc.conf semantics - no consensus was reached to remove these %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Aftermath: Human issues Initial CVS commits were made, but existing infrastructure wasn't changed. %center, font "ital" This was a mistake! %leftfill, font "standard" We didn't announce our integration intentions: Users perceived this as a stealth attack without consultation We felt there had been enough discussion already (5 years worth), and didn't want to delay any further %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Technical & 'religious' complaints %font "ital" "the use of magic functions is bad" %font "standard" Code reuse was a goal %font "ital" "switching from /etc/rc isn't the BSD way" %font "standard" A common 'religious' argument. Robert Elz (a long-time BSD contributer) says: %center, font "ital" "[the BSD way is to] find something that looks to be better (in the opinion of the small group deciding such things), implement it, and ship it" %leftfill, font "standard" In this case, the 'small group' was the NetBSD core team %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Technical & 'religious' complaints (cont.) %font "ital" "why wasn't a System V init.d implemented?" %font "standard" (polar position to the rc retainers) I covered this in the design goals Some vocal detractors gave the impression that a majority of users were against this work Far from the truth ... just another "holy war" Over one year since implementation and a lot of people support it in principle %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Technical details (1/3) /etc/rc Started by init Calls rcorder to order /etc/rc.d/*, skipping files tagged "nostart" Invokes each script in turn with an argument of "start" /etc/rc.shutdown Reverse of /etc/rc Calls rcorder to order /etc/rc.d/*, matching files tagged "shutdown" Invokes each script in turn with an argument of "stop" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Technical details (2/3) /etc/rc.d/* scripts Individual scripts for each service Called by rc, rc.shutdown, and manually by users Must support: start, stop Should support: restart, status, rcvar, and other arguments as necessary If argument prefixed with "force", skip rc.conf check /etc/rc.subr Shell script containing helper functions Removes duplication in individual rc.d scripts %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Example: /etc/rc.d/dhclient %font "typewriter", size 4 #!/bin/sh # # PROVIDE: dhclient # REQUIRE: network mountcritlocal # . /etc/rc.subr name="dhclient" rcvar=$name command="/sbin/${name}" pidfile="/var/run/${name}.pid" load_rc_config $name run_rc_command "$1" %font "standard" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%page %% %%Technical details (3/4) %% %% /etc/rc.d/* scripts (cont.) %% Provide placeholder scripts as sequence points for other scripts to require: %% NETWORK - basic network services, dhclient %% SERVERS - basic services (NETWORK, ppp, syslog) exist for services needed later (named) %% DAEMON - before general purpose daemons (dhcpd, lpd, ntpd) %% LOGIN - before user login services (inetd, sshd, xdm) and services which run user processes (cron, sendmail) %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%page %% %%Technical details (3/4) %% %% These are shell scripts, sourced by the rc.d scripts %% "exit" will terminate the boot sequence %% Not all commands will be available %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%page %% %%/etc/rc.subr functions %% %% checkyesno var %% determine if rc.conf variable var is 'yes'or 'no' %% check_pidfile pidfile procname %% parse pidfile for pid, prints pid if it matches procname %% check_process procname %% prints pids matching procname %% load_rc_config command %% reads rc.conf and rc.conf.d/command %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%page %% %%/etc/rc.subr functions %% %% run_rc_command arg %% arg is the user provided argument (e.g., "stop") %% The "kitchen sink" function, which is highly flexible, supporting many different service types %% Behaviour controlled by setting various shell variables %% example: rc.d/dhclient %% XXX pull in example %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Technical details (3/3) rcorder Parses supplied scripts for special comments which describe the dependencies PROVIDE - service provided REQUIRE - services required BEFORE - service to insert before KEYWORD - keywords to match to either explicitly keep (rcorder -k) or skip (rcorder -s) Allows 3rdparty scripts to be easily inserted into arbitrary points in the sequence /etc/defaults/rc.conf, /etc/rc.conf, /etc/rc.conf.d/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Current status Recent enhancements When "stop"ping a service, poll until process exits Optional rc.shutdown watchdog timer, which terminates rc.shutdown if the watchdog fires chkconfig(8) to control rc.conf.d/foo config files Future work Ability to run scripts from service A to service B Gives most of what people seem to want in run states Have sample implementation Need a clean way to store current "service name" (equivalent to run state #); considered using a sysctl(3) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Conclusion Extremely contentious and difficult to implement. Because of this, consensus isn't necessarily achievable; a "core" technical group needs to intervene at times Vocal users do not necessarily represent a majority People usually don't comment unless they feel extremely strongly, especially in the negative There is often a "silent majority" in agreement %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %page Availability NetBSD 1.5 ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-1.5/ NetBSD-current ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-current/ Anon CVS SUP Access via CVS web http://cvsweb.netbsd.org/bsdweb.cgi/basesrc/etc/