Manage from Telnet

From unRAID
Jump to: navigation, search

More Info Here: http://lime-technology.com/forum/index.php?topic=153.0

Author: Joe L.


I put together a UNIX shell script that allows for some basic management of the unRaid array when logged in via telnet.

It is named "unmenu" and might be helpful to some unRaid owners. It does not perform all functions the web-based interface can perform. It cannot be used to add a disk to an array, or to format disks, or to initialize the array, or even to start the array if it is stopped.

What it can do is show you disk status, disk statistics, and let you start and stop a background parity check. It can also let you reboot the server, or issue a "powerdown" command to safely stop the array prior to shutting off the power supplies. All the "management" commands must be typed as upper-case (hold down the shift key when typing the command) This is to help prevent any accidental commands from being issued.

To install it, unzip the attachment to this post and drag it to your flash drive. Then log in via telnet and type:

chmod +x /boot/unmenu

That will mark it as executable. Then to invoke it log in via telnet and then type:

cd /boot
unmenu

The screen on the unmenu refreshes automatically every 30 seconds or whenever a key is pressed on the keyboard.

Here are some sample screen shots.


http://i1.tinypic.com/20gec7s.jpg http://i1.tinypic.com/20gecl5.jpg http://i1.tinypic.com/20geec4.jpg http://i1.tinypic.com/20geeqx.jpg http://i1.tinypic.com/20gef6t.jpg

#!/bin/sh
trap '' 2
trap 'stty sane; rm /tmp/$$unmenu_status;' EXIT

DELAY=30

MODE="disk_status"
STATUS="PLEASE Wait..."

if [ -x /usr/bin/tput ]
then
	clearscreen=`tput clear`
	goto_top=`tput cup 0 1`
	goto_bot=`tput cup 24 1`
	goto_menu10=`tput cup 10 3`
	goto_menu11=`tput cup 11 3`
	goto_menu12=`tput cup 12 3`
	goto_menu13=`tput cup 13 3`
	goto_menu1=`tput cup 18 3`
	goto_menu2=`tput cup 19 3`
	goto_menu3=`tput cup 20 3`
	goto_menu4=`tput cup 21 3`
	goto_command_line=`tput cup 23 1`
	bold=`tput smso`
	norm=`tput rmso`
	ul=`tput smul`
	noul=`tput rmul`
else
	clearscreen=`echo -n -e "\033[H\033[2J"`
	goto_top=`echo -n -e "\033[1;2H"`
	goto_bot=`echo -n -e "\033[25;2H"`
	goto_menu10=`echo -n -e "\033[11;4H"`
	goto_menu11=`echo -n -e "\033[12;4H"`
	goto_menu12=`echo -n -e "\033[13;4H"`
	goto_menu13=`echo -n -e "\033[14;4H"`
	goto_menu1=`echo -n -e "\033[19;4H"`
	goto_menu2=`echo -n -e "\033[20;4H"`
	goto_menu3=`echo -n -e "\033[21;4H"`
	goto_menu4=`echo -n -e "\033[22;4H"`
	goto_command_line=`echo -n -e "\033[24;2H"`
	bold=`echo -n -e "\033[7m"`
	norm=`echo -n -e "\033[27m"`
	ul=`echo -n -e "\033[4m"`
	noul=`echo -n -e "\033[24m"`
fi

# Timed read of a single key from the user
read_key()
{
    IFS= read -t $DELAY -r -s -n1 -d '' "${@:-_KEY}"
}

# Query the "md" module and get the current status
get_status() {
	cmd status | strings >/tmp/$$unmenu_status
	if [ "$MODE" = "disk_statistics" ]
	then
		mount >/tmp/$$mount_status
	fi
	UPTIME=`uptime | cut -d" " -f3-6| \
	sed "s/\\(.*\\)\\([^:]*\\):\\([^:]*\\),$/ \\1 \\2hours, \\3 minutes/"`
	STATUS=`grep mdState /tmp/$$unmenu_status | cut -d "=" -f2`
	NUMDISKS_IN_ARRAY=`grep "^mdNumProtected" /tmp/$$unmenu_status | 
		cut -d "=" -f2`
	NUMDISKS_IN_SB=`grep "^sbNumDisks" /tmp/$$unmenu_status | 
		cut -d "=" -f2`
	RESYNC=`grep "^mdResync" /tmp/$$unmenu_status | 
		cut -d "=" -f2`
	RESYNCPERCENT=`grep "^mdResyncPrcnt" /tmp/$$unmenu_status | 
		cut -d "=" -f2`
	RESYNCFINISH=`grep "^mdResyncFinish" /tmp/$$unmenu_status | 
		cut -d "=" -f2`

	i=0
	while [ "$i" -lt "$NUMDISKS_IN_SB" ]
	do
		rdevname[$i]=`grep "rdevName.$i"= /tmp/$$unmenu_status|
			sed -e "s/rdevName.$i=//" -e "s/^\\(...*\\)$/\\/dev\\/\\1/"`
		dserial[$i]=`grep "diskSerial.$i"= /tmp/$$unmenu_status|
			sed "s/diskSerial.$i=//"`
		dmodel[$i]=`grep "diskModel.$i"= /tmp/$$unmenu_status|
			sed "s/diskModel.$i=//"`
		serial[$i]=`grep "rdevSerial.$i"= /tmp/$$unmenu_status|
			sed "s/rdevSerial.$i=//"`
		model[$i]=`grep "rdevModel.$i"= /tmp/$$unmenu_status|
			sed "s/rdevModel.$i=//"`
		disk_device[$i]=`echo ${rdevname[$i]}| cut -c6-`
			writes[$i]=`cat /sys/block/${disk_device[$i]}/stat 2>/dev/null| awk '{print $5}'`
			reads[$i]=`cat /sys/block/${disk_device[$i]}/stat 2>/dev/null| awk '{print $1}'`
			errors[$i]=`grep "rdevNumErrors.$i"= /tmp/$$unmenu_status|
				sed "s/rdevNumErrors.$i=//"`
		status[$i]=`grep "rdevStatus.$i"= /tmp/$$unmenu_status|
			sed -e "s/rdevStatus.$i=//" -e \
				"s/DISK_OK/OK/" -e \
				"s/DISK_NP/Not Installed/"`

		last_io[$i]=`grep "rdevLastIO.$i"= /tmp/$$unmenu_status|
			sed -e "s/rdevLastIO.$i=//"`

				if [ "${last_io[$i]}" = "0" -o "${last_io[$i]}" = ""  ]
				then
					last_io[$i]="*"
				else
					now=`date '+%s'`
					seconds=$(($now-${last_io[$i]}))
					hours=$(($seconds / 3600))
					seconds=$(($seconds - ($hours * 3600)))
					minutes=$(($seconds / 60))
					seconds=$(($seconds - ($minutes * 60)))
					last_io[$i]="$hours:$minutes:$seconds idle"
				fi
				status[$i]="${status[$i]} ${last_io[$i]}"

		device[$i]=`grep "diskName.$i"= /tmp/$$unmenu_status|
			sed -e "s/diskName.$i=//" -e "s/md/\\/dev\\/md/"`
		if [ "${model[$i]}" != "" -a "${device[$i]}" = "" -a "${status[$i]}" = "OK" ]
		then
			device[$i]="parity"
		else
			if [ "${device[$i]}" != "" ]
			then
				space[$i]=`df -h "${device[$i]}" 2>/dev/null | 
					grep -v "Filesystem" | 
					grep -v "/dev/ram" | 
					cut -c20-33,40-43`
			else
				space[$i]=""
			fi
		fi
		if [ "$STATUS" != "STARTED" ]
		then
			blkid "${rdevname[$i]}" | grep "TYPE=" >/dev/null 2>&1 
			if [ $? != 0 -a "${device[$i]}" != "parity drive" ]
			then
				if [ "${status[$i]}" = "OK" ]
				then
					status[$i]="OK unformatted"
				fi
			fi
		fi

		if [ "${device[$i]}" != "" -a "$MODE" = "disk_statistics" ]
		then
			mountpoint[$i]=`grep "${device[$i]} " /tmp/$$mount_status|
			cut -d" " -f3`
		else
			mountpoint[$i]=""
			reads[$i]=""
			writes[$i]=""
			errors[$i]=""
		fi
	
		let "i+=1"
	done
	i=0
	DISK_STATUS=`while [ "$i" -lt "$NUMDISKS_IN_SB" ]
	do
		printf "%2s %15.15s-%-15.15s %-14s %-9.9s %s\n" \
			$i "${model[$i]}" "${serial[$i]}" "${status[$i]}" \
			"${device[$i]}" "${space[$i]}"
		if [ "${status[$i]}" = "DISK_WRONG" ]
		then
			printf "   %15.15s-%-15.15s <-- was the old disk in slot %s\n" \
			"${dmodel[$i]}" "${dserial[$i]}" "$i"
		fi
		let "i+=1"
	done`
	i=0
	DISK_STATISTICS=`while [ "$i" -lt "$NUMDISKS_IN_SB" ]
	do
		printf "%2s   %-10s %-10s %-12s %-14s %-14s %-8s\n" \
			$i "${device[$i]}" "${rdevname[$i]}" \
			"${mountpoint[$i]}" \
			"${reads[$i]}" "${writes[$i]}" "${errors[$i]}"
		let "i+=1"
	done`
}

cmd() {
	echo $* >/proc/mdcmd
	cat /proc/mdcmd 
}

draw_screen() {
	# get the current status
	get_status

	# Top screen line has unRaid status, 
	printf "%s%s%-35s  %-35s %s\n" "$clearscreen" "$goto_top" \
		 "unRaid status: $STATUS" "`date`"
	printf "%-27s%-10s%s" \
	 "Number of disks in array :" "$NUMDISKS_IN_ARRAY" "$UPTIME"

	case "$MODE" in
		"disk_status")
		printf "\n%s%-79s\n%2s %13s-%-15s %-14s %-12s %s%s\n" \
		"$bold" "DISK STATUS" \
		"Disk" "Model" "Serial" "Status" "unRaid-dev" \
		"Size  Used %Used" "$norm"
		echo "$DISK_STATUS"
		if [ "$RESYNCPERCENT" != "" ]
		then
			printf "\nParity CHECK in progress, %s%% complete, est. finish in %s minutes.\n" "$RESYNCPERCENT" "$RESYNCFINISH"
		fi
		;;
		"disk_statistics")
		printf "\n%s%-79s\n%2s %-10s %-10s %-10s %s%s\n" \
		"$bold" "DISK STATISTICS" \
		"Disk" "unRaid-dev" " raw-dev" \
		"Mount-Point  Bytes-Read     Bytes-Written  Errors  " "$norm"
		echo "$DISK_STATISTICS"
		if [ "$RESYNCPERCENT" != "" ]
		then
			printf "\nParity Resync in progress, %s%% complete, est. finish in %s minutes.\n" "$RESYNCPERCENT" "$RESYNCFINISH"
		fi
		;;
		"manage_array")
		printf "\n%s%-79s%s\n" \
		"$bold" "MANAGE ARRAY"  "$norm"
		case "$STATUS" in
		"STARTED")
			printf "%s%s%s%s" \
			"$goto_menu10" \
			"Press 'S' (upper case) to STOP the array."
			if [ "$RESYNCPERCENT" = "" ]
			then
			printf "%s%s" \
			"$goto_menu11" \
			"      'C' (upper case) to perform background parity CHECK"
			else
			printf "%s%s" \
			"$goto_menu11" \
			"      'N' (upper case) to STOP background parity CHECK"
			fi
		;;
		STOPPED)
			printf "%s%s" \
			"$goto_menu10" \
			"Press 'S' (upper case) to START the array." \
			"$goto_menu11" \
			"      'R' (upper case) to REBOOT the server." \
			"$goto_menu12" \
			"      'P' (upper case) to POWERDOWN the server."
		;;
		esac
		;;
	esac
}

display_menu_choices() {
	case $MODE in
	"disk_status")
		printf "%s%s" $goto_menu1 "Press '1' for Disk Status"
		printf "%s%s" $goto_menu2 "      '2' for Disk Statistics"
		printf "%s%s" $goto_menu3 "      '3' for Array Management"
		printf "%s%s" $goto_menu4 "      'q' to quit"
	;;
	"disk_statistics")
		printf "%s%s" $goto_menu1 "Press '1' for Disk Status"
		printf "%s%s" $goto_menu2 "      '2' for Disk Statistics"
		printf "%s%s" $goto_menu3 "      '3' for Array Management"
		printf "%s%s" $goto_menu4 "      'q' to quit"
	;;
	"manage_array")
		printf "%s%s" "$goto_menu1" "Press '1' for Disk Status"
		printf "%s%s" "$goto_menu2" "      '2' for Disk Statistics"
		printf "%s%s" "$goto_menu3" "      '3' for Array Management"
		printf "%s%s" "$goto_menu4" "      'q' to quit"
	;;
	esac
}

get_user_input() {
	printf "%s%s" "$goto_command_line" "Command: "
	a=""
	read_key a
	case "$a" in
	q|Q) exit;;
	"1") MODE="disk_status" ;; 
	"2") MODE="disk_statistics" ;; 
	"3") MODE="manage_array" ;; 
	esac
	if [ "$MODE" = "manage_array" ]
	then
		case "$STATUS" in
		"STARTED")
			case "$a" in
			"S") # stop the array
			sync
			sync
			# Stop Samba
			printf "%s%s%s\n" "$clearscreen" "$goto_menu10" \
				"Stopping SAMBA..."
			/root/samba stop
			
			printf "%s\n" "Unmounting Disks..."
			# unmount the disks
		i=0
		while [ "$i" -lt "$NUMDISKS_IN_SB" ]
		do
			if [ "${device[$i]}" != "" -a "${device[$i]}" != "parity"  ]
			then
				umount -v "${device[$i]}"
			fi
			let "i+=1"
		done
			# Stop the unRaid array
			printf "%s\n" "Stopping unRaid array..."
			cmd stop
			printf "%s\n" "Stopped unRaid array..."
			sleep 5
				
			;;
			"C") # background check of parity
			cmd check
			MODE="disk_status"
			;;
			"N") # cancel background check of parity
			cmd nocheck
			MODE="disk_status"
			;;
			esac
		;;
		"STOPPED")
			case "$a" in
			"S") # start the array
			# Start the unRaid array
				echo "$clearscreen"
				/usr/bin/wget -q -O - localhost/blank.htm >/dev/null
				/usr/bin/wget -q -O - localhost/blank.htm?cmdStart=apply >/dev/null
				echo
				echo "Restarting Array..."
				echo
				sleep 10
			;;
			"R") # reboot server
				echo "Are you sure you want to reboot? Y/N"
				read_key ans
				case $ans in
				y|Y)
				tput clear
				echo "rebooting in 5 seconds..."
				sleep 5
				reboot
				;;
				esac
			;;
			"P") # power down server (or try)
				echo "Are you sure you want to power down? Y/N"
				read_key ans
				case $ans in
				y|Y)
				tput clear
				echo "powering down in 5 seconds..."
				sleep 5
				poweroff
				;;
				esac
			;;
			esac
		;;
		esac
	fi
}

# main loop
while true
do
	draw_screen
	display_menu_choices
	get_user_input
done