File: booting.html

package info (click to toggle)
lg-issue19 4-4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,388 kB
  • ctags: 122
  • sloc: sh: 73; makefile: 37
file content (405 lines) | stat: -rw-r--r-- 18,527 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
<!--startcut ==========================================================-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<title>Single-User Booting Under Linux Issue 19</title>
</HEAD>
<BODY BGCOLOR="#EEE1CC" TEXT="#000000" LINK="#0000FF" VLINK="#0020F0"
ALINK="#FF0000">
<!--endcut ============================================================-->

<H4>
&quot;Linux Gazette...<I>making Linux just a little more fun!</I>&quot;
</H4>

<P> <HR> <P> 
<!--===================================================================-->

<center>
<H2>Single-User Booting Under Linux</H2>
<H4>By John Gatewood Ham,
<a href="mailto:zappaman@alphabox.compsci.buu.ac.th">zappaman@alphabox.compsci.buu.ac.th</a></H4>
</center>
<P><HR>
I was trained as a system administrator on HP, IBM, and Sun workstations 
while working as a DRT consultant assigned to Informix as an alpha-tester.  
There I learned the need for a true single-user operating mode in Unix.  
When I tried to use the single user mode with Linux, it did not work in the 
way that I expected.  After many, many reboots I worked out the right 
configuration to support a true single-user mode on the distribution I was 
using, Slackware 3.2, by modifying the boot process.
</P>
<P>
This article will now explain how to setup the bootup process for Linux so 
that single-user mode really works if you are using the Slackware 3.2 
distribution (or a derivative).  I will begin by assuming that your kernel 
is correctly configured and that the <CODE>init</CODE> program starts successfully.  
See the Installation-HOWTO at
<A HREF=ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Installation-HOWTO><code>ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Installation-HOWTO</code></A>
for help to get this far.  Once you have a system that boots, however, you 
have only begun.  Why?  Most distributions will give you a generic set of 
initialization scripts that are designed to work for an average installation.  
You will want to customize this in order to run extra things you want and/or 
to prevent  running things you do not want.  With the dozen or so standard 
startup scripts things can seem confusing, but after you read this article 
you should be able to understand enough to create a custom environment 
when you boot that exactly suits you.
</P>
<P>
As I stated earlier, I will begin by assuming that <CODE>init</CODE> has started 
successfully.  It will examine the file <CODE>/etc/inittab</CODE> to determine 
what to do.  In that file are located the lines to activate your login 
devices such as terminals, modems, and your virtual consoles.  Leave that 
stuff alone.  What we are interested in are the lines which call the 
startup/shutdown scripts.  These lines will look something like this:
</P>
<PRE>
# Default runlevel.
id:3:initdefault:

# System initialization (runs when system boots).
si::sysinit:/etc/rc.d/rc.S

# Script to run when going single user (runlevel 1).
l1:1:wait:/etc/rc.d/rc.K

# Script to run when going single user (runlevel S or s)
mm:S:wait:/etc/rc.d/rc.K2

# Script to run when going multi user.
rc:23456:wait:/etc/rc.d/rc.M

# Runlevel 0 halts the system.
l0:0:wait:/etc/rc.d/rc.0

# Runlevel 6 reboots the system.
l6:6:wait:/etc/rc.d/rc.6
</PRE>
<P>
The comments are present and are very helpful.  First you need to determine 
your default runlevel.  In this case it is 3.  The format of the <CODE>/etc/inittab</CODE>
file section we are looking at is simple.  Blank lines are ignored.  Lines 
with '#' as the first character are comments and are ignored.  Other lines 
have 4 parts separated by the colon character.  These parts are 1. symbolic 
label, 2. runlevel, 3. action and 4.command to run.  These are documented in 
the section 5 manual page for <CODE>/etc/inittab</CODE> (<CODE>man 5 inittab</CODE>).  First
we must find a line with an action of <CODE>initdefault</CODE>, and then see what runlevel 
it has.  That will be the default runlevel.  Obviously you should not have 2 
lines that have <CODE>initdefault</CODE> as the action in an <CODE>/etc/inittab</CODE> file.  Once you know 
the default runlevel, you will be able to know what <CODE>/etc/inittab</CODE> entries 
will be processed by <CODE>init</CODE>.  The 1 runlevel is considered single-user 
maintenance mode, but it supported multiple simultaneous logins in virtual 
terminals with the default <CODE>/etc/inittab</CODE> on my systems.  You can prevent this by 
removing the 1 from the getty lines of the tty2, tty3, tty4, etc.  The 3 
runlevel is considered the normal multi-user mode with full networking 
support.  The S runlevel is supposed to be true single-user, and you can 
theoretically enter that runlevel using the <CODE>lilo</CODE> parameter 
<CODE>single</CODE>.  However, for the Slackware 3.2 distribution, that does 
not put you in a single-user mode as you would expect, but instead you wind 
up in runlevel 3.  The <CODE>/etc/inittab</CODE> file I show here does not have that problem 
however.  Once you have read this article you can change the system to 
behave in the expected manner.  So we know we will go to runlevel 3.  That 
means <CODE>init</CODE> will perform every command in the <CODE>/etc/inittab</CODE> file that has a <CODE>sysinit</CODE>, 
then <CODE>boot</CODE>, or <CODE>bootwait</CODE>, and finally any entries for our runlevel 3.  When you 
want to run a script when entering a runlevel, it doesn't make sense to have 
more than one script line in the <CODE>/etc/inittab</CODE> file for that level.  Instead, you 
should put everything in 1 script, or call scripts from within the script 
mentioned in the <CODE>/etc/inittab</CODE> file using the dot method.  Once thing to note is 
that field 2, the runlevel field, can have more than 1 runlevel specified.  
The <CODE>init</CODE> program will first run the <CODE>si</CODE> entry 
(and we will wait for it to finish running <CODE>/etc/rc.d/rc.S</CODE>) since it has 
<CODE>sysinit</CODE> (which implies <CODE>wait</CODE>) in the third field.  Then it will run everything 
with 3 specified.  So in our example file we will run the <CODE>si</CODE> target, then 
the <CODE>rc</CODE> target (and we will wait for it to finish running the 
<CODE>/etc/rc.d/rc.M</CODE> script since the third field is <CODE>wait</CODE>), and finally 
we it will do the <CODE>c1</CODE> through <CODE>c6</CODE> targets which set up the virtual ttys during 
a normal boot.  
</P>
<P>
If we boot (via <CODE>lilo</CODE>) and add the <CODE>single</CODE> 
parameter, we will still run the <CODE>si</CODE> target (<CODE>/etc/rc.d/rc.S</CODE>) and wait for it to 
complete, but then we will run the <CODE>mm</CODE> target (<CODE>/etc/rc.d/rc.K2</CODE>).  Keep in mind 
that runlevel 1 and runlevel S are essentially the same when you enter them, 
but how you get there is very different.  Runlevel 1 can be entered by using 
the command <CODE>/sbin/telinit 1</CODE>, but <CODE>/sbin/telinit s</CODE> will send you to runlevel 5 
often for some reason (some kind of bug).  Runlevel 1 will give you a normal 
log in, and allows 1 user (<I>any</I> 1 user) to log in at the console.  
With this setup, runlevel S will give you a special root-only login that 
allows only root to use the console.  Since only root can log in, only a 
special password prompt is displayed.  If you press enter or ctl-D, the system 
will return to runlevel 3.  This root-only login is accomplished by using 
the <CODE>/bin/sulogin</CODE> program.  Runlevel S is probably what you want when you think 
single-user, but you have to reboot the machine and use <CODE>lilo</CODE> and have the 
single parameter to make it work.  You can use runlevel 1 to accomplish the 
same things, but remember you will have to manually return to runlevel 3 
when you are done with another call to <CODE>/sbin/telinit 3</CODE> or a reboot, and you 
must insure that nobody else can get to the console but the root user.  
WARNING: The true single-user mode entered with the single parameter to 
<CODE>lilo</CODE> with  my <CODE>/etc/inittab</CODE> and <CODE>/etc/rc.d/rc.K2</CODE> will support only 1 console and no other 
virtual terminals.  Do not run anything that locks up the terminal!
</P>
<P>
Ok, so what do we know now?  We know what scripts <CODE>init</CODE> will call and when they 
will be called.  But what can be in those scripts?  The scripts should be 
written for bash unless you are a real guru and KNOW the other shell you 
wrote scripts for will be available during boot.  There is nothing preventing 
you from using <CODE>perl</CODE> or <CODE>tcsh</CODE> or whatever, but traditionally most everyone uses 
<CODE>bash</CODE> scripts (ok, ok, Bourne shell scripts) for unix boot scripts.  The <CODE>/etc/rc.d/rc.S</CODE>
script which is called at system boot time should take care of things like 
<CODE>fsck</CODE>'ing your file systems, mounting them, and starting up swapping and other 
essential daemons.  These are things that you need independent of runlevel.  
The <CODE>/etc/rc.d/rc.M</CODE> script which is called when you enter runlevel 3 should start all 
the processes that remain that you usually need during normal system 
operation EXCEPT things like <CODE>getty</CODE>.  Processes that must be restarted whenever 
they stop running like <CODE>getty</CODE> should be placed in the <CODE>/etc/inittab</CODE> file instead of 
being started by a boot script.  So what is in a typical <CODE>/etc/rc.d/rc.M</CODE> script?  
Usually configuring the network , starting web servers, sendmail, and 
anything else you want to always run like database servers, quota 
programs, etc.
</P>
<P>
The only startup script I mention in my <CODE>/etc/inittab</CODE> that is not included in the
Slackware 3.2 distribution is <CODE>/etc/rc.d/rc.K2</CODE>, and it is merely a modified version 
of <CODE>/etc/rc.d/rc.K</CODE> set up for single user mode.  Remember this is the startup script 
that will be used if you choose to enter the <CODE>single</CODE> parameter to <CODE>lilo</CODE>.  At 
the end of this file you will see a line:
</P>
<PRE>
exec /bin/sulogin /dev/console
</PRE>
<P>
This will replace the current process which is running the script with the 
<CODE>/bin/sulogin</CODE> program.  This means, of course, that this has to be the last 
line in your script, since nothing after this line will be processed by <CODE>bash</CODE>.
After that program starts, it displays a message to either enter the root 
password or press ctl-D.  If you enter the correct root password, you will 
be logged in as root in a true single-user mode.  Be careful, though, 
because when you exit that shell the machine will go into runlevel 3.  
If you want to reboot before entering runlevel 3 you must remember to do 
it (via <CODE>shutdown</CODE>) instead of just exiting the shell.  If you press ctl-D 
instead of the root password, the system will enter runlevel 3.  I have 
changed the incorrect calls to <CODE>kill</CODE> to use the <CODE>killall5</CODE> program, since 
the lines with <CODE>kill</CODE> caused <CODE>init</CODE> to be killed and a runlevel change was
happening incorrectly.
</P>
<P>
Well, I hope that this description of how I enabled my Linux machine to 
have a single-user mode similar to that of the big-name workstations 
proves helpful to you.  Customizing your boot process is not too hard, 
once you understand something about how the <CODE>/etc/inittab</CODE> 
and <CODE>/etc/rc.d/*</CODE>
scripts work.  Be sure you 1. backup your entire system, 2. have a boot 
floppy, and 3. a rescue floppy that can restore the backup (or any 
individual files) you made in step 1 using the boot floppy from step 2 to 
boot the machine.  If you make a 1 character typo you can prevent the 
machine from booting, so the backup steps, while tedious, are really 
necessary to protect yourself before you experiment.
</P>
<h1><CENTER>The Files</CENTER></h1>
<P>
Here are the files I used.  Use at your own risk.  They work for me, but
may need to be modified to work for you.
</P>
<hr>
<h2><Center><code>/etc/inittab</code></center></h2>
<PRE>
#
# inittab	This file describes how the INIT process should set up
#		the system in a certain run-level.
#
# Version:	@(#)inittab		2.04	17/05/93	MvS
#                                       2.10    02/10/95        PV
#
# Author:	Miquel van Smoorenburg, <a href="mailto:miquels@drinkel.nl.mugnet.org">miquel@drinkel.nl.jugnet.org</a>
# Modified by:	Patrick J. Volkerding, <a href="mailto:volkerdi@ftp.cdrom.com">volkerdi@ftp.cdrom.com</a>
# Modified by:  John Gatewood Ham, <a href="mailto:zappaman@alphabox.compsci.buu.ac.th">zappaman@alphabox.compsci.buu.ac.th</a>
#
# Default runlevel.
id:3:initdefault:

# System initialization (runs when system boots).
si::sysinit:/etc/rc.d/rc.S

# Script to run when going maintenance mode (runlevel 1).
l1:1:wait:/etc/rc.d/rc.K

# Script to run when going single user (runlevel s)
mm:S:wait:/etc/rc.d/rc.K2

# Script to run when going multi user.
rc:23456:wait:/etc/rc.d/rc.M

# What to do at the "Three Finger Salute".
# make the machine halt on ctl-alt-del
ca::ctrlaltdel:/sbin/shutdown -h now "going down on ctl-alt-del"

# Runlevel 0 halts the system.
l0:0:wait:/etc/rc.d/rc.0

# Runlevel 6 reboots the system.
l6:6:wait:/etc/rc.d/rc.6

# What to do when power fails (shutdown to single user).
pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING"

# If power is back before shutdown, cancel the running shutdown.
pg:0123456:powerokwait:/sbin/shutdown -c "THE POWER IS BACK"

# If power comes back in single user mode, return to multi user mode.
ps:S:powerokwait:/sbin/init 5

# The getties in multi user mode on consoles an serial lines.
#
# NOTE NOTE NOTE adjust this to your getty or you will not be
#                able to login !!
#
# Note: for 'agetty' you use linespeed, line.
# for 'getty_ps' you use line, linespeed and also use 'gettydefs'
# we really don't want multiple logins in single user mode...
c1:12345:respawn:/sbin/agetty 38400 tty1 linux
c2:235:respawn:/sbin/agetty 38400 tty2 linux
c3:235:respawn:/sbin/agetty 38400 tty3 linux
c4:235:respawn:/sbin/agetty 38400 tty4 linux
c5:235:respawn:/sbin/agetty 38400 tty5 linux
c6:235:respawn:/sbin/agetty 38400 tty6 linux

# Serial lines
#s1:12345:respawn:/sbin/agetty 19200 ttyS0 vt100
#s2:12345:respawn:/sbin/agetty 19200 ttyS1 vt100

# Dialup lines
#d1:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS0 vt100
#d2:12345:respawn:/sbin/agetty -mt60 38400,19200,9600,2400,1200 ttyS1 vt100

# Runlevel 4 used to be for an X-window only system, until we discovered
# that it throws init into a loop that keeps your load avg at least 1 all 
# the time. Thus, there is now one getty opened on tty1. Hopefully no one
# will notice. ;^)
# It might not be bad to have one text console anyway, in case something 
# happens to X.
x1:4:wait:/etc/rc.d/rc.4

# End of /etc/inittab
</PRE>
<hr>
<h2><Center><code>/etc/rc.d/rc.K</code></center></h2>
<PRE>
# /bin/sh
#
# rc.K 		This file is executed by init when it goes into runlevel
#		1, which is the administrative state. It kills all
#		deamons and then puts the system into single user mode.
#		Note that the file systems are kept mounted.
#
# Version:	@(#)/etc/rc.d/rc.K	1.50	1994-01-18
# Version:	@(#)/etc/rc.d/rc.K	1.60	1995-10-02 (PV)
#
# Author:	Miquel van Smoorenburg <a href="mailto:miquels@drinkel.nl.mugnet.org">miquels@drinkel.nl.mugnet.org</a>
# Modified by:  Patrick J. Volkerding <a href="mailto:volkerdi@ftp.cdrom.com">volkerdi@ftp.cdrom.com</a>
# Modified by:  John Gatewood Ham <a href="mailto:zappaman@alphabox.compsci.buu.ac.th">zappaman@alphabox.compsci.buu.ac.th</a>
#
  # Set the path.
  PATH=/sbin:/etc:/bin:/usr/bin

  # Kill all processes.
  echo
  echo "Sending all processes the TERM signal."
  killall5 -15
  echo -n "Waiting for processes to terminate"
  for loop in 0 1 2 3 4 5 6 7 ; do
    sleep 1
    echo -n "."
  done
  echo
  echo "Sending all processes the KILL signal."
  killall5 -9

  # Try to turn off quota and accounting.
  if [ -x /usr/sbin/quotaoff ]
  then
	echo "Turning off quota.."
	/usr/sbin/quotaoff -a
  fi
  if [ -x /sbin/accton ]
  then
	echo "Turning off accounting.."
	/sbin/accton
  fi

</PRE>
<hr>
<h2><Center><code>/etc/rc.d/rc.K2</code></center></h2>
<PRE>
# /bin/sh
#
# rc.K 		This file is executed by init when it goes into runlevel
#		1, which is the administrative state. It kills all
#		deamons and then puts the system into single user mode.
#		Note that the file systems are kept mounted.
#
# Version:	@(#)/etc/rc.d/rc.K	1.50	1994-01-18
# Version:	@(#)/etc/rc.d/rc.K	1.60	1995-10-02 (PV)
#
# Author:	Miquel van Smoorenburg <a href="mailto:miquels@drinkel.nl.mugnet.org">miquels@drinkel.nl.mugnet.org</a>
# Modified by:  Patrick J. Volkerding <a href="mailto:volkerdi@ftp.cdrom.com">volkerdi@ftp.cdrom.com</a>
# Modified by:  John Gatewood Ham <a href="mailto:zappaman@alphabox.compsci.buu.ac.th">zappaman@alphabox.compsci.buu.ac.th</a>
#
# Set the path.
PATH=/sbin:/etc:/bin:/usr/bin

# Kill all processes.
echo
echo "Sending all processes the TERM signal."
killall5 -15
echo -n "Waiting for processes to terminate"
for loop in 0 1 2 3 4 5 6 7 ; do
  sleep 1
  echo -n "."
done
echo
echo "Sending all processes the KILL signal."
killall5 -9

# Try to turn off quota and accounting.
if [ -x /usr/sbin/quotaoff ]
then
	echo "Turning off quota.."
	/usr/sbin/quotaoff -a
fi
if [ -x /sbin/accton ]
then
	echo "Turning off accounting.."
	/sbin/accton
fi

# Now go to the single user level
exec /bin/sulogin /dev/console
</PRE>
<HR>
<address>
<A HREF="mailto:zappaman@alphabox.compsci.buu.ac.th">zappaman@alphabox.compsci.buu.ac.th</A>
<BR>
<A HREF="http://alphabox.compsci.buu.ac.th/~zappaman">Information about me.</A>
</address>


<!--===================================================================-->
<P> <hr> <P> 
<center><H5>Copyright &copy; 1997, John Gatewood Ham<BR> 
Published in Issue 19 of the Linux Gazette, July 1997</H5></center>

<!--===================================================================-->
<P> <hr> <P> 
<A HREF="./lg_toc19.html"><IMG ALIGN=BOTTOM SRC="../gx/indexnew.gif" 
ALT="[ TABLE OF CONTENTS ]"></A>
<A HREF="../lg_frontpage.html"><IMG ALIGN=BOTTOM SRC="../gx/homenew.gif"
ALT="[ FRONT PAGE ]"></A>
<A HREF="./unrpm.html"><IMG SRC="../gx/back2.gif"
ALT=" Back "></A>
<A HREF="./trade.html"><IMG SRC="../gx/fwd.gif" ALT=" Next "></A>
<P> <hr> <P> 
<!--startcut ==========================================================-->
</BODY>
</HTML>
<!--endcut ============================================================-->