Sample Header Ad - 728x90

Safely eject USB live system asking the uesr to remove it

2 votes
0 answers
211 views
For my work I'm preparing a live USB with Clonezilla. It runs a custom bash script to clone disks. This USB is going to be cloned to several other USBs so they can be used in multiple machines. It's not possible to run Clonezilla to RAM since the image to clone (22G) is in the USB. I want to replicate, in my script, the standard behavior of live Linux distributions installer, that ask to remove the USB medium and then press enter to reboot the machine. Example script using eject, but this doesn't seem right:
eject /dev/sdb
read -r -p 'Remove USB and press Enter' # not executed since the USB is no longer plugged
reboot
I want to be *very* sure that the USB(s) are removed safely, since they are from work, they are many, and of course taking the risk of ruining them is not an option. **What would be the best and safest way to do this?** Now, why so much effort for a seemingly trivial thing? The USBs are going to be deployed to hundreds of machines. All that can be automated is needed to gain time and avoid errors. The users need to check the cloning worked, hence the reboot. But if the USB is still plugged, the machine will boot it instead of the local OS. This question is related but I understand it doesn't apply to a live system. ___ This is the script that seems to do this, from a Lubuntu that I got unsquashing the filesystem.squashfs file from the ISO. I'm still trying to understand it, any help appreciated.
#! /bin/sh

# Author: Mathieu Trudel-Lapierre 
#         Tollef Fog Heen 
#         Marco Amadori 
#

PATH=/usr/sbin:/usr/bin:/sbin:/bin
NAME=casper
SCRIPTNAME=/etc/init.d/${NAME}
DO_SNAPSHOT=/sbin/${NAME}-snapshot

# Exit if system was not booted by casper
[ -f /run/.casper-boot ] || exit 0

# Exit if the system was booted from an ISO image rather than a physical CD
grep -qs find_iso= /proc/cmdline && exit 0

# Read configuration variable file if it is present
[ -r /etc/$NAME.conf ] && . /etc/$NAME.conf

# Try to cache everything we're likely to need after ejecting.  This
# is fragile and simple-minded, but our options are limited.
cache_path() {
    path="$1"

    if [ -d "$path" ]; then
        for f in $(find "$path" -type f); do
            cache_path "$f"
        done
    elif [ -f "$path" ] && [ ! -L "$path" ]; then
        if [ -x "$path" ]; then
            if file -L "$path" | grep -q 'dynamically linked'; then
                for lib in $(ldd "$path" | awk '{ print $3 }'); do
                    cache_path "$lib"
                done
            fi
        fi
        echo -n >> "$path"
    fi
}

do_stop ()
{
    logger -t ${NAME} "resyncing snapshots and caching reboot files..."

    if [ ! -z "${ROOTSNAP}" ]; then
        $DO_SNAPSHOT --resync-string="${ROOTSNAP}"
    fi

    if [ ! -z "${HOMESNAP}" ]; then
        $DO_SNAPSHOT --resync-string="${HOMESNAP}"
    fi

    # check for netboot
    if [ ! -z "${NETBOOT}" ] || grep -qs netboot /proc/cmdline || grep -qsi root=/dev/nfs /proc/cmdline  || grep -qsi root=/dev/cifs /proc/cmdline ; then
        return 0
    fi

    # Don't prompt to eject the SD card on Babbage board, where we reuse it
    # as a quasi-boot-floppy. Technically this uses a bit of ubiquity
    # (archdetect), but since this is mostly only relevant for
    # installations, who cares ...
    if type archdetect >/dev/null 2>&1; then
        subarch="$(archdetect)"
        case $subarch in
            arm*/imx51)
                return 0
                ;;
        esac
    fi

    prompt=1
    if grep -qs noprompt /proc/cmdline || [ -e /run/casper-no-prompt ]; then
        prompt=
    fi

    for path in $(which halt) $(which reboot) /bin/chvt /etc/rc?.d /etc/default $(which stty) /bin/plymouth /lib/plymouth /lib/*/plymouth /lib/systemd /etc/systemd /lib/*/libnss_files* /etc/nsswitch.conf /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf /usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf /usr/share/fonts/truetype/ubuntu/UbuntuMono-R.ttf /etc/fonts/fonts.conf /etc/fonts/conf.d/60-latin.conf; do
        cache_path "$path"
    done

    device="$(grep " /cdrom " /proc/mounts | cut -d' ' -f1)" || device=
    # If /cdrom isn't mounted, don't try to eject it
    if [ -z "$device" ]; then
        return 0
    fi

    # If the device exists but can't be found in /sys/block, it's most likely a partition
    # so unmount it (lazy mode) and sync
    if [ -b "$device" ] && [ ! -f "/sys/block/$(basename $device)/removable" ]; then
        umount -l $device >/dev/null 2>&1
        sync
        # from now on operate on the partition's block device
        device=/dev/$(basename "$(readlink -f /sys/class/block/$(basename $device)/..)")
    fi

    # If we're still there, then we're probably a cdrom or other media
    # ship the eject if the kernel says the media isn't removable
    if [ "$(cat /sys/block/$(basename $device)/removable)" = "0" ]; then
        return 0
    fi

    # XXX - i18n
    MSG="Please remove the installation medium, then press ENTER: "
    MSG_FALLBACK="Please remove the installation medium, then reboot."

    if [ "$prompt" ]; then
        if [ -x /bin/plymouth ] && plymouth --ping; then
            chvt 63
            plymouth message --text="$MSG"
            clear > /dev/tty1
            echo $MSG_FALLBACK > /dev/tty1
        else
            stty sane  /dev/console
        fi
    fi

    eject -p -m $device >/dev/null 2>&1

    [ "$prompt" ] || return 0

    if [ -x /bin/plymouth ] && plymouth --ping; then
        plymouth watch-keystroke > /dev/null
    else
        read x < /dev/console
    fi
}

do_stop
Asked by schrodingerscatcuriosity (12812 rep)
Dec 14, 2021, 03:07 PM
Last activity: Dec 14, 2021, 06:13 PM