File: checkroot.sh

package info (click to toggle)
sysvinit 2.88dsf-59.9
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,156 kB
  • ctags: 1,694
  • sloc: ansic: 7,089; sh: 3,335; makefile: 306; perl: 74
file content (371 lines) | stat: -rwxr-xr-x 9,353 bytes parent folder | download
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
#! /bin/sh
### BEGIN INIT INFO
# Provides:          checkroot mtab
# Required-Start:    mountdevsubfs hostname
# Required-Stop:     
# Should-Start:      keymap hwclockfirst hdparm bootlogd
# Should-stop:
# Default-Start:     S
# Default-Stop:
# X-Interactive:     true
# Short-Description: Check to root file system.
### END INIT INFO

# Include /usr/bin in path to find on_ac_power if /usr/ is on the root
# partition.
PATH=/sbin:/bin:/usr/bin
FSCK_LOGFILE=/var/log/fsck/checkroot
[ "$FSCKFIX" ] || FSCKFIX=no
[ "$SULOGIN" ] || SULOGIN=no
. /lib/init/vars.sh

. /lib/lsb/init-functions
. /lib/init/mount-functions.sh

do_start () {
	# Trap SIGINT so that we can handle user interrupt of fsck.
	trap "" INT

	#
	# Set SULOGIN in /etc/default/rcS to yes if you want a sulogin to
	# be spawned from this script *before anything else* with a timeout,
	# like sysv does.
	#
	[ "$SULOGIN" = yes ] && sulogin -t 30 $CONSOLE

	KERNEL="$(uname -s)"
	MACHINE="$(uname -m)"

	read_fstab

	#
	# Activate the swap device(s) in /etc/fstab. This needs to be done
	# before fsck, since fsck can be quite memory-hungry.
	#
	ENABLE_SWAP=no
	case "$KERNEL" in
	  Linux)
	  	if [ "$NOSWAP" = yes ]
		then
			[ "$VERBOSE" = no ] || log_warning_msg "Not activating swap as requested via bootoption noswap."
			ENABLE_SWAP=no
		else
			if [ "$swap_on_lv" = yes ]
			then
				[ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on logical volume."
			elif [ "$swap_on_file" = yes ]
			then
				[ "$VERBOSE" = no ] || log_warning_msg "Not activating swap on swapfile."
			else
				ENABLE_SWAP=yes
			fi
		fi
		;;
	  *)
		ENABLE_SWAP=yes
		;;
	esac
	if [ "$ENABLE_SWAP" = yes ]
	then
		if [ "$VERBOSE" = no ]
		then
			log_action_begin_msg "Activating swap"
			swapon -a -e >/dev/null 2>&1
			log_action_end_msg $?
		else
			log_daemon_msg "Activating swap"
			swapon -a -v
			log_end_msg $?
		fi
	fi

	#
	# Does the root device in /etc/fstab match with the actual device ?
	# If not we try to use the /dev/root alias device, and if that
	# fails we create a temporary node in /run.
	#
	# Do this only on Linux. Neither kFreeBSD nor Hurd have
	# /dev/root and the device ids used here are specific to
	# Linux.
	KERNEL="$(uname)"
	if [ "$rootcheck" = yes ] && [ "$KERNEL" = Linux ]
	then
		ddev="$(mountpoint -qx $rootdev)"
		rdev="$(mountpoint -d /)"
		if [ "$ddev" != "$rdev" ] && [ "$ddev" != "4:0" ]
		then
			if [ "$(mountpoint -qx /dev/root)" = "4:0" ]
			then
				rootdev=/dev/root
			else
				if \
					rm -f /run/rootdev \
					&& mknod -m 600 /run/rootdev b ${rdev%:*} ${rdev#*:} \
					&& [ -e /run/rootdev ]
				then
					rootdev=/run/rootdev
				else
					rootfatal=yes
				fi
			fi
		fi
	fi

	#
	# Bother, said Pooh.
	#
	if [ "$rootfatal" = yes ]
	then
		log_failure_msg "The device node $rootdev for the root filesystem is missing or incorrect 
or there is no entry for the root filesystem listed in /etc/fstab. 
The system is also unable to create a temporary node in /run. 
This means you have to fix the problem manually."
		log_warning_msg "A maintenance shell will now be started. 
CONTROL-D will terminate this shell and restart the system."
		# Start a single user shell on the console
		if ! sulogin $CONSOLE
		then
			log_failure_msg "Attempt to start maintenance shell failed. 
Will restart in 5 seconds."
			sleep 5
		fi
		[ "$VERBOSE" = no ] || log_action_msg "Will now restart"
		reboot -f
	fi

	# See if we're on AC Power.  If not, we're not gonna run our
	# check.  If on_ac_power (in /usr/) is unavailable, behave as
	# before and check all file systems needing it.
# Disabled AC power check until fsck can be told to only check the
# file system if it is corrupt when running on battery. (bug #526398)
#	if which on_ac_power >/dev/null 2>&1 && [ "$rootcheck" = yes ]
#	then
#		on_ac_power >/dev/null 2>&1
#		if [ "$?" -eq 1 ]
#		then
#			log_warning_msg "On battery power, so skipping file system check."
#			rootcheck=no
#		fi
#	fi

	#
	# See if we want to check the root file system.
	#
	FSCKCODE=0

	if [ -e /run/initramfs/fsck-root ]
	then
		rootcheck=no
	fi

	if is_fastboot_active
	then
		[ "$rootcheck" = yes ] && log_warning_msg "Fast boot enabled, so skipping root file system check."
		rootcheck=no
	fi

	if which findmnt >/dev/null 2>&1
	then
		if [ "$(findmnt -f -n -o FSTYPE /)" = "btrfs" ]
		then
			[ "$rootcheck" = yes ] && log_warning_msg "btrfs root detected, so skipping root file system check."
			rootcheck=no
		fi
	fi

	if [ "$rootcheck" = yes ]
	then
		#
		# Ensure that root is quiescent and read-only before fsck'ing.
		#
		# mount -n -o remount,ro / would be the correct syntax but
		# mount can get confused when there is a "bind" mount defined
		# in fstab that bind-mounts "/" somewhere else.
		#
		# So we use mount -n -o remount,ro $rootdev / but that can
		# fail on older kernels on sparc64/alpha architectures due
		# to a bug in sys_mount().
		#
		# As a compromise we try both.
		#
		if \
			! mount    -n -o remount,ro              $rootdev /              \
			&& ! mount -n -o remount,ro -t dummytype $rootdev /  2>/dev/null \
			&& ! mount -n -o remount,ro                       /  2>/dev/null
		then
			log_failure_msg "Cannot check root file system because it is not mounted read-only."
			rootcheck=no
		fi
	fi

	#
	# The actual checking is done here.
	#
	if [ "$rootcheck" = yes ]
	then
		if [ -f /forcefsck ] || grep -q -s -w -i "forcefsck" /proc/cmdline
		then
			force="-f"
		else
			force=""
		fi

		if [ "$FSCKFIX" = yes ]
		then
			fix="-y"
		else
			fix="-a"
		fi

		spinner="-C"
		case "$TERM" in
		  dumb|network|unknown|"")
			spinner="" ;;
		esac
		# This Linux/s390x special case should go away.
		if [ "${KERNEL}:${MACHINE}" = Linux:s390x ]
		then
			spinner=""
		fi
		
		if [ "$VERBOSE" = no ]
		then
			log_action_begin_msg "Checking root file system"
			logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -t $roottype $rootdev
			FSCKCODE=$?
			if [ "$FSCKCODE" = 0 ]
			then
				log_action_end_msg 0
			else
				log_action_end_msg 1 "code $FSCKCODE"
			fi
		else
			log_daemon_msg "Will now check root file system"
			logsave -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t $roottype $rootdev
			FSCKCODE=$?
			log_end_msg $FSCKCODE
		fi
	fi

	#
	# If there was a failure, drop into single-user mode.
	#
	# NOTE: "failure" is defined as exiting with a return code of
	# 4 or larger. A return code of 1 indicates that file system
	# errors were corrected but that the boot may proceed. A return
	# code of 2 or 3 indicates that the system should immediately reboot.
	#
	if [ "$FSCKCODE" -eq 32 ]
	then
		log_warning_msg "File system check was interrupted by user"
	elif [ "$FSCKCODE" -gt 3 ]
	then
		# Surprise! Re-directing from a HERE document (as in "cat << EOF")
		# does not work because the root is currently read-only.
		log_failure_msg "An automatic file system check (fsck) of the root filesystem failed. 
A manual fsck must be performed, then the system restarted. 
The fsck should be performed in maintenance mode with the 
root filesystem mounted in read-only mode."
		log_warning_msg "The root filesystem is currently mounted in read-only mode. 
A maintenance shell will now be started. 
After performing system maintenance, press CONTROL-D 
to terminate the maintenance shell and restart the system."
		# Start a single user shell on the console
		if ! sulogin $CONSOLE
		then
			log_failure_msg "Attempt to start maintenance shell failed. 
Will restart in 5 seconds."
			sleep 5
		fi
		[ "$VERBOSE" = no ] || log_action_msg "Will now restart"
		reboot -f
	elif [ "$FSCKCODE" -gt 1 ]
	then
		log_failure_msg "The file system check corrected errors on the root partition 
but requested that the system be restarted."
		log_warning_msg "The system will be restarted in 5 seconds."
		sleep 5
		[ "$VERBOSE" = no ] || log_action_msg "Will now restart"
		reboot -f
	fi

	#
	# Remount root to final mode (rw or ro).
	#
	# See the comments above at the previous "mount -o remount"
	# for an explanation why we try this twice.
	#
	if ! mount -n -o remount,$rootopts,$rootmode $fstabroot / 2>/dev/null
	then
		mount -n -o remount,$rootopts,$rootmode /
	fi

	# If possible, migrate /etc/mtab to be a symlink to
	# /proc/mounts.  Note that not all systems e.g. Hurd currently
	# support this.
	if [ "$rootmode" != "ro" ]; then
		mtab_migrate
	fi

	if selinux_enabled && [ -x /sbin/restorecon ] && [ -r /etc/mtab ]
	then
		restorecon /etc/mtab
	fi

	#
	# Remove /run/rootdev if we created it.
	#
	rm -f /run/rootdev

	# Update mount options for mounts created in early boot
	# S01mountkernfs.sh
	/etc/init.d/mountkernfs.sh reload
	# S03mountdevsubfs.sh
	/etc/init.d/mountdevsubfs.sh reload

}

do_status () {
	# If / is read-write or swap is enabled, this script have done
	# its job.
	rootrw=false
	swapon=false
	if [ -f /etc/mtab ] ; then
	    if grep " / " /etc/mtab |grep -q rw ; then
		rootrw=true
	    fi
	fi
	if [ -f /proc/swaps ] ; then
	    if [ "$(cat /proc/swaps |grep -v ^Filename)" ] ; then
		swapon=true
	    fi
	fi
	if [ true = "$rootrw" ] || [ true = "$swapon" ] ; then
		return 0
	else
		return 4
	fi
}

case "$1" in
  start|"")
	do_start
	;;
  restart|reload|force-reload)
	echo "Error: argument '$1' not supported" >&2
	exit 3
	;;
  stop)
	# No-op
	;;
  status)
	do_status
	exit $?
	;;
  *)
	echo "Usage: checkroot.sh [start|stop]" >&2
	exit 3
	;;
esac

: