2013. október 4.

Lemezcsere futásidőben

Hot-swap merevlemezeket cserélni nem is annyira egyszerű. Behelyezés után általában felismeri a rendszer de az eszköznevek (/dev/sdX) cserélődését még ilyenkor is figyelni kell például UUID alapján. Ha ki is akarunk venni akkor még több teendőnk van: Lecsatolni az összes érintett fájlrendszert, leállítani a lemezt és megszüntetni az eszközt. Ezen kívül nem illik például használatban lévő swap lemezt sem kitépni. Szerencsére ezt is lehet automatizálni.


A disk-eject.sh script a következőket végzi el helyettünk.
  • Azonosító (UUID), kötetcímke (LABEL) vagy eszköznév (/dev/sdXY) alapján is megkeres egy partíciót és a hozzátartozó lemezt.
  • Lecsatolja az összes lemezen lévő partíciót (unmount)
  • Ellenőrzi hogy biztosan nincs a lemezen cserehely (swap) partíció használatban, illetve nincs rajta aktív szoftveres raid partíció.
  • Leállítja a lemezt (spindown) és eltávolítja a blokkeszközt a rendszerből a lemez biztonságos eltávolításhoz.
Például ha egy tartalék backup1 nevű partíciót tartalmazó lemezt akarunk kivenni:
disk-eject.sh LABEL="backup1"
Ha az azonosító formátuma egyértelmű a LABEL="" vagy UUID="" meghatározás elhagyható, viszont egynél több találatra a script nem fog lefutni. Aktív swap vagy raid esetén nem emeli ki a lemezt. Ha mégis ezt szeretnénk a --force-swap és a --force-raid opcióval érhetjük el ezt. Ilyenkor a swap partíciókat swapoff parancssal leállítja, a raid tömbök alól viszont egyszerűen értesítés nélkül kitépi a lemezt.
#!/bin/bash
# (c) 2013 http://blog.webgyerek.net
# THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY

# Help
if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then
echo "Eject a disk from the system: unmount, spindown, delete device"
echo
echo "Usage: $0 IDENTIFIER [--force-raid] [--force-swap]"
echo
echo "IDENTIFIER: something unique to find the disk device in blkid"
echo "--force-raid: !DANGEROUS! force ejecting even with raid volumes on disk in use"
echo "--force-swap: !DANGEROUS! force ejecting even with swap volumes on disk in use"
exit 0
fi

ident=$1

if [[ $2 == "--force-raid" ]] || [[ $3 == "--force-raid" ]]; then
forceraid="yes"
fi

if [[ $2 == "--force-swap" ]] || [[ $3 == "--force-swap" ]]; then
forceswap="yes"
fi

# Gettin device & check it's unique

blkid=$(blkid | grep -e "$ident")
devX=""
devY=""
while read -r line; do
devY=$(echo "$line" | cut -d : -f 1 | cut -c 6- | sed 's/[0-9]//g')
if [[ ! -z "$devX" ]] && [[ "$devX" != "$devY" ]]; then
echo "Abort: IDENTIFIER not unique" >&2
exit 1
fi
devX="$devY"
done <<< "$blkid"

if [[ -z "$devX" ]]; then
echo "Abort: IDENTIFIER not found" >&2
exit 1
fi

# Checking swap partitions
swap=$(cat /proc/swaps | grep -e "/dev/$devX" | cut -f 1)
if [[ ! -z "$swap" ]] && [[ $forceswap != "yes" ]]; then
echo "Abort: Swap partition in use $swap" >&2
fi

# If forced, try to swapoff
if [[ ! -z "$swap" ]]; then
echo "Warning: Swap partition in use $swap" >&2
# Swapoff
for part in $swap; do
swapoff $part || exit 4
done
fi

# Checking RAID
raid=$(cat /proc/mdstat | grep -e " $devX")
if [[ ! -z "$raid" ]] && [[ $forceraid != "yes" ]]; then
echo "Abort: RAID partition in use in $raid" >&2
exit 5
fi

# If forced we simply don't mind
if [[ ! -z "$raid" ]]; then
echo "Warning: RAID partition in use in $raid" >&2
fi

# Checking mounts
mounts=$(mount | grep /dev/$devX | cut -d " " -f 3)
for point in $mounts; do
umount $point
if (( $? > 0)); then
echo "Failed to unmount $point for $label!"
exit 2
fi
done

# Spin down disk
hdparm -Y /dev/$devX > /dev/null

# Remove device (sdX) from system
#echo 1 > /sys/block/$devX/device/delete

exit 0
A cserélt lemezeken lévő adatok kezeléséhez hasznos a partícióknak egyedi nevet adni, parancssorban ezt az e2label segítségével tehetjük meg. Ezután az adatokhoz való gyors hozzáféréshez további 2 scriptet javaslok.
A mediamount.sh az összes fel nem csatolt, címkével ellátott, szokásos (ext2,3,4 fat, fat32) fájlrendszert felcsatolja a /media/CÍMKE mappába.
A mediaclean.sh pedig ugyanitt takarít, az összes üres mappát törli, illetve -u paraméterrel meghívva az összes itt csatolt fájlrendszert le is választja.
#!/bin/bash

if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
echo "$0 [LABEL1, [LABEL2, ... ]]"
echo "Mount all simple (fat, fat32, ext2, ext3, ext4) partitions to /media/LABEL"
echo "LABELS: Only mount partitions with LABELS given"
exit 0
fi

if [[ ! -z "$*" ]]; then
labels="$*"
else
labels=$(blkid | perl -ne '/^.*?LABEL=\"(.*?)\".*?TYPE=\"(fat|ext[234]|fat32)\".*?$/ && print "$1 "' )
fi

for label in $labels
do
# Gettin device name
devXNUM=$(blkid | grep "LABEL=\"$label\"" | cut -d : -f 1 | cut -c 6- )

if [[ -z "$devXNUM" ]]; then
echo "No such label: $label" >&2
continue
fi

# Mount only if not alerady
ismnt=$(mount | grep "/dev/$devXNUM ")
if [[ ! -z "$ismnt" ]]; then
continue
fi

# Mounting
mkdir -p /media/$label
mount /dev/$devXNUM /media/$label
done
#!/bin/bash

if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
echo "$0 [-u]"
echo "Clean up in /media: remove empty dirs, optionally unmount filesystems"
echo "-u: Also unmount all filesystems in /media"
exit 0
fi

list=$(ls -A /media)
for dir in $list
do
mnted=$(mount | grep "/media/$dir")
# Mounting
if [[ ! -z "$mnted" ]] && [[ "$1" == "-u" ]]; then
umount /media/$dir
rmdir /media/$dir
fi
if [[ -z "$mnted" ]]; then
rmdir /media/$dir
fi
done