From 8142ffde3037976e152711f902ad9622aa1b7cba Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 22 Oct 2017 13:31:10 +0200 Subject: hours of polishing tmux, script sequences, hinting. ^C abort in tmux is broken. --- make-boot-image.sh | 194 ++++++++++++++++++++++--------------- nfs/autorun.sh | 31 ------ nfs/nfs-autorun.sh | 23 +++++ nfs/scripts/funcs.sh | 42 +++++--- nfs/scripts/image_capture_I5456.sh | 8 +- nfs/scripts/image_deploy.sh | 2 +- 6 files changed, 171 insertions(+), 129 deletions(-) delete mode 100755 nfs/autorun.sh create mode 100755 nfs/nfs-autorun.sh diff --git a/make-boot-image.sh b/make-boot-image.sh index afcdb89..17baf51 100755 --- a/make-boot-image.sh +++ b/make-boot-image.sh @@ -15,7 +15,7 @@ WGET="wget" # "wget --no-check-certificate" could help but is a security conce KERNEL_TARBALL_URL=https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.39.tar.xz KCONFIGLIB_MAIN_URL=https://raw.githubusercontent.com/ulfalizer/Kconfiglib/7eace27993ad3aa1d6911866d9c60a11f32d36d9/kconfiglib.py KCONFIGLIB_PATCH_URL=https://raw.githubusercontent.com/ulfalizer/Kconfiglib/7eace27993ad3aa1d6911866d9c60a11f32d36d9/makefile.patch -NIC_FIRMWARE_URL=http://fr.archive.ubuntu.com/ubuntu/pool/main/l/linux-firmware/nic-firmware_1.165_all.udeb +NIC_FIRMWARE_URL=http://fr.archive.ubuntu.com/ubuntu/pool/main/l/linux-firmware/nic-firmware_1.169_all.udeb BUSYBOX_BIN_URL=https://busybox.net/downloads/binaries/1.26.2-defconfig-multiarch/busybox-x86_64 PCI_IDS_URL=https://pci-ids.ucw.cz/v2.2/pci.ids USB_IDS_URL=https://usb-ids.gowdy.us/usb.ids @@ -240,9 +240,12 @@ if [ ! -d "$WORKDIR/initrd" ] then mkdir -p "$WORKDIR/initrd/"{bin,dev,etc/rc.d,mnt/nfs,root,proc,root,sbin,sys,run/lock,run,tmp,usr/share/udhcpc,var/log} $ROOTCMD cp -a /dev/{null,console,tty1} "$WORKDIR/initrd/dev/" $ROOTCMD chmod 1777 "$WORKDIR/initrd/run/lock" + touch "$WORKDIR/initrd/etc/fstab" ln -s "/proc/mounts" "$WORKDIR/initrd/etc/mtab" ln -s "../run" "$WORKDIR/initrd/var/run" ln -s "../run/lock" "$WORKDIR/initrd/var/lock" + echo 'root::0:0:root:/root:/bin/sh' > "$WORKDIR/initrd/etc/passwd" + echo 'root:x:0:' > "$WORKDIR/initrd/etc/group" fi # XXX workaround, kernel makefile's cpio preseves everything and it is not so cool for us @@ -344,25 +347,25 @@ echo $VERSION > "$WORKDIR/initrd/etc/eficast_version" cat > "$WORKDIR/initrd/etc/rc.d/funcs" <<"EOF" # echo_color [prefix_string] echo_color() { - [ $# -eq 4 ] && echo -n "$3" setterm --foreground "$1" --background "$2" - [ $# -eq 4 ] && echo -n "$4" || echo -n "$3" + echo -n "$3" setterm --foreground white --background black - echo " (eficast v"$(cat /etc/eficast_version)")" + [ "x$4" == "xversion" ] && echo " (eficast v"$(cat /etc/eficast_version)")" || echo } -# if no args, print colored message, wait 1 minute and reboot +# if no args, print colored message, wait 10 sec and reboot eficast_end() { - echo_color white green "----- EFICAST end of execution ------" ( sfx_success ; touch /run/nosound ) & - read -t60 -p 'Ctrl+C to have a shell, Enter to skip wait time...' + message reboot "in 10s" + echo_color white green "----- EFICAST end of execution ------" + read -t10 -p 'Ctrl+C to have a shell, Enter to skip wait time...' reboot } # note : rcS rescue_shell is slighly different because most of the env is not ready in rcS rescue_shell() { - echo - echo_color white red "Something went wrong. Dropping to a shell." + echo -e "\e]2;rescue_shell\007" # Term title (tmux), intentionnal carriage return + echo_color white red "Something went wrong. Dropping to a shell." version ( sfx_failure ; touch /run/nosound ) & PS1='\h:\w# ' HOME='/root/' /bin/busybox sh } @@ -397,26 +400,26 @@ network_show() { setterm -bold off } -nfs_autorun() { - if [ ! -x /mnt/nfs/autorun.sh ] - then echo_color white red "----- NFS server NOT ready ------" - return 1 - fi - echo_color white green "----- NFS server ready ------" - echo_color green black "autorun.sh script will run on tty1 now" -# tmux since 2.x absolutly wants a working UTF-8 locale -# pane-border-* is supported since tmux 2.3 - LC_ALL=C.UTF-8 tmux \ - new-session -d 'tmux-main-pane main' \; \ +autorun() { + echo_color green black "$1-autorun.sh script will run on tmux-main-pane now" + read -t10 -p 'Ctrl+C to have a shell, Enter to skip wait time...' + + # tmux since 2.x absolutly wants a working UTF-8 locale (C.UTF-8 is okay) + # pane-border-* options are supported since tmux 2.3 + tmux \ + new-session -d "/etc/rc.d/tmux-main-pane $1" \; \ set -g pane-border-status top \; \ set -g pane-border-format " #T " \; \ set-window-option status off \; \ - split-window -t %0 -l1 pigz-watch progression \; \ - split-window -t %0 -l5 iftop-watch network \; \ - split-window -t %0 -l6 iostat-watch disk \; \ - split-window -h -p40 pstree-watch processes \; \ - select-pane -t:.0 \; \ - attach + split-window -t %0 -l1 pigz-watch progression + + [ "x$1" == "xnfs" ] && tmux split-window -t %0 -l5 iftop-watch network + [ $(tput lines) -gt 30 ] && tmux \ + split-window -t %0 -l6 iostat-watch cpu-disk \; \ + split-window -t %0 -l6 mpstat-watch cpu-softintr \; \ + split-window -h -p40 pstree-watch processes + tmux select-pane -t:.0 \; attach + # Hack to keep the error flow intact if [ -r /run/autorun_res ] then res=$(cat /run/autorun_res) @@ -463,11 +466,19 @@ cat > "$WORKDIR/initrd/etc/inittab" <<"EOF" ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init -tty1::respawn:/etc/rc.d/rc2_or_rescue -tty2::askfirst:/bin/sh -tty3::askfirst:/bin/sh +tty1::respawn:/etc/rc.d/rc2-or-rescue +tty2::askfirst:/bin/sh -l +tty3::askfirst:/bin/sh -l +EOF +cat > "$WORKDIR/initrd/etc/profile" <<"EOF" +export LC_ALL=C.UTF-8 +export TERM=linux # busybox on qemu set vt102, then tmux segfaults +# https://git.busybox.net/busybox/tree/init/init.c, search for VT_OPENQRY +# happens if qemu pass "-append console=ttyS0" or similar to the kernel EOF add_initrd_script "/etc/rc.d/rcS" <<"EOF" +echo -e '\e[37;42m'----- EFICAST start of execution ------'\e[0m' +echo -e '\e[32m/etc/rc.d/rcS script will run on /dev/console now\e[0m' echo -e '\e[37;43m'----- rcS script started -----'\e[0m' # Hint for user about boot steps if its hangs # Declare some funcs to have a tidy output with trace mode @@ -509,13 +520,12 @@ network_up # Bring net interfaces up (no config) sleep 5 # Wait for physical link detection + STP + IPv6 DAD & Autoconf set +v # Hint users about boot steps to help them if it hangs -echo -e '\e[32m/etc/rc.d/rc2 script will run on tty1 now\e[0m' +echo -e '\e[32m/etc/rc.d/rc2-or-rescue script will run on /dev/tty1 now\e[0m' echo -e '\e[37;43m----- rcS script ended -----\e[0m' EOF add_initrd_script "/etc/rc.d/rc2" <<"EOF" echo -e '\e[37;43m'----- rc2 script started -----'\e[0m' # Hint for user about boot steps if its hangs . /etc/rc.d/funcs # Load helper functions -export TERM=linux # FIXME: wrong default TERM=vt102, why? setterm -blank 60 # screen sleep mode after 60 minutes set -v # Trace execution @@ -523,48 +533,59 @@ network_conf network_show machine_info -mount -v -t nfs -o nolock 172.16.2.28:/masters /mnt/nfs -nfs_autorun && eficast_end - +autorun nfs && eficast_end +#autorun initrd && eficast_end set +v echo -e '\e[37;43m'----- rc2 script ended -----'\e[0m' # Hint for user about boot steps if its hangs EOF -add_initrd_script "/usr/share/udhcpc/default.script" <<"EOF" -#!/bin/sh -case $1 in - bound) - # Configure interface and default gateway - busybox ifconfig $interface ${mtu:+mtu $mtu} $ip netmask $subnet ${broadcast:+broadcast $broadcast} - busybox ip -4 route add default via $router dev $interface - - # Update resolver configuration file - [ -n "$domain" ] && R="domain $domain" || R="" - for i in $dns; do - R="$R\nnameserver $i" - done - echo -e "$R" > /etc/resolv.conf - - # Update in-kernel-memory hostname - [ -n "$hostname" ] && hostname $hostname - ;; - renew | deconf) echo "no action taken: $1: $interface" >&2 ;; - leasefail | nak) echo "configuration failed: $1: $message" >&2 ;; -esac +add_initrd_script "/etc/rc.d/initrd-autorun.sh" <<"EOF" +read -t60 -p 'Dummy script. Ctrl+C to have a shell, Enter to skip wait time...' EOF -add_initrd_script "/etc/rc.d/rc2_or_rescue" <<"EOF" +add_initrd_script "/etc/rc.d/rc2-or-rescue" <<"EOF" +. /etc/rc.d/funcs # Load helper functions if [ -f /run/rescue ] then rm /run/rescue - source /etc/rc.d/funcs # TODO : this probably don't work + echo_color green black "/etc/rc.d/rc2 dead. Spawn rescue_shell run on /dev/tty1 now" rescue_shell else touch /run/rescue - source /etc/rc.d/rc2 + echo_color green black "/etc/rc.d/rc2 script will run on /dev/tty1 now" + sh -lc /etc/rc.d/rc2 # Need /etc/profile fi EOF -add_initrd_script "/bin/tmux-main-pane" <<"EOF" -echo -ne "\e]2;$*\007" # Term title (tmux) -trap 'echo $? > /run/autorun_res ; tmux kill-server' EXIT -cd /mnt/nfs -./autorun.sh +add_initrd_script "/etc/rc.d/tmux-main-pane" <<"EOF" +# Drop a in-tmux rescue shell in case of failure, prevents clearing screen with valuable informations +trap 'res=$?; echo $res > /run/autorun_res ; [ "$res" -eq 0 ] || rescue_shell; tmux kill-server' EXIT +. /etc/rc.d/funcs # Load helper functions +case $1 in + initrd) echo -ne "\e]2;initrd-autorun.sh\007" # Term title (tmux) + message initrd autorun + source /etc/rc.d/initrd-autorun.sh + ;; + nfs) source nfs-mount + if [ $? -ne 0 ] + then echo_color white red "----- NFS server : not mounted ------" + echo_color green black "Check for failure above. Exiting rescue shell twice will retry mount" + return 1 + fi + if ! [ -x /mnt/nfs/nfs-autorun.sh ] + then echo_color white red "----- NFS server : missing script ------" + echo_color green black "Check nfs-autorun.sh : should be present, readable and executable" + ls -l /mnt/nfs + return 2 + fi + echo_color white green "----- NFS server ready ------" + message nfs autorun + echo -ne "\e]2;nfs-autorun.sh\007" # Term title (tmux) + cd /mnt/nfs && source ./nfs-autorun.sh + ;; + *) echo "Usage : $0 (nfs|initrd)" + return 1 ;; +esac +EOF +add_initrd_script "/bin/nfs-mount" <<"EOF" +echo -ne "\e]2;$0\007" # Term title (tmux) +set -v # Trace execution +mount -v -t nfs -o nolock 172.16.2.28:/masters /mnt/nfs EOF add_initrd_script "/bin/iftop-watch" <<"EOF" echo -ne "\e]2;$*\007" # Term title (tmux) @@ -575,6 +596,14 @@ add_initrd_script "/bin/iostat-watch" <<"EOF" echo -ne "\e]2;$*\007" # Term title (tmux) iostat -cdmz 1 | awk '$1=="avg-cpu:" { system("clear"); } length($0) > 0 { print $0; }' EOF +add_initrd_script "/bin/mpstat-watch" <<"EOF" +# Emulates watch command with mpstat +echo -ne "\e]2;$*\007" # Term title (tmux) +while true; do + mpstat -I SCPU | grep -vE '^(Linux.*|)$' + sleep 1 +done +EOF add_initrd_script "/bin/pigz-watch" <<"EOF" # Emulate watch command using pipeview (pv) for a running pigz echo -ne "\e]2;$*\007" # Term title (tmux) @@ -592,20 +621,31 @@ while true; do sleep 1 done EOF -add_initrd_script "/bin/tmux-wrap" <<"EOF" -# tmux since 2.x absolutly wants a working UTF-8 locale -# pane-border-* is supported since tmux 2.3 -LC_ALL=C.UTF-8 tmux \ - new-session -d 'tmux-main-pane main' \; \ - set -g pane-border-status top \; \ - set -g pane-border-format " #T " \; \ - set-window-option status off \; \ - split-window -t %0 -l1 pigz-watch progression \; \ - split-window -t %0 -l5 iftop-watch network \; \ - split-window -t %0 -l6 iostat-watch disk \; \ - split-window -h -p40 pstree-watch processes \; \ - select-pane -t:.0 \; \ - attach +add_initrd_script "/bin/lsblk-watch" <<"EOF" +echo -ne "\e]2;$*\007" # Term title (tmux) +watch -t lsblk -o NAME,SIZE,MODEL,SERIAL,FSTYPE,LABEL,MOUNTPOINT +EOF +add_initrd_script "/usr/share/udhcpc/default.script" <<"EOF" +#!/bin/sh +case $1 in + bound) + # Configure interface and default gateway + busybox ifconfig $interface ${mtu:+mtu $mtu} $ip netmask $subnet ${broadcast:+broadcast $broadcast} + busybox ip -4 route add default via $router dev $interface + + # Update resolver configuration file + [ -n "$domain" ] && R="domain $domain" || R="" + for i in $dns; do + R="$R\nnameserver $i" + done + echo -e "$R" > /etc/resolv.conf + + # Update in-kernel-memory hostname + [ -n "$hostname" ] && hostname $hostname + ;; + renew | deconf) echo "no action taken: $1: $interface" >&2 ;; + leasefail | nak) echo "configuration failed: $1: $message" >&2 ;; +esac EOF add_initrd_script "/bin/message" <<"EOF" # Output some center ASCII-art text, one line per argument diff --git a/nfs/autorun.sh b/nfs/autorun.sh deleted file mode 100755 index ad99a8e..0000000 --- a/nfs/autorun.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/busybox sh - -rest10() { - # Let the user read machine_info and other usefull informations on console (or skip with Enter) - sfx_question ; read -t10 -p 'Press Enter or wait 10 sec...' - # Make some blank lines on console - echo -e '\n\n\n\n\n' -} - -# Define some handy variables -imagedir=/mnt/nfs/images -scriptdir=/mnt/nfs/scripts/ -hostname=$(hostname) - -# Load helper functions -source $scriptdir/funcs.sh # Load some autorun.sh specific helper functions -source /etc/rc.d/funcs # Reload init help functions - -# Check all prerequisites and exit if it fail -hostname_test || exit 1 -firstdisk_test || exit 2 - -# Run the main action script -if nfswrite_test -then # Start deploy script after letting a chance to cancel it - rest10 ; source $scriptdir/image_deploy.sh - -else scriptavailability_test image_capture_${hostname}.sh || exit 3 - # Start capture script if all it needs is available - rest10 ; source $scriptdir/image_capture.sh -fi diff --git a/nfs/nfs-autorun.sh b/nfs/nfs-autorun.sh new file mode 100755 index 0000000..b2be8b2 --- /dev/null +++ b/nfs/nfs-autorun.sh @@ -0,0 +1,23 @@ +#!/bin/busybox sh + +# Define some handy variables +imagedir=/mnt/nfs/images +scriptdir=/mnt/nfs/scripts/ +hostname=$(hostname) + +# Load helper functions +source $scriptdir/funcs.sh # Load some nfs-autorun.sh specific helper functions + +# Check all prerequisites and exit if it fail +hostname_test || exit 1 +firstdisk_test || exit 2 + +# Run the main action script +if nfswrite_test +then # Start deploy script after letting a chance to cancel it + pause10s ; source $scriptdir/image_deploy.sh + +else scriptavailability_test image_capture_${hostname}.sh || exit 3 + # Start capture script if all it needs is available + pause10s ; source $scriptdir/image_capture.sh +fi diff --git a/nfs/scripts/funcs.sh b/nfs/scripts/funcs.sh index 5e27052..a69fb75 100644 --- a/nfs/scripts/funcs.sh +++ b/nfs/scripts/funcs.sh @@ -1,24 +1,34 @@ +# no args, let the user read useful informations on console (or skip with Enter) +pause10s() { + sfx_question # sfx_* comes from /etc/rc.d/funcs helpers + read -t10 -p 'Press Enter or wait 10 sec...' + # Make some blank lines on console + echo -e '\n\n\n\n\n' +} + # no args, print colored message, returns 0 if hostname seems valid, returns 1 if hostname is a default one hostname_test() { + BADNAME='echo_color white red ">>> hostname should not contain special characters or should not be FQDN : $hostname"' + # This test is for security concern, hostname will be used as shell arg case $hostname in - "(none)"|eficast|"") echo_color white red ">>> " "hostname is not customized : $hostname" ; return 1 ;; - *\&*) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *\(*) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *\{*) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *\;*) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *\<*) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *\`*) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *\ *) echo_color white red ">>> " "hostname should not contain special characters or should not be FQDN : $hostname" ; return 2 ;; - *) echo_color green black ">>> " "hostname is $hostname" ; return 0 ;; + "(none)"|eficast|"") echo_color white red ">>> hostname is not customized : $hostname" ; return 1 ;; + *\&*) $BADNAME; return 2 ;; + *\(*) $BADNAME; return 2 ;; + *\{*) $BADNAME; return 2 ;; + *\;*) $BADNAME; return 2 ;; + *\<*) $BADNAME; return 2 ;; + *\`*) $BADNAME; return 2 ;; + *\ *) $BADNAME; return 2 ;; + *) echo_color green black ">>> hostname is $hostname" ; return 0 ;; esac } # no args, print colored message, returns 0 if NFS is read-only, returns 1 if NFS is read-write (needed for image capture) nfswrite_test() { if ! touch /mnt/nfs/.writetest - then echo_color green black ">>> " "NFS is read-only" + then echo_color green black ">>> NFS is read-only" return 0 - else echo_color white blue ">>> " "NFS is read-write" + else echo_color white blue ">>> NFS is read-write" return 1 fi } @@ -27,13 +37,13 @@ nfswrite_test() { firstdisk_test() { diskinfo=$(lsblk --list --output TRAN,MODEL --noheadings --nodeps /dev/sda) case $diskinfo in - sata*) echo_color green black ">>> " "First disk is SATA and is available ($diskinfo)" + sata*) echo_color green black ">>> First disk is SATA and is available ($diskinfo)" return 0 ;; - usb*) echo_color white red ">>> " "First disk is USB ($diskinfo)" + usb*) echo_color white red ">>> First disk is USB ($diskinfo)" return 1 ;; - *) echo_color white red ">>> " "First disk is unknown ($diskinfo)" + *) echo_color white red ">>> First disk is unknown ($diskinfo)" return 2; ;; esac @@ -43,9 +53,9 @@ firstdisk_test() { scriptavailability_test() { script=$scriptdir/$1 if [ -r $script ] - then echo_color green black ">>> " "Script $script is available" + then echo_color green black ">>> Script $script is available" return 0 - else echo_color white blue ">>> " "Script $script is missing or unreadable" + else echo_color white blue ">>> Script $script is missing or unreadable" return 1 fi } diff --git a/nfs/scripts/image_capture_I5456.sh b/nfs/scripts/image_capture_I5456.sh index bc40a51..9895edd 100644 --- a/nfs/scripts/image_capture_I5456.sh +++ b/nfs/scripts/image_capture_I5456.sh @@ -4,16 +4,16 @@ # $outdir is the also the current working dir, garanted to be empty and writable # Many cloning/partitioning tools are available for use, see make-boot-image.sh -echo_color white blue ">>> " "Capturing /dev/sda boot sectors" +echo_color white blue ">>> Capturing /dev/sda boot sectors" dd if=/dev/sda count=2048 2>logs/sda-dd.log | pigz --fast > sda-dd.gz 2>logs/sda-pigz.log -echo_color white blue ">>> " "Capturing /dev/sda1 NTFS BOOT" +echo_color white blue ">>> Capturing /dev/sda1 NTFS BOOT" partclone.ntfs --clone -s /dev/sda1 -L logs/sda1-partclone.log --no_check | pigz --fast >sda1-partclone.gz 2>logs/sda1-pigz.log -echo_color white blue ">>> " "Capturing /dev/sda2 NTFS WINDOWS" +echo_color white blue ">>> Capturing /dev/sda2 NTFS WINDOWS" partclone.ntfs --clone -s /dev/sda2 -L logs/sda2-partclone.log --no_check | pigz --fast >sda2-partclone.gz 2>logs/sda2-pigz.log -echo_color white blue ">>> " "Capturing /dev/sda3 EXT4 LINUX" +echo_color white blue ">>> Capturing /dev/sda3 EXT4 LINUX" partclone.ext4 --clone -s /dev/sda3 -L logs/sda3-partclone.log --no_check | pigz --fast >sda3-partclone.gz 2>logs/sda3-pigz.log diff --git a/nfs/scripts/image_deploy.sh b/nfs/scripts/image_deploy.sh index bdc5e9c..4efd715 100644 --- a/nfs/scripts/image_deploy.sh +++ b/nfs/scripts/image_deploy.sh @@ -1,4 +1,4 @@ #!/bin/busybox sh # Should only started from autorun.sh (define some helper functions and variables) -echo_color white red ">>> " "Image deploy not yet ready" +echo_color white red ">>> Image deploy not yet ready" -- cgit v1.2.3