Разметка жесткого диска из bash-сценария

Автор ping_Win, 15 Сентября 2012, 22:26

« предыдущая тема - следующая тема »

0 Пользователей и 1 Гость просматривают эту тему.

ping_Win

Собственно, хочу довести развертывание линуксов до уровня "вставил флешку и включил комп", на данный момент загвоздка в том, что все известные мне утилиты, которые могут размечать жесткий диск работают в интерактивном режиме. Есть ли какой-то способ размечать ЖД из скрипта без всяких этих ваших интерактивностей?

Vicpo

15 Сентября 2012, 22:45 #1 Последнее редактирование: 15 Сентября 2012, 22:45 от Vicpo
Пример скрипта - создает разделы /, /var, /tmp, swap, /opt
Насчет рабочий или нет - тести на виртуалке http://linuxforum.kz/public/style_emoticons/<#EMO_DIR#>/smile.gif\' class=\'bbc_emoticon\' alt=\':)\' />
[codebox]
#!/bin/sh

#
# preparedisk.sh
#
# This script prepares the disk for installation. It will
# re-partition the disk, thus ALL DATA ON THE DISK WILL BE LOST.
#

MKFSARGS2="-q -b 4096 -i 8192 -O sparse_super,filetype,resize_inode,dir_index"
MKFSARGS3="-j $MKFSARGS2"

err() {
   local message=$1
   echo "ERROR: $1"
   echo "ERROR: $1" >> /tmp/preparedisk.log
   exit 1
}

echox() {
   echo "$*"
   echo "$*" >> /tmp/preparedisk.log
}

echonx() {
   echo -n "$*"
   echo "$*" >> /tmp/preparedisk.log
}

warn() {
   local message=$1
   echo "WARNING: $1"
   echo "WARNING: $1" >> /tmp/preparedisk.log
}

log() {
   echo "$*" >> /tmp/preparedisk.log
}

log_file() {
   echo "=== $1" >> /tmp/preparedisk.log
   cat $1 >> /tmp/preparedisk.log
   echo "===" >> /tmp/preparedisk.log
}

run() {
   local status
   echo "*** $*" >> /tmp/preparedisk.log
   LIBC_FATAL_STDERR_=1 MALLOC_CHECK_=3 $* >> /tmp/preparedisk.log 2>&1
   status=$?
   if [ $status -ne 0 ]; then
      echo "ERROR: $*"
      echo "ERROR: $*" >> /tmp/preparedisk.log
   fi
   return $status
}

clear_lvm() {
   local volumes=$(lvm pvs --noheadings -o pv_name)
   if [ -n "$volumes" ]; then
      echox "Existing lvm volumes found; clearing..."
      run lvm pvremove -y -ff $volumes;
   fi
}

#
# setup swap lvm with 3 * memory. maximum 16G or free space on
# volume group. minimum 8GB.
#
# vg:    the volume group to use
# minfree: minimum free space in GiB to leave on vg after creating swap
#
setup_swap_on_vg() {
   local minswap=$((8 * 1024 * 1024))
   local maxswap=$((16 * 1024 * 1024))
   local vg=$1
   local minfree=$2

   if [ -n "$minfree" ]; then
      minfree=$(( $minfree * 1024 * 1024 ))
   else
      minfree=0
   fi

   echox "Setting up swap space."
   local free=$(lvm vgs --noheadings --nosuffix --units k -o vg_free $vg | cut -d. -f1)
   if [ $? -ne 0 ]; then
      warn "Could not determine free space in volume group $vg"
      return 1
   fi
   if [ $free -lt $minfree ]; then
      warn "Not enough space to create swap in $vg"
      return 1
   fi

   local memsize=$(awk '/^MemTotal:/ { print $2 }' < /proc/meminfo)
   if [ -z "$memsize" ]; then
      return 1
   fi

   local swapsize=$(( $memsize * 3 ))
   if [ $swapsize -gt $maxswap ]; then
      swapsize=$maxswap
   fi
   if [ $swapsize -lt $minswap ]; then
      swapsize=$minswap
   fi

   local freeleft=$(( $free - $swapsize ))
   if [ $freeleft -lt $minfree ]; then
      swapsize=$(( $free - $minfree ))
   fi

   if [ $swapsize -lt $minswap ]; then
      warn "Not enough space to create swap in $vg"
      return 1
   fi
   swapsize="${swapsize}K"
   if ! run lvm lvcreate -n swap -L "${swapsize}" $vg; then
      warn "Could not create LV swap of size ${swapsize}"
      return 1
   fi
   if ! run mkswap /dev/$vg/swap; then
      warn "Could not initialize swap space"
      return 1
   fi
   return 0
}


setup_big_disk() {
   local bootdev=$1
   local size=$2
   local partitionpath=$3

   log "*** setup_big_disk $1 $2 $3"

   local lvmpart="${partitionpath}2"
   local volgroup00="vg00"

   local rootsize=""
   local varsize=""
   local tmpsize=""
   if [ $size -lt 59392 ]; then
      # 5G / + 5G /var + 5G /tmp + 5G /opt + min 8G swap = 28G
      rootsize="5G"
      varsize="5G"
      tmpsize="5G"
      optmin="5"
   else
      # 10G / + 15G /var + 5G /tmp + 10G /opt + max 16G swap = 56G
      rootsize="10G"
      varsize="15G"
      tmpsize="5G"
      optmin="10"
   fi

   PARTED=parted
   run $PARTED --script -- $bootdev "mkpart primary ext2 2048s $rootsize"
   run $PARTED --script -- $bootdev "mkpart primary ext2 $rootsize -1"
   run $PARTED --script -- $bootdev "set 1 boot on"
   run $PARTED --script -- $bootdev "set 2 lvm on"
   run partprobe -s > /dev/null

   echox "Setting up LVM."
   local instdevice=$(imtool -d)
   if [ -n "$instdevice" ]; then
      mkdir -p /etc/lvm
      echo "devices { filter = [ \"r|$instdevice|\" ] }" > /etc/lvm/lvm.conf
   fi
   run dd if=/dev/zero of=$lvmpart bs=2048 count=1 >/dev/null
   run lvm pvcreate -y -ff $lvmpart
   run lvm vgcreate $volgroup00 $lvmpart
   run lvm lvcreate -n tmp -L$tmpsize $volgroup00
   run lvm lvcreate -n var -L$varsize $volgroup00

   cat >> /tmp/installdiskinfo <<EOF
ROOTFS=${partitionpath}1
volgroup=${volgroup00}
VAR=/dev/mapper/${volgroup00}-var
TMP=/dev/mapper/${volgroup00}-tmp
OPT=/dev/mapper/${volgroup00}-opt
SWAP=/dev/mapper/${volgroup00}-swap
INSTALLDEST=/mnt
EOF

   local volgroup01="vg01"
   if ! setup_additional_disk $volgroup01 $bootdev ; then
      volgroup01=$volgroup00
   fi

   setup_swap_on_vg $volgroup00 $optmin
   

   run lvm lvcreate -n opt -l 100%FREE $volgroup00

   . /tmp/installdiskinfo

   echonx "Creating file systems:"
   run mke2fs $MKFSARGS3 $ROOTFS
   [ $? -eq 0 ] && echonx " " || echonx " !"
   echonx "root"
   run mke2fs $MKFSARGS3 $VAR
   [ $? -eq 0 ] && echonx " " || echonx " !"
   echonx "var"
   run mke2fs $MKFSARGS3 $TMP
   [ $? -eq 0 ] && echonx " " || echonx " !"
   echonx "tmp"
   run mke2fs $MKFSARGS3 $OPT
   [ $? -eq 0 ] && echonx " " || echonx " !"
   echonx "opt"
   echox

   run mount -t ext3 $ROOTFS $INSTALLDEST

   mkdir -p $INSTALLDEST/var
   mkdir -p $INSTALLDEST/tmp
   mkdir -p $INSTALLDEST/opt
   mkdir -p $INSTALLDEST/proc
   mkdir -p $INSTALLDEST/sys

   mount -t ext3 "$VAR" $INSTALLDEST/var
   mount -t ext3 "$TMP" $INSTALLDEST/tmp
   mount -t ext3 "$OPT" $INSTALLDEST/opt
   mount -t proc proc $INSTALLDEST/proc
   mount -t sysfs none $INSTALLDEST/sys

   mkdir -p $INSTALLDEST/etc
   cat >> $INSTALLDEST/etc/fstab.inst <<EOF
proc         /proc      proc   defaults                  0   0
tmpfs         /dev/shm   tmpfs   defaults                  0   0
devpts         /dev/pts   devpts gid=5,mode=620               0   0
$ROOTFS         /         ext3   defaults,errors=remount-ro      1   1
$VAR         /var      ext3   nosuid,nodev,errors=remount-ro   0   2
$TMP         /tmp      ext3   nosuid,nodev,errors=remount-ro   0   2
$OPT         /opt      ext3   nosuid,nodev,errors=remount-ro   0   2
$SWAP         none      swap   sw                        0   0
EOF
}

setup_small_disk() {
   local bootdev=$1
   local size=$2
   local partitionpath=$3

   log "*** setup_small_disk $1 $2 $3"

   PARTED=parted
   run $PARTED --script -- $bootdev 'mkpart primary ext2 2048s -2G'
   run $PARTED --script -- $bootdev 'mkpart primary linux-swap -2G -1'
   run $PARTED --script -- $bootdev 'set 1 boot on'
   run partprobe -s > /dev/null

   echox "Setting up swap space."
   if ! run mkswap ${partitionpath}2; then
      warn "Could initialize swap space"
   fi

   cat >> /tmp/installdiskinfo <<EOF
ROOTFS=${partitionpath}1
SWAP=${partitionpath}2
INSTALLDEST=/mnt
EOF

   . /tmp/installdiskinfo

   echonx "Creating file systems:"
   run mke2fs $MKFSARGS3 $ROOTFS
   [ $? -eq 0 ] && echonx " " || echonx " !"
   echonx "root"
   echox

   mount -t ext3 $ROOTFS $INSTALLDEST

   mkdir -p $INSTALLDEST/var
   mkdir -p $INSTALLDEST/tmp
   mkdir -p $INSTALLDEST/opt
   mkdir -p $INSTALLDEST/proc

   mount -t proc proc $INSTALLDEST/proc

   mkdir -p $INSTALLDEST/etc
   cat >> $INSTALLDEST/etc/fstab.inst <<EOF
proc      /proc      proc      defaults               0   0
tmpfs      /dev/shm   tmpfs      defaults               0   0
devpts      /dev/pts   devpts      gid=5,mode=620            0   0
$ROOTFS      /         ext3      defaults,errors=remount-ro   1   1
$SWAP      none      swap      sw                     0   0
EOF

}

#
# check that size of device is greater than given min
# device: sysfs device name (e.g. hda, sda, cciss!c0d0)
# min:   size in blocks of 512 bytes
#
check_size() {
   local device=$1
   local min=$2
   size=$(cat /sys/block/$device/size)
   size=$(( $size / 2048 ))
   if [ $size -lt $min ]; then
   return 1
   else
   return 0
   fi
}

#
# search disks in defined order and skip all devices until
# optional device given in skip parameter is reached
# skip: device after which to start searching (optional)
#
find_firstdisk() {
   local skip=$1
   local installdevice=
   local bestdisk=
   local found=""

   if [ -z "$skip" ]; then
   found="1"
   fi

   for disk in hda hdb hdc hdd hde hdf hdg hdh vda; do
   [ "$disk" = "$installdevice" ] && continue
   [ ! -e /sys/block/$disk ]    && continue
   [ "$(cat /sys/block/$disk/removable)" = "1" ] && continue

   if [ -n "$found" ]; then
      if check_size $disk 10240; then
      echo $disk
      return
      fi
   fi

   if [ -n "$skip" ] && [ "$skip" = "$disk" ]; then
      found="1"
   fi
   done

   for disk in sda sdb sdc sdd sde sdf sdg sdh; do
   [ "$disk" = "$installdevice" ] && continue
   [ ! -e /sys/block/$disk ]    && continue
   [ "$(cat /sys/block/$disk/removable)" = "1" ] && continue

   if [ -n "$found" ]; then
      if check_size $disk 10240; then
      echo $disk
      return
      fi
   fi

   if [ -n "$skip" ] && [ "$skip" = "$disk" ]; then
      found="1"
   fi
   done

   echo ""
}
#
# search for additional disk and create volume group vg01 on it
# bootdev: primary disk which should be skipped
#
setup_additional_disk() {
   local volgroup=$1
   local bootdev=$2

   echo -n "Searching for additional disks:"
   local disk=$(basename $bootdev)
   disk=$(find_firstdisk $disk)
   if [ -z "$disk" ]; then
      echo "."
      return 1
   fi
   echo -n " $disk"
   echo "."


   run dd if=/dev/zero of=/dev/${disk} bs=512 count=1 >/dev/null
   run parted --script -- /dev/${disk} 'mklabel msdos'
   run partprobe -s > /dev/null

   PARTED=parted
   run $PARTED --script -- /dev/${disk} "mkpart primary ext2 2048s -1"
   run $PARTED --script -- /dev/${disk} "set 1 lvm on"
   run partprobe -s > /dev/null

   run dd if=/dev/zero of=/dev/${disk}1 bs=2048 count=1 >/dev/null
   run lvm pvcreate -y -ff /dev/${disk}1

   echo "DISK01=/dev/${disk}" >> /etc/installdiskinfo
   if lvm vgs --noheadings -o vg_name | grep -q $volgroup ; then
      run lvm vgextend $volgroup /dev/${disk}1
   else
      echo "VOLGROUP01=$volgroup" >> /etc/installdiskinfo
      run lvm vgcreate $volgroup /dev/${disk}1
   fi

   return 0
}

. /tmp/installdiskinfo

log_file /tmp/installdiskinfo

clear_lvm

echox "Writing disklabel."
run dd if=/dev/zero of=$BOOTDEV bs=512 count=1 >/dev/null
run parted --script -- $BOOTDEV 'mklabel msdos'
run partprobe -s > /dev/null

BOOTDEVSIZE=$(sfdisk -s $BOOTDEV)
BOOTDEVSIZE=$(( $BOOTDEVSIZE / 1024 ))
log "BOOTDEVSIZE=$BOOTDEVSIZE"
echox "Creating partitions."

if [ "$BOOTDEVSIZE" -lt 29696 ] || grep -q -E "\bforcesinglepartition\b" /proc/cmdline ; then
   # < 29G: small disk scheme, single partition
   echox "Using small disk scheme ($(($BOOTDEVSIZE / 1024)) GiB)."
   setup_small_disk $BOOTDEV $BOOTDEVSIZE $PARTITIONPATH

elif [ "$BOOTDEVSIZE" -lt 59392 ]; then
   # < 58G: medium disk scheme, full partition set, reduced size
   echox "Using medium disk scheme ($(($BOOTDEVSIZE / 1024)) GiB)."
   setup_big_disk $BOOTDEV $BOOTDEVSIZE $PARTITIONPATH
else
   # >= 58G: big disk scheme, full partition set
   echox "Using big disk scheme ($(($BOOTDEVSIZE / 1024)) GiB)."
   setup_big_disk $BOOTDEV $BOOTDEVSIZE $PARTITIONPATH
fi

log_file /tmp/installdiskinfo

cp /tmp/installdiskinfo $INSTALLDEST/etc/installdiskinfo
[/codebox]

sotrud_nik

17 Сентября 2012, 09:19 #2 Последнее редактирование: 17 Сентября 2012, 09:21 от sotrud_nik
Цитата: ping_Win от 15 Сентября 2012, 22:26Собственно, хочу довести развертывание линуксов до уровня "вставил флешку и включил комп", на данный момент загвоздка в том, что все известные мне утилиты, которые могут размечать жесткий диск работают в интерактивном режиме. Есть ли какой-то способ размечать ЖД из скрипта без всяких этих ваших интерактивностей?

Почему же не могут интерактивно,

fdisk /dev/sda << EOF
o
n
p
1
+10G
t
83
w
EOF

sotrud_nik


ping_Win

Сударь, Вы разуплотнили мой мозг... Вроде бы всё просто и очевидно, но чёрт возьми! Мне бы в голову такое никогда не пришло. Будем тестить...

Василий Иванов

буков то понаписал :D

BACKUP=kvm-backup-2018-1.tar.xz
setopt extendedglob
VGNAME=$(vgs --noheadings -o vg_name) && [[ -n $VGNAME ]] && vgremove -fv $VGNAME
if [[ -z $DISK ]]; then
    typeset -a devs
    devs=( $(lsblk -bn -x SIZE | awk '{if($6=="disk") print $1}') )
    if (( $#devs != 1 )); then
        print "failed to detect block device, consider using DISK=/dev/sdX"
        lsblk -bn -x SIZE
    else
        DISK=/dev/$devs[1]
    fi
fi
if [[ -z $DISK || ! -b $DISK ]]; then
    print "'$DISK' is not a block device"
else
    print -P "%BUsing %F{green}${DISK}%F{default}%b"
    cd /root
    sgdisk -Z $DISK
    sgdisk -n 0:0:+1024M $DISK
    sgdisk -n 0:0:+100M $DISK
    sgdisk -n 0:0:0 $DISK
    sgdisk -c 1:vm_swap $DISK
    sgdisk -c 2:vm_boot $DISK
    sgdisk -c 3:vm_root $DISK
    sgdisk -t 1:8200 $DISK
    sgdisk -t 2:ef02 $DISK
    partprobe $DISK
    mkswap -L vm_swap ${DISK}1
    mkfs.btrfs -f -L vm_root ${DISK}3
    swapon LABEL=vm_swap
    mount LABEL=vm_root /mnt/gentoo
    cd /mnt/gentoo
    wget --user=xxx --password=yyy http://domain.tld/vps/$BACKUP
    tar --numeric-owner -xvpf $BACKUP -C /mnt/gentoo
fi


примерно так виртуалку можно разметить и потом распаковать систему. ↑↑↑ это не bash а zsh ↑↑↑