mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
This fragment, not enabled by default, allows stack traces to be captured and displayed by gdb in case the daemon crashes.
249 lines
6.5 KiB
Bash
Executable File
249 lines
6.5 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
echo Starting /init script ...
|
||
|
||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||
export PATH
|
||
|
||
# Debian bug 606622.
|
||
RUNLEVEL=S
|
||
PREVLEVEL=N
|
||
export RUNLEVEL PREVLEVEL
|
||
|
||
# Make sure /tmp /var/tmp are real directories, not symlinks.
|
||
if [ ! -d /tmp ] || [ ! -d /var/tmp ]; then
|
||
rm -f /tmp /var/tmp
|
||
mkdir /tmp /var/tmp
|
||
chmod 1777 /tmp /var/tmp
|
||
fi
|
||
|
||
# Try to print a stack trace for segfaults inside the appliance.
|
||
for d in /lib64 /lib; do
|
||
f=$d/libSegFault.so
|
||
if [ -f "$f" ]; then
|
||
LD_PRELOAD=$f
|
||
export LD_PRELOAD
|
||
break
|
||
fi
|
||
done
|
||
|
||
mkdir -p /sysroot
|
||
|
||
# Mount /proc.
|
||
if [ ! -d /proc ]; then rm -f /proc; fi
|
||
mkdir -p /proc
|
||
mount -t proc /proc /proc
|
||
|
||
# Parse the kernel command line early (must be after /proc is mounted).
|
||
cmdline=$(</proc/cmdline)
|
||
|
||
if [[ $cmdline == *guestfs_verbose=1* ]]; then
|
||
guestfs_verbose=1
|
||
set -x
|
||
fi
|
||
if [[ $cmdline == *guestfs_network=1* ]]; then
|
||
guestfs_network=1
|
||
fi
|
||
if [[ $cmdline == *guestfs_rescue=1* ]]; then
|
||
guestfs_rescue=1
|
||
fi
|
||
if [[ $cmdline == *guestfs_noreboot=1* ]]; then
|
||
guestfs_noreboot=1
|
||
fi
|
||
if [[ $cmdline == *guestfs_boot_analysis=1* ]]; then
|
||
guestfs_boot_analysis=1
|
||
fi
|
||
|
||
# Mount the other special filesystems.
|
||
if [ ! -d /sys ]; then rm -f /sys; fi
|
||
mkdir -p /sys
|
||
mount -t sysfs /sys /sys
|
||
# taken from initramfs-tools/init --Hilko Bengen
|
||
mkdir -p /run
|
||
mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run
|
||
mkdir -p /run/lock
|
||
ln -s ../run/lock /var/lock
|
||
|
||
# On Fedora 23, util-linux creates /etc/mtab in %post .. stupid
|
||
# and e2fsprogs fails if the link doesn't exist .. stupid stupid
|
||
if ! test -e /etc/mtab; then
|
||
ln -s /proc/mounts /etc/mtab
|
||
fi
|
||
|
||
# devtmpfs is required since udev 176
|
||
mount -t devtmpfs /dev /dev
|
||
mkdir -p /dev/pts
|
||
mount -t devpts /dev/pts /dev/pts
|
||
|
||
if [[ $cmdline == *selinux=1* ]]; then
|
||
mount -t selinuxfs none /sys/fs/selinux
|
||
fi
|
||
|
||
# Static nodes must happen before udev is started.
|
||
|
||
# Set up kmod static-nodes (RHBZ#1011907).
|
||
mkdir -p /run/tmpfiles.d
|
||
kmod static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf
|
||
|
||
# Create a machine-id with a random UUID
|
||
machine_id=$(dd if=/dev/urandom bs=16 count=1 status=none | od -x -A n)
|
||
echo "${machine_id// /}" > /etc/machine-id
|
||
|
||
# Set up tmpfiles (must run after kmod.conf is created above).
|
||
systemd-tmpfiles --prefix=/dev --prefix=/run --prefix=/var/run --create --boot
|
||
|
||
# Find udevd and run it directly.
|
||
for f in /lib/systemd/systemd-udevd /usr/lib/systemd/systemd-udevd \
|
||
/sbin/udevd /lib/udev/udevd \
|
||
/usr/lib/udev/udevd; do
|
||
if [ -x "$f" ]; then UDEVD="$f"; break; fi
|
||
done
|
||
if [ -z "$UDEVD" ]; then
|
||
echo "error: udev not found! Things will probably not work ..."
|
||
fi
|
||
|
||
$UDEVD --daemon #--debug
|
||
udevadm trigger
|
||
udevadm settle --timeout=600
|
||
|
||
# Disk optimizations.
|
||
# Increase the SCSI timeout so we can read remote images.
|
||
shopt -s nullglob
|
||
for f in /sys/block/sd*/device/timeout; do echo 300 > $f; done
|
||
# https://access.redhat.com/site/solutions/5427
|
||
for f in /sys/block/{h,s,ub,v}d*/queue/scheduler; do echo noop > $f; done
|
||
shopt -u nullglob
|
||
|
||
# Set up the network.
|
||
ip addr add 127.0.0.1/8 brd + dev lo scope host
|
||
ip link set dev lo up
|
||
|
||
if test "$guestfs_network" = 1; then
|
||
iface=$(ls -I all -I default -I lo /proc/sys/net/ipv4/conf)
|
||
touch /etc/fstab # Workaround for Ubuntu.
|
||
if dhclient --version >/dev/null 2>&1; then
|
||
dhclient $iface
|
||
else
|
||
dhcpcd $iface
|
||
fi
|
||
fi
|
||
|
||
# Scan for MDs.
|
||
mdadm -As --auto=yes --run
|
||
|
||
# Scan for LVM.
|
||
modprobe dm_mod ||:
|
||
|
||
lvm vgchange -aay --sysinit
|
||
|
||
# Scan for Windows dynamic disks.
|
||
ldmtool create all
|
||
|
||
# These are useful when debugging.
|
||
if test "$guestfs_verbose" = 1 && test "$guestfs_boot_analysis" != 1; then
|
||
uname -a
|
||
ls -lR /dev
|
||
cat /proc/mounts
|
||
lvm pvs
|
||
lvm vgs
|
||
lvm lvs
|
||
ip a
|
||
ip r
|
||
lsmod
|
||
#hwclock -r
|
||
date
|
||
echo -n "clocksource: "
|
||
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
|
||
#ping -n -v -c 5 8.8.8.8
|
||
|
||
echo -n "uptime: "; cat /proc/uptime
|
||
fi
|
||
|
||
# Run the daemon.
|
||
cmd="guestfsd"
|
||
eval `grep -Eo 'guestfs_channel=[^[:space:]]+' /proc/cmdline`
|
||
if test "x$guestfs_channel" != "x"; then
|
||
cmd="$cmd --channel $guestfs_channel"
|
||
fi
|
||
if test "$guestfs_verbose" = 1; then
|
||
cmd="$cmd --verbose"
|
||
fi
|
||
if test "$guestfs_network" = 1; then
|
||
cmd="$cmd --network"
|
||
fi
|
||
if false; then
|
||
# To get a stack trace if the daemon crashes:
|
||
# (1) change this section to 'if true'
|
||
# (2) add 'gdb' to 'appliance/packagelist.in'
|
||
unset LD_PRELOAD
|
||
echo set pagination off > /tmp/gdb-script
|
||
echo run >> /tmp/gdb-script
|
||
echo info registers >> /tmp/gdb-script
|
||
echo 'x/16i $pc' >> /tmp/gdb-script
|
||
echo t a a bt >> /tmp/gdb-script
|
||
echo quit >> /tmp/gdb-script
|
||
cmd="gdb -batch -x /tmp/gdb-script --args $cmd"
|
||
fi
|
||
if ! test "$guestfs_rescue" = 1; then
|
||
echo $cmd
|
||
$cmd
|
||
else
|
||
# Run virt-rescue shell.
|
||
|
||
# We need a daemon, even in virt-rescue.
|
||
$cmd &
|
||
|
||
# XXX This gives a bit of time for virt-rescue to connect to the
|
||
# daemon and mount any filesystems.
|
||
sleep 2
|
||
|
||
# Get name of the serial port, from console= passed by libguestfs.
|
||
# XXX Consider using /proc/consoles
|
||
guestfs_serial=$(grep -Eo 'console=[^[:space:]]+' /proc/cmdline |
|
||
sed s/console=//)
|
||
|
||
# Remove LD_PRELOAD=libSegFault set above.
|
||
unset LD_PRELOAD
|
||
|
||
:> $HOME/.bashrc
|
||
grep -Eo 'TERM=[^[:space:]]+' /proc/cmdline >> $HOME/.bashrc
|
||
echo "PS1='><rescue> '" >> $HOME/.bashrc
|
||
echo "export TERM PS1" >> $HOME/.bashrc
|
||
|
||
# The shell is opened by default on /dev/console, which (on Linux)
|
||
# is not a controlling terminal, causing job control to fail. For
|
||
# how we work around this, see:
|
||
# https://busybox.net/FAQ.html#job_control
|
||
run_bash_with_ctty ()
|
||
{
|
||
setsid bash -c \
|
||
"exec bash </dev/$guestfs_serial >/dev/$guestfs_serial 2>&1"
|
||
}
|
||
|
||
echo
|
||
echo "------------------------------------------------------------"
|
||
echo
|
||
echo "Welcome to virt-rescue, the libguestfs rescue shell."
|
||
echo
|
||
echo "Note: The contents of / (root) are the rescue appliance."
|
||
if ! test -d "/sysroot/dev"; then
|
||
echo "You have to mount the guest’s partitions under /sysroot"
|
||
echo "before you can examine them."
|
||
else
|
||
echo "Use 'cd /sysroot' or 'chroot /sysroot' to see guest filesystems."
|
||
fi
|
||
echo
|
||
run_bash_with_ctty
|
||
echo
|
||
echo "virt-rescue: Syncing the disk now before exiting ..."
|
||
echo
|
||
fi
|
||
|
||
sync
|
||
|
||
if ! test "$guestfs_noreboot" = 1; then
|
||
# qemu has the -no-reboot flag, so issuing a reboot here actually
|
||
# causes qemu to exit gracefully.
|
||
reboot -f
|
||
fi
|