On Sun, 2009-11-29 at 13:56 +0100, Marco d'Itri wrote: > On Nov 28, Bastian Blank <wa...@debian.org> wrote: > > > The Linux image packages needs to do some modifications to core > > configuration files like fstab in the future to allow newer kernels to > > work. To do this and the planned further extension I intend to make all > > linux image packages depend on python. > This is not justified. > I will be happy to rewrite in perl whatever you need.
Find attached an initial attempt to use shell only. Let me know if you are interested. The script is configurable, so a sysadmin can decide to re-rewrite fstab using DM/LVM names rather than UUID, or volume LABEL, or legacy /dev/hd* names. Known bugs/limitation: * Should accept command line arguments * Some devices may need to be blacklisted * What about removable media? (UUID of media in CDROM? ouch) * Should actually write fstab ;) I have hesitated to probe the current /dev or to use blkid... I can change that easily. I think this script should have a companion, to insert/update a comments line above each fstab entry (à-la Debian-Installer) Franklin
#!/bin/sh set -e # update-fstab-persistent-names - Rewrite current fstab # (Using your prefered device naming). # # Copyright 2009, Frank Lin PIAT <fp...@klabs.be> # Licensed under GPLv2 or later # # Known bugs/limitation # * Should actually _write_ fstab ;) # * Doesn't accept command line arguments # * Some devices may need to be blacklisted # * What about removable media? # ====== User configurable variables ====== # # Prefered device naming scheme to use in fstab. **Order matters**. # dm : use /dev/grpname/logvolname for LVM volumes # : or /dev/mapper/dmname for CRYPT and other. # uuid : use UUID=cafecafe (based on the FS's volume UUID) # label : use LABEL=foo (based on the FS's volume name) # plaindev : use legacy /dev/ devices. PREFERED_NAME='dm uuid label plaindev' # Rewrite existing LABEL=foo lines in fstab REWRITE_LABELS=1 # Rewrite existing UUID=foo lines in fstab REWRITE_UUIDS=1 # ====== End of user configurable variables ====== # # Let's declare some functions... # Initialise a sed file to rewrite fstab, based on device major/minor IDs. # (this temporary sed file search and replace all possible names for the # local devices, with a fake unique ID "#DEVICE=X.Y" where X and Y are # the device's major and minor numbers) generate_simple_fstab_sed() { # Sed rule to rewrite /dev/* entry as #DEVICE=X:Y find /dev/ \( -type b -o -type l \) \ \! -path '/dev/.udev/*' \! -path '/dev/.static/*' \ -iregex '^[a-z0-9./_-]*$' -printf '%Y\t%p\n' \ | sed -n -e 's/^b\t\(.*\)/\1/p' \ | while read s ; do printf 's\t^%s\>\t#DEVICE=%d:%d\t\n' \ "$s" \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" done # Sed rule to rewrite existing LABELS=* entry as #DEVICE=X:Y if [ "$REWRITE_LABELS" = "1" -a -d /dev/disk/by-label ]; then find /dev/disk/by-label/ -type l -iregex '^[a-z0-9./_-]*$' \ | while read s ; do \ printf 's\t^%s\>\t#DEVICE=%d:%d\t\n' \ "LABEL=$(basename $s)" \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" done fi # Sed rule to rewrite existing UUID=* entry as #DEVICE=X:Y if [ "$REWRITE_UUIDS" = "1" -a -d /dev/disk/by-uuid ]; then find /dev/disk/by-uuid/ -type l -iregex '^[a-z0-9./_-]*$' \ | while read s ; do \ printf 's\t^%s\>\t#DEVICE=%d:%d\tg\n' \ "UUID=$(basename $s)" \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" done fi } # create a list of device-major-minor -> /dev/vg/lv for LVM. use_dm_legacy() { which vgs 2>&1 > /dev/null || return 0 LVM_VGS="$(vgs --all -o vg_name --noheadings | sed -e 's#^\s*#/dev/#')" [ ! "$LVM_VGS" ] && return 0 find $LVM_VGS -maxdepth 1 -type l -iregex '^[a-z0-9./_-]*$' \ | while read s ; do \ printf 's\t#DEVICE=%d:%d\t%s\t\n' \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" \ "$s" done } # create a list of device-major-minor -> /dev/vg/lv # or -> /dev/mapper/name for dmsetup (LVM/DM/CRYPT...) use_dm_new() { which dmsetup 2>&1 > /dev/null || return 0 dmsetup info -c --noheadings --separator="$(printf "\t")" \ -o major,minor,name,vg_name,lv_name \ | while read maj min name vg lv ; do if [ "$vg" -a "$lv" -a -b /dev/$vg/$lv ] ; then DEV=/dev/$vg/$lv else DEV=/dev/mapper/$name fi if [ -b $DEV ]; then printf "s\t#DEVICE=%d:%d\t%s\t\n" $maj $min $DEV fi done } # Disaptcher to create a list of device-major-minor -> /dev/vg/lv # or -> /dev/mapper/diskmappername, depending on dmsetup version. use_dm() { which dmsetup 2>&1 > /dev/null || return 0 # Lenny's dmsetup don't provide "lv_name" if dmsetup --noheadings info -c -o lv_name >/dev/null 2>&1; then use_dm_new else use_dm_legacy fi } # create a list of device-major-minor -> uuid use_uuid() { [ ! -d /dev/disk/by-uuid ] && return 0 find /dev/disk/by-uuid/ -type l -iregex '^[a-z0-9./_-]*$' \ | while read s ; do \ printf 's\t#DEVICE=%d:%d\t%s\t\n' \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" \ "UUID=$(basename $s)" done } # create a list of device-major-minor -> label use_label() { [ ! -d /dev/disk/by-label ] && return 0 find /dev/disk/by-label/ -type l -iregex '^[a-z0-9./_-]*$' \ | while read s ; do \ printf 's\t#DEVICE=%d:%d\t%s\t\n' \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" \ "LABEL=$(basename $s)" done } # create a list of device-major-minor -> /dev use_plaindev() { find /dev/ -maxdepth 1 -type b '!' -path '/dev/.udev/*' \ | grep -v '/dev/dm-' \ | while read s ; do \ printf 's\t#DEVICE=%d:%d\t%s\t\n' \ "$(stat -L -c '0x%t' "$s")" \ "$(stat -L -c '0x%T' "$s")" \ "$s" done } # Drop remaining entries which have no sane equivalement. use_dropunknown() { echo '/#DEVICE=/d' } # Drop null rules use_dropnullrules() { echo '/^s\t^\([^\t]\+\)\\>\t\1\t/d' } # ====== End of Function declaration ====== # WDIR="$(mktemp -d -t $(basename $0).XXX)" trap 'if [ "$WDIR" ]; then rm -f $WDIR/* ; rmdir $WDIR ; fi' EXIT #Don't purge to debug#WDIR="/tmp/this-is-a-test" # Initialise a sed file to rewrite fstab generate_simple_fstab_sed > $WDIR/fstab.sed # Now, let's poke the sed file to use sensible devices names # instead of the fake "#DEVICE=X.Y". i=1 last_tweak=".0.orig" for p in $PREFERED_NAME dropunknown dropnullrules ; do case $p in dm|uuid|label|plaindev|dropunknown|dropnullrules) sedtweak=$WDIR/tweak_${i}_Use_$p.sed use_$p > $sedtweak sed -i$last_tweak -f $sedtweak $WDIR/fstab.sed last_tweak=".$i.$p" ;; *) echo "Error: Invalid preference value \"$p\" for option PREFFERED_NAME" 1>&2 ;; esac i=$((i + 1)) done # And Finaly... sed -f $WDIR/fstab.sed /etc/fstab