base/init: save timestamp earlier and remove /sys mount duplicate
[dracut.git] / modules.d / 99base / init
blobf576e35169956603b6352ac5515907d9f2a5a59f
1 #!/bin/sh
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
5 # Licensed under the GPLv2
7 # Copyright 2008-2010, Red Hat, Inc.
8 # Harald Hoyer <harald@redhat.com>
9 # Jeremy Katz <katzj@redhat.com>
11 wait_for_loginit()
13 set +x
14 [ "$RD_DEBUG" = "yes" ] || return
15 [ -e /run/initramfs/loginit.pipe ] || return
16 echo "DRACUT_LOG_END"
17 exec 0<>/dev/console 1<>/dev/console 2<>/dev/console
18 # wait for loginit
19 i=0
20 while [ $i -lt 10 ]; do
21 if [ ! -e /run/initramfs/loginit.pipe ]; then
22 j=$(jobs)
23 [ -z "$j" ] && break
24 [ -z "${j##*Running*}" ] || break
26 sleep 0.1
27 i=$(($i+1))
28 done
30 if [ $i -eq 10 ]; then
31 kill %1 >/dev/null 2>&1
32 kill $(while read line;do echo $line;done</run/initramfs/loginit.pid)
35 set -x
36 rm -f /run/initramfs/loginit.pipe /run/initramfs/loginit.pid
39 emergency_shell()
41 set +e
42 if [ "$1" = "-n" ]; then
43 _rdshell_name=$2
44 shift 2
45 else
46 _rdshell_name=dracut
48 echo ; echo
49 warn $@
50 source_hook emergency
51 echo
52 wait_for_loginit
53 [ -e /run/initramfs/.die ] && exit 1
54 if getargbool 1 rd.shell -y rdshell || getarg rd.break rdbreak; then
55 echo "Dropping to debug shell."
56 echo
57 export PS1="$_rdshell_name:\${PWD}# "
58 [ -e /.profile ] || echo "exec 0<>/dev/console 1<>/dev/console 2<>/dev/console" > /.profile
59 sh -i -l
60 else
61 warn "Boot has failed. To debug this issue add \"rdshell\" to the kernel command line."
62 # cause a kernel panic
63 exit 1
67 NEWROOT="/sysroot"
68 [ -d $NEWROOT ] || mkdir -p -m 0755 $NEWROOT
70 trap "emergency_shell Signal caught!" 0
71 OLDPATH=$PATH
72 PATH=/usr/sbin:/usr/bin:/sbin:/bin
73 export PATH
75 RD_DEBUG=""
76 . /lib/dracut-lib.sh
78 [ -c /dev/null ] || mknod -m 0666 /dev/null c 1 3
80 # mount some important things
81 [ ! -d /proc/self ] && \
82 mount -t proc -o nosuid,noexec,nodev /proc /proc >/dev/null 2>&1
84 [ ! -d /sys/kernel ] && \
85 mount -t sysfs -o nosuid,noexec,nodev /sys /sys >/dev/null 2>&1
87 if [ -x /lib/systemd/systemd-timestamp ]; then
88 RD_TIMESTAMP=$(/lib/systemd/systemd-timestamp)
89 else
90 read RD_TIMESTAMP _tmp < /proc/uptime
91 unset _tmp
94 setdebug
96 if [ "$RD_DEBUG" = "yes" ]; then
97 getarg quiet && DRACUT_QUIET="yes"
98 a=$(getarg loglevel=)
99 [ -n "$a" ] && [ $a -ge 8 ] && unset DRACUT_QUIET
102 if ! ismounted /dev; then
103 # try to mount devtmpfs
104 if ! mount -t devtmpfs -o mode=0755,nosuid,noexec udev /dev >/dev/null 2>&1; then
105 # if it failed fall back to normal tmpfs
106 mount -t tmpfs -o mode=0755,nosuid udev /dev >/dev/null 2>&1
107 # Make some basic devices first, let udev handle the rest
108 mknod -m 0666 /dev/null c 1 3
109 mknod -m 0666 /dev/ptmx c 5 2
110 mknod -m 0600 /dev/console c 5 1
111 mknod -m 0660 /dev/kmsg c 1 11
115 # prepare the /dev directory
116 [ ! -h /dev/fd ] && ln -s /proc/self/fd /dev/fd >/dev/null 2>&1
117 [ ! -h /dev/stdin ] && ln -s /proc/self/fd/0 /dev/stdin >/dev/null 2>&1
118 [ ! -h /dev/stdout ] && ln -s /proc/self/fd/1 /dev/stdout >/dev/null 2>&1
119 [ ! -h /dev/stderr ] && ln -s /proc/self/fd/2 /dev/stderr >/dev/null 2>&1
121 if ! ismounted /dev/pts; then
122 mkdir -m 0755 /dev/pts
123 mount -t devpts -o gid=5,mode=620,noexec,nosuid devpts /dev/pts >/dev/null 2>&1
126 if ! ismounted /dev/shm; then
127 mkdir -m 0755 /dev/shm
128 mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs /dev/shm >/dev/null 2>&1
131 if ! ismounted /run; then
132 mkdir -m 0755 /newrun
133 mount -t tmpfs -o mode=0755,nosuid,nodev tmpfs /newrun >/dev/null 2>&1
134 cp -a -t /newrun /run/*
135 mount --move /newrun /run
136 rm -fr /newrun
139 UDEVVERSION=$(udevadm --version)
140 if [ $UDEVVERSION -gt 166 ]; then
141 # newer versions of udev use /run/udev/rules.d
142 export UDEVRULESD=/run/udev/rules.d
143 else
144 mkdir -m 0755 /dev/.udev /dev/.udev/rules.d
145 export UDEVRULESD=/dev/.udev/rules.d
148 if [ "$RD_DEBUG" = "yes" ]; then
149 mkfifo /run/initramfs/loginit.pipe
150 loginit $DRACUT_QUIET </run/initramfs/loginit.pipe >/dev/console 2>&1 &
151 exec >/run/initramfs/loginit.pipe 2>&1
152 else
153 exec 0<>/dev/console 1<>/dev/console 2<>/dev/console
156 source_conf /etc/conf.d
158 # run scriptlets to parse the command line
159 getarg 'rd.break=cmdline' 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline"
160 source_hook cmdline
162 [ -z "$root" ] && die "No or empty root= argument"
163 [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"
165 # Network root scripts may need updated root= options,
166 # so deposit them where they can see them (udev purges the env)
168 echo "root='$root'"
169 echo "rflags='$rflags'"
170 echo "fstype='$fstype'"
171 echo "netroot='$netroot'"
172 echo "NEWROOT='$NEWROOT'"
173 } > /tmp/root.info
175 # pre-udev scripts run before udev starts, and are run only once.
176 getarg 'rd.break=pre-udev' 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev"
177 source_hook pre-udev
179 # start up udev and trigger cold plugs
180 udevd --daemon --resolve-names=never
182 UDEV_LOG_PRIO_ARG=--log-priority
183 UDEV_QUEUE_EMPTY="udevadm settle --timeout=0"
185 if [ $UDEVVERSION -lt 140 ]; then
186 UDEV_LOG_PRIO_ARG=--log_priority
187 UDEV_QUEUE_EMPTY="udevadm settle --timeout=1"
190 getargbool 0 rd.udev.info -y rdudevinfo && udevproperty "$UDEV_LOG_PRIO_ARG=info"
191 getargbool 0 rd.udev.debug -y rdudevdebug && udevproperty "$UDEV_LOG_PRIO_ARG=debug"
192 udevproperty "hookdir=$hookdir"
194 getarg 'rd.break=pre-trigger' 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger"
195 source_hook pre-trigger
197 # then the rest
198 udevadm trigger --action=add $udevtriggeropts >/dev/null 2>&1
200 getarg 'rd.break=initqueue' 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue"
202 RDRETRY=$(getarg rd.retry 'rd_retry=')
203 RDRETRY=${RDRETRY:-20}
204 RDRETRY=$(($RDRETRY*2))
207 while :; do
209 check_finished && break
211 udevsettle
213 check_finished && break
215 if [ -f $hookdir/initqueue/work ]; then
216 rm $hookdir/initqueue/work
219 for job in $hookdir/initqueue/*.sh; do
220 [ -e "$job" ] || break
221 job=$job . $job
222 check_finished && break 2
223 done
225 $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue
227 for job in $hookdir/initqueue/settled/*.sh; do
228 [ -e "$job" ] || break
229 job=$job . $job
230 check_finished && break 2
231 done
233 $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue
235 # no more udev jobs and queues empty.
236 sleep 0.5
238 # dirty hack for some cdrom drives,
239 # which report no medium for quiet
240 # some time.
241 for cdrom in /sys/block/sr*; do
242 [ -e "$cdrom" ] || continue
243 # skip, if cdrom medium was already found
244 strstr "$(udevadm info --query=env --path=${cdrom##/sys})" \
245 ID_CDROM_MEDIA && continue
247 if [ -e "$cdrom"/events_poll_msecs -a ! -e "/tmp/.poll_${cdrom##*/}" ]; then
248 msecs=$(while read a; do echo $a;done < "$cdrom"/events_poll_msecs)
249 if [ "$msecs" = "-1" ]; then
250 echo 250 > "$cdrom"/events_poll_msecs
251 > "/tmp/.poll_${cdrom##*/}"
253 else
254 echo change > "$cdrom/uevent"
256 done
258 i=$(($i+1))
259 [ $i -gt $RDRETRY ] \
260 && { flock -s 9 ; emergency_shell "No root device \"$root\" found"; } 9>/.console_lock
261 done
262 unset job
263 unset queuetriggered
265 # reset cdrom polling
266 for cdrom in /sys/block/sr*; do
267 [ -e "$cdrom" ] || continue
268 if [ -e "$cdrom"/events_poll_msecs ]; then
269 echo -1 > "$cdrom"/events_poll_msecs
271 done
273 # pre-mount happens before we try to mount the root filesystem,
274 # and happens once.
275 getarg 'rd.break=pre-mount' 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break pre-mount"
276 source_hook pre-mount
279 getarg 'rd.break=mount' 'rdbreak=mount' && emergency_shell -n mount "Break mount"
280 # mount scripts actually try to mount the root filesystem, and may
281 # be sourced any number of times. As soon as one suceeds, no more are sourced.
283 while :; do
284 [ -d "$NEWROOT/proc" ] && break;
285 for f in $hookdir/mount/*.sh; do
286 [ -f "$f" ] && . "$f"
287 [ -d "$NEWROOT/proc" ] && break;
288 done
290 i=$(($i+1))
291 [ $i -gt 20 ] \
292 && { flock -s 9 ; emergency_shell "Can't mount root filesystem"; } 9>/.console_lock
293 done
296 echo -n "Mounted root filesystem "
297 while read dev mp rest; do [ "$mp" = "$NEWROOT" ] && echo $dev; done < /proc/mounts
298 } | vinfo
300 # pre pivot scripts are sourced just before we switch over to the new root.
301 getarg 'rd.break=pre-pivot' 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break pre-pivot"
302 source_hook pre-pivot
304 # by the time we get here, the root filesystem should be mounted.
305 # Try to find init.
306 for i in "$(getarg real_init=)" "$(getarg init=)" /sbin/init /etc/init /init /bin/sh; do
307 [ -n "$i" ] || continue
308 if ! [ -d "$NEWROOT$i" ] && [ -L "$NEWROOT$i" -o -x "$NEWROOT$i" ]; then
309 INIT="$i"
310 break
312 done
314 [ "$INIT" ] || {
315 echo "Cannot find init!"
316 echo "Please check to make sure you passed a valid root filesystem!"
317 emergency_shell
320 getarg rd.break rdbreak && emergency_shell -n switch_root "Break before switch_root"
322 if [ $UDEVVERSION -lt 168 ]; then
323 # stop udev queue before killing it
324 udevadm control --stop-exec-queue
326 HARD=""
327 while pidof udevd >/dev/null 2>&1; do
328 for pid in $(pidof udevd); do
329 kill $HARD $pid >/dev/null 2>&1
330 done
331 HARD="-9"
332 done
333 else
334 udevadm control --exit
335 udevadm info --cleanup-db
338 export RD_TIMESTAMP
339 set +x # Turn off debugging for this section
340 # Clean up the environment
341 for i in $(export -p); do
342 i=${i#declare -x}
343 i=${i#export}
344 strstr "$i" "=" || continue
345 i=${i%%=*}
346 [ -z "$i" ] && continue
347 case $i in
348 root|PATH|HOME|TERM|PS4|RD_*)
351 unset "$i";;
352 esac
353 done
355 initargs=""
356 read CLINE </proc/cmdline
357 if getarg init= >/dev/null ; then
358 set +x # Turn off debugging for this section
359 ignoreargs="console BOOT_IMAGE"
360 # only pass arguments after init= to the init
361 CLINE=${CLINE#*init=}
362 set -- $CLINE
363 shift # clear out the rest of the "init=" arg
364 for x in "$@"; do
365 for s in $ignoreargs; do
366 [ "${x%%=*}" = $s ] && continue 2
367 done
368 initargs="$initargs $x"
369 done
370 unset CLINE
371 else
372 set +x # Turn off debugging for this section
373 set -- $CLINE
374 for x in "$@"; do
375 case "$x" in
376 [0-9]|s|S|single|emergency|auto ) \
377 initargs="$initargs $x"
379 esac
380 done
382 [ "$RD_DEBUG" = "yes" ] && set -x
384 if [ -d "$NEWROOT"/run ]; then
385 NEWRUN="${NEWROOT}/run"
386 mount --bind /run "$NEWRUN"
387 NEWINITRAMFSROOT="$NEWRUN/initramfs"
389 if [ "$NEWINITRAMFSROOT/lib" -ef "/lib" ]; then
390 for d in bin etc lib lib64 sbin tmp usr var; do
391 [ -h /$d ] && ln -fsn $NEWINITRAMFSROOT/$d /$d
392 done
394 else
395 NEWRUN=/dev/.initramfs
396 mkdir -m 0755 "$NEWRUN"
397 mount --bind /run/initramfs "$NEWRUN"
400 wait_for_loginit
402 info "Switching root"
404 umount -l /run
406 unset PS4
408 CAPSH=$(command -v capsh)
409 SWITCH_ROOT=$(command -v switch_root)
410 PATH=$OLDPATH
411 export PATH
413 if [ -f /etc/capsdrop ]; then
414 . /etc/capsdrop
415 info "Calling $INIT with capabilities $CAPS_INIT_DROP dropped."
416 unset RD_DEBUG
417 exec $CAPSH --drop="$CAPS_INIT_DROP" -- \
418 -c "exec switch_root \"$NEWROOT\" \"$INIT\" $initargs" || \
420 warn "Command:"
421 warn capsh --drop=$CAPS_INIT_DROP -- -c exec switch_root "$NEWROOT" "$INIT" $initargs
422 warn "failed."
423 emergency_shell
425 else
426 unset RD_DEBUG
427 exec $SWITCH_ROOT "$NEWROOT" "$INIT" $initargs || {
428 warn "Something went very badly wrong in the initramfs. Please "
429 warn "file a bug against dracut."
430 emergency_shell