virtualbox ssh manage script - preversion
von speefak- SNIPPET_TEXT:
-
- #!/bin/bash
- # name : vbox_cli-manager
- # desciption : shell based cli management for virtualbox on various servers
- # autor : speefak (itoss@gmx.de)
- # licence : (CC) BY-NC-SA
- # version : 0.2.8
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- ############################################################################################################
- ####################################### define global variables ########################################
- ############################################################################################################
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- ConfigFile=/home/user/.vbox_mgr.cfg # configure => path to config file
- XfreeRDPPassword="password" # configure => password from virtual box user on VM host
- ConfigfileMD5SumOld=$(md5sum $ConfigFile 2> /dev/null)
- VirtualBoxInstalledVersion=$(dpkg -l | grep virtualbox | awk '{printf $3}' | cut -d "-" -f1)
- CheckMark="\033[0;32m\xE2\x9C\x94\033[0m"
- Version=$(cat $(readlink -f $(which $0)) | grep "# version" | head -n1 | awk -F ":" '{print $2}' | sed 's/ //g')
- ScriptName=$(basename $(readlink -f $(which $0)))
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- ############################################################################################################
- ##################################### set vars from input options #######################################
- ############################################################################################################
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- OptionVarList="
- VirtualMachineManagement;-vmm
- HelpDialog;-?
- HelpDialog;-help
- BootVM;-b
- PauseVM;-pv
- ResumeVM;-rv
- HibernateVM;-h
- ShutdownVM;-s
- ResetVM;-r
- PowerOffVM;-p
- KillVM;-k
- RDPConnectVM;-c
- RDPCloseVM;-C
- RDPQuitVM;-q
- UpdateVMSpecs;-us
- ShowVMSpecs;-ss
- ListVMStatus;-ls
- ShowConfig;-sc
- NewConfig;-nc
- Reconfigure;-rc
- CheckConfig;-cc
- Monochrome;-m
- ScriptInformation;-i
- VMConfigSet;-vmcfg
- "
- # set entered vars from optionvarlist
- OptionAllocator=" " # for option seperator "=" use cut -d "="
- SAVEIFS=$IFS
- IFS=$(echo -en "\n\b")
- for InputOption in $(echo " $@" | sed 's/ -/\n-/g') ; do
- for VarNameVarValue in $OptionVarList ; do
- VarName=$(echo "$VarNameVarValue" | cut -d ";" -f1)
- VarValue=$(echo "$VarNameVarValue" | cut -d ";" -f2)
- # if [[ -n $(echo " $InputOption" | grep " $VarValue" 2>/dev/null) ]]; then
- if [[ $InputOption == "$VarValue" ]]; then
- eval $(echo "$VarName"='$InputOption') # if [[ -n Option1 ]]; then echo "Option1 set";fi
- #eval $(echo "$VarName"="true")
- elif [[ $(echo $InputOption | cut -d "$OptionAllocator" -f1) == "$VarValue" ]]; then
- eval $(echo "$VarName"='$(echo $InputOption | cut -d "$OptionAllocator" -f 2-10)')
- fi
- done
- done
- IFS=$SAVEIFS
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- ############################################################################################################
- ########################################### define functions ###########################################
- ############################################################################################################
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- usage () {
- cat << USAGE
- Virtualbox Shell Manager - version $VERSION
- Usage: $(basename $0) [-option]
- virtual machine management
- -b(X.X) (b)oot virtual machine (hostnumber.VMnumner)
- -pv(X.X) (p)ause (v)irtual machine (hostnumber.VMnumner)
- -rv(X.X) (r)esume (v)irtual machine (hostnumber.VMnumner)
- -h(X.X) (h)ibernate virtual machine (hostnumber.VMnumner)
- -s(X.X) (s)hutdown virtual machine via acpi (hostnumber.VMnumner)
- -r(X.X) (r)eset virtual machine (hostnumber.VMnumner)
- -p(X.X) (p)oweroff virtual machine (hostnumber.VMnumner)
- -k(X.X) (k)ill virtual machine (hostnumber.VMnumner)
- -c(X.X) (c)onnect virtual machine via rdp protokoll (hostnumber.VMnumner)
- -C(X.X) (C)lose RDP connection (hostnumber.VMnumner)
- -q(X.X) (q)uit (a)ll rdp sessions
- configuration and information
- -us (u)pdate virtual machines (s)pecifications
- -ss (s)how virtual machines (s)pecifications
- -ls (X) (l)ist virtual machines (s)tatus (X=<hostnumber|h|string>)
- -sc (s)how (c)onfiguration
- -nc (n)ew (c)onfiguration
- -rc (r)e(c)onfigure
- -cc (c)heck (c)onnections (-ls h)
- virtual machine configuration
- -vmcfg (X.X) rdp configure virtual machine (hostnumber.VMnumner) rdp functions
- -i show script (i)nformation"
- -m (m)onocrome output"
- toggle RDP fullscreen: Strg+Alt+Enter
- USAGE
- printf "$(tput setaf 1) $@ $(tput sgr0)\n\n"
- exit
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- load_color_codes () {
- # parse required colours for echo/printf usage: printf "%s\n" "Text in ${Red}red${Reset}, white and ${Blue}blue${Reset}."
- Black='\033[0;30m' && DGray='\033[1;30m'
- LRed='\033[0;31m' && Red='\033[1;31m'
- LGreen='\033[0;32m' && Green='\033[1;32m'
- LYellow='\033[0;33m' && Yellow='\033[1;33m'
- LBlue='\033[0;34m' && Blue='\033[1;34m'
- LPurple='\033[0;35m' && Purple='\033[1;35m'
- LCyan='\033[0;36m' && Cyan='\033[1;36m'
- LLGrey='\033[0;37m' && White='\033[1;37m'
- Reset='\033[0m'
- BG='\033[47m'
- FG='\033[0;30m'
- # parse required colours for sed usage: sed 's/status=sent/'${Green}'status=sent'${Reset}'/g' |\
- if [[ $1 == sed ]]; then
- for i in $(cat $0 | sed -n '/^load_color_codes/,/FG/p' | tr "&" "\n" | grep "='"); do
- eval $(sed 's|\\|\\\\|g' <<< $i) # sed parser '\033[1;31m' => '\\033[1;31m'
- done
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- script_information () {
- printf "\n"
- printf " Scriptname: $ScriptName\n"
- printf " Version: $Version \n"
- printf " Location: $(pwd)/$ScriptName\n"
- printf " Filesize: $(ls -lh $0 | cut -d " " -f5)\n"
- printf "\n"
- exit 0
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- check_input_options () {
- #############TODO###############!
- check_input_options () {
- # create available options list
- InputOptionList=$(cat $ScriptFile | sed -n '/usage()/,/exit/p' | grep " -[[:alpha:]]" | awk '{print $3}' | grep "^\-")
- # check for valid input options
- for Option in $@ ; do
- if [[ -z $(grep -w -- "$Option" <<< "$InputOptionList") ]]; then
- InvalidOptionList=$(echo $InvalidOptionList $Option)
- fi
- done
- # print invalid options and exit script_information
- if [[ -n $InvalidOptionList ]]; then
- usage "invalid option: $InvalidOptionList"
- fi
- }
- ############################
- testing () {
- # create available options list
- AvailableOptionList=$(cat $ScriptName | sed -n '/USAGE/,/^exit/p' | grep "^ -[[:alpha:]]" | awk -F "(" '{print $1 $2}' | awk '{print $1}' | sed 's/X\./'[[:digit:]].*'/g' | cut -d "X" -f1 )
- # print
- echo "$AvailableOptionList"
- for EntreredOption in $@ ; do
- for AvailableOption in $AvailableOptionList ; do
- echo "|$EntreredOption|$AvailableOption|"
- if [[ ! "$EntreredOption" == "$AvailableOption" ]]; then
- echo $EntreredOption
- fi
- done
- done
- exit
- }
- #testing
- for EntreredOption in $@ ; do
- for AvailableOption in $InputOptionList ; do
- echo "|$AvailableOption|$EntreredOption|" # If/ else doesnt work , even when the expression should match
- #if [[ -n $(grep -- "$AvailableOption" <<< "$EntreredOption") ]]; then
- if [[ "$EntreredOption" == "$AvailableOption" ]]; then # "-m" == "-m" => if does not break the loop ? WHY !!!????
- break
- fi
- if [[ -n $(echo " $EntreredOption" | grep " $AvailableOption" ) ]]; then
- break
- fi
- InvalidOptionList=$(echo -e "$InvalidOptionList \n $EntreredOption")
- done
- done
- InvalidOptionList=$(echo "$InvalidOptionList" | sed 's/ //g' | sort -u | tr "\n" " ")
- # print invalid options and exit script_information
- if [[ -n $InvalidOptionList ]]; then
- usage "invalid option: $InvalidOptionList"
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- configure_dialog () {
- # create config file
- ConfigParameterList=$(cat $0 | grep -A16 "configure_dialog () {" | grep "read -e -p \" Enter" | awk -F " " '{print $NF}')
- # display Var input prompt and default value, enter/edit value
- printf "\n"
- # default value # varname in configfile
- read -e -p " Enter available hosts (user1@host1 user1@host2): " -i "${VboxHostLoginList}" VboxHostLoginList
- read -e -p " Enter vbox manager user: " -i "${VboxManagerSSHKeyUser:-$(whoami)}" VboxManagerSSHKeyUser
- read -e -p " Enter configuration file: " -i "${ConfigFile:-$HOME/.vbox_mgr.cfg}" ConfigFile
- read -e -p " Enter VM specifications storage file: " -i "${VmSpecListFile:-$HOME/.vbox_mgr_vm_specs.list}" VmSpecListFile
- read -e -p " Enter connection timeout (seconds): " -i "${SSHCheckConnectionTimeout:-10}" SSHCheckConnectionTimeout
- if [[ -z $XfreeRDP ]] && [[ -z $(which xfreerdp) ]]; then
- XfreeRDP="not found, please install xfreerdp"
- fi
- read -e -p " Enter xfreerdp path: " -i "${XfreeRDP:-$(which xfreerdp)}" XfreeRDP
- read -e -p " Enter screen resolution: " -i "${ScreenRes:-1650x900x32}" ScreenRes
- # print new Vars
- printf "\n new configuration values: \n\n"
- for i in $ConfigParameterList; do
- echo " $i=\""$(eval echo $(echo "$"$i))\"
- done
- # check for existing config file
- if [[ -s $ConfigFile ]]; then
- printf "\n"
- read -e -p " overwrite existing configuration (y/n) " -i "y" OverwriteConfig
- if [[ $OverwriteConfig == [yY] ]]; then
- rm $ConfigFile
- else
- sed -i '/Reconfigure=true/d' $ConfigFile
- sed -i '/CreateNewConfig=true/d' $ConfigFile
- printf "\n existing configuration :\n\n"
- cat $ConfigFile
- exit
- fi
- fi
- # write Vars to config file
- for i in $ConfigParameterList; do
- echo "$i=\""$(eval echo $(echo "$"$i))\" >> $ConfigFile
- done
- printf " configuration saved in: $ConfigFile\n\n"
- sed -i "s|^ ConfigFile=.*| ConfigFile=$ConfigFile|" $(readlink -f $0) $HOME/.vbox_mgr.cfg #check for first run
- chmod 600 $ConfigFile
- # check for configuration changes
- if [[ ! $(md5sum $ConfigFile) == $ConfigfileMD5SumOld ]]; then
- printf "$(tput setaf 1) configuration changed - please update VM specs: $(tput sgr0)\n"
- printf "$(tput setaf 2) ( $0 -us ) $(tput sgr0)\n\n"
- else
- printf "$(tput setaf 3) no configuration changes $(tput sgr0)\n\n"
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- set_vm_vars_from_configfileline () { # usage: set_vm_vars_from_configfileline <hostnumer.vmnumber>
- # load processingline from config file
- ProcccessingLine=$(grep "^$1" <<< $VmSpecList)
- if [[ -n $ProcccessingLine ]]; then
- # set processing vars
- for Var in User=2 Host=3 VMID=4 RDPPort=5 CPU=6 RAM=7 OS=8 VMName=9 VMDisk=10 VMDiskSize=11 ;do
- VarName=$( cut -d "=" -f1 <<< $Var)
- ConfigfileField=$( cut -d "=" -f2 <<< $Var)
- eval $VarName=\"$(echo $ProcccessingLine | cut -d "|" -f$ConfigfileField)\"
- done
- VarLoadError=0
- else
- printf "$(tput setaf 1)virtual machine $1 not found$(tput sgr0)\n"
- VarLoadError=1
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- check_config () {
- if [[ -s $ConfigFile ]] && [[ -z $(cat $ConfigFile | grep "Reconfigure=true\|CreateNewConfig=true") ]]; then
- # read config file
- source $ConfigFile
- elif [[ -s $ConfigFile ]] && [[ -n $(cat $ConfigFile | grep "Reconfigure=true") ]]; then
- # read config and reconfigure
- source $ConfigFile
- configure_dialog
- elif [[ ! -s $ConfigFile ]] || [[ -n $(cat $ConfigFile | grep "CreateNewConfig=true") ]]; then
- # create new config file
- rm $ConfigFile &> /dev/null
- configure_dialog
- exit
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- check_execution_user () {
- # check execution user
- if [ ! "$(whoami)" = "$VboxManagerSSHKeyUser" ]; then
- printf "$(tput setaf 1) SSH key authentication user required $VboxManagerSSHKeyUser. You are $(whoami) \n$(tput sgr0)"
- exit 1
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- host_connection_check () { # VboxHostLogin var has to be set
- host_connection_check_thread () {
- Host=$(echo $VboxHostLogin | cut -d "@" -f2)
- Host=${Host/127.0.0.1/localhost}
- User=$(echo $VboxHostLogin | cut -d "@" -f1)
- # check for local execution on same user, no ssh connection required
- if [[ -n $( grep localhost <<< "$VboxHostLogin") ]]; then
- if [[ ! $User == $(whoami) ]]; then
- printf "$(tput setaf 1)unknown vbox user on local machine$(tput sgr0)"
- return
- fi
- HostVMListDetails=$(for i in $(VBoxManage list vms ) ; do vboxmanage showvminfo $i 2>> /dev/null ; done && echo VirtualHarddisks: && VBoxManage list hdds)
- if [[ $? == 0 ]]; then
- printf "$(tput setaf 2)online$(tput sgr0)"
- else
- printf "$(tput setaf 1)unknown error$(tput sgr0)"
- fi
- # check SSH connection to destination host
- else
- SSHCheckConnectionTimeout=2
- CMDTimeout=$(($SSHCheckConnectionTimeout+1))
- SSHOutoutLogfile="/tmp/.vbx-ssh.log"
- echo > $SSHOutoutLogfile
- timeout $CMDTimeout ssh -v -o ConnectTimeout=$SSHCheckConnectionTimeout $VboxHostLogin -E $SSHOutoutLogfile 2>&1 exit
- #TODO => use ssh return values for error output => https://support.microfocus.com/kb/doc.php?id=7021696
- SSHOutputV="$(cat $SSHOutoutLogfile)"
- if [[ -n $(grep "No route to host" <<< $SSHOutputV) ]] ; then
- printf "$(tput setaf 1)offline, host unreachable$(tput sgr0)"
- elif [[ -n $(grep "Connection established" <<< $SSHOutputV) ]] ; then
- printf "$(tput setaf 2) online$(tput sgr0)"
- if [[ -n $(grep "Authenticated to $Host" <<< $SSHOutputV) ]] ; then
- printf ",$(tput setaf 2) authentication ok $CheckMark$(tput sgr0)"
- elif [[ -n $(grep "Next authentication method: password" <<< $SSHOutputV | tail -n 1) ]] ; then
- printf ",$(tput setaf 1) authentication failed (ssh key) $(tput sgr0)"
- elif [[ -n $(grep "Connection refused" <<< $SSHOutputV | tail -n 1) ]] ; then
- printf ",$(tput setaf 1) authentication error$(tput sgr0)"
- fi
- else
- printf "$(tput setaf 1)Unknown error$(tput sgr0)"
- fi
- fi
- }
- # check all hosts from config file
- if [[ $1 == ALL ]]; then
- for VboxHostLogin in $VboxHostLoginList ; do
- HostNumber=$(echo "$VboxHostLoginList" | tr " " "\n" | nl | grep -w "$VboxHostLogin" | awk '{print $1}')
- printf "Connection check for host #$HostNumber $VboxHostLogin: " | awk -F ":" '{printf " %-65s %s %s ",$1, $2, $3}'
- host_connection_check_thread
- printf "\n"
- done
- else
- host_connection_check_thread
- fi
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- list_VM_status () {
- AvailableHosts=$(echo "$VboxHostLoginList" | tr " " "\n" | nl |sed 's/^[[:blank:]]*//')
- # create specific hostlist ( -ls <number|host|string )
- ProcessingHosts=$(for i in $( grep -v "ls" <<< $ListVMStatus) ; do
- # check for host number input
- if [[ -z $(sed 's/[[:digit:]]//g' <<< $i) ]]; then
- if [[ -n $(echo "$AvailableHosts" | grep ^$i) ]]; then
- echo "$AvailableHosts" | grep ^$i
- else
- # write error message
- echo "unknown host number: $i"
- fi
- # check for string input ( IP,host,user, etc.)
- elif [[ -n $(echo "$AvailableHosts" | grep $i ) ]]; then
- echo "$AvailableHosts" | grep $i
- # write error message
- else
- echo "string not found in hostlist: $i"
- fi
- done | sort -u )
- # print input errors
- if [[ -n $(grep -v ^[[:digit:]] <<< $ProcessingHosts) ]]; then
- usage "$( grep -v ^[[:digit:]] <<< "$ProcessingHosts")"
- fi
- # set/clear VboxHostLoginList ( set all hosts from config for -ls only command )
- if [[ $ListVMStatus == "-ls" ]]; then
- VboxHostLoginList=$VboxHostLoginList
- else
- VboxHostLoginList=
- fi
- # rewrite VboxHostLoginList. check entered hosts/strings.
- for i in $( awk -F "^[[:digit:]]" '{print $2}' <<< $ProcessingHosts ) ; do
- # check for unknown hosts/strings
- if [[ -z $(echo "$AvailableHosts" | grep -w $i ) ]]; then
- echo "unknown host"
- fi
- # write specefied hosts to VboxHostLoginList
- if [[ -n $(echo "$AvailableHosts" | grep $i ) ]]; then
- VboxHostLoginList=$(echo $VboxHostLoginList $i)
- fi
- done
- # get virtual machine list from $VboxHostLoginList
- for VboxHostLogin in $(echo "$VboxHostLoginList" | tr " " "\n") ; do
- Host=$(echo $VboxHostLogin | cut -d "@" -f2)
- Host=${Host/127.0.0.1/localhost}
- User=$(echo $VboxHostLogin | cut -d "@" -f1)
- HostNumber=$(echo "$AvailableHosts" | grep $VboxHostLogin | awk '{print $1}')
- # check for config errors ( missing VMs ) in $VmSpecListFile
- if [[ -n $(cat $VmSpecListFile | grep $VboxHostLogin | grep UpdateSpecsError ) ]]; then
- printf "|VMs on Host $HostNumber ($VboxHostLogin): |" | awk -F "|" '{printf "\n%s %-42s %s ",$1, $2, $3}' >&2
- printf "$(tput setaf 1)|No virtual machines detected $(tput setaf 3)| update virtual machine specs: $0 -us|\n $(tput sgr0)" |\
- awk -F "|" '{printf "\n%s %-47s %s ",$1, $2, $3}' >&2
- continue
- else
- printf "|VMs on Host $HostNumber ($VboxHostLogin): |" | awk -F "|" '{printf "\n%s %-42s %s ",$1, $2, $3}' >&2
- fi
- #TODO count calculate max caracter count for $VboxHostLogin VMName auto adjust slot width count VboxHostLogin
- SlotWidthCountVboxHostLogin=$(echo "$VmSpecList" | cut -d "|" -f3 | sed 1d | sort -u | awk '{ print length, $2 }' | sort -n | tail -1)
- SlotWidthCountVMName=$(echo "$VmSpecList" | grep -v "|||" | cut -d "|" -f9 | sed 1d | sort -u | awk '{ print length, $2 }' | sort -n | tail -1)
- ## Create HostVMList
- # create virtual machine list from local host
- if [[ $Host == "localhost" ]]; then
- if [[ ! $User == $(whoami) ]]; then
- printf "$(tput setaf 1) unknown user on local machine$(tput sgr0)\n" >&2
- continue
- fi
- HostVMList=$(VBoxManage list vms && echo running vms: && VBoxManage list runningvms)
- HostVMListCMDExitCode=$?
- # create virtual machine list from remote host
- else
- HostVMList=$(timeout $SSHCheckConnectionTimeout ssh $VboxHostLogin "VBoxManage list vms && echo running vms: && VBoxManage list runningvms" 2>/dev/null )
- HostVMListCMDExitCode=$?
- fi
- # if host is unreachable run host connection check
- if [[ ! $HostVMListCMDExitCode == 0 ]]; then
- HostConnectionCheckOutput=$(host_connection_check $VboxHostLogin)
- printf "$HostConnectionCheckOutput\n" >&2
- # create virtual machine list from local VmSpecList
- HostVMList=$(echo "$VmSpecList" | grep "$Host" |sed '1d' | awk -F "|" '{printf "\"%s\" {%s}\n", $9 , $4}')
- else
- printf "$(tput setaf 2)host connected$(tput sgr0)\n" >&2
- HostConnectionCheckOutput=
- fi
- ## Create HostVMList completed
- # proccess HostVMList for function output
- SAVEIFS=$IFS
- IFS=$(echo -en "\n\b")
- HostVMRunIDList=$(echo "$HostVMList" | grep -A50 "running vms:" | awk '{print $NF}' | sed '1,1d' )
- HostVMRunIDList=${HostVMRunIDList:-none}
- for VM in $HostVMList; do
- # skip extra output for running vm entires in HostVMList, entries are used to mark running vms from HostVMList
- if [[ -n $(echo $VM| grep "running vms:") ]]; then
- break
- fi
- VMName=$(echo $VM | cut -d '"' -f2)
- VMID=$(echo $VM | cut -d '"' -f3 | sed 's/ {//g' | tr -d "}")
- # create VM status entry ( running vms )
- for RunningVMID in $HostVMRunIDList ;do
- VMStatus="$(tput setaf 1) Offline $(tput sgr0)"
- if [[ $(echo $VM | grep "$RunningVMID") ]]; then
- VMStatus="$(tput setaf 2) Online $(tput sgr0)"
- break
- fi
- done
- if [[ -n $HostConnectionCheckOutput ]]; then
- VMStatus="$(tput setaf 1) Unkown $(tput sgr0)"
- fi
- VMNumber=$(echo "$VmSpecList" | grep $VMID | awk -F "|" '{print $1 }'| head -n1)
- echo "|$VMNumber|$VMName|$VboxHostLogin|$VMID|$VMStatus|"
- done
- IFS=$SAVEIFS
- #printf "Nr.|Virtual Machine Name|Host|ID|Status|\n"
- done | awk -F "|" '{printf " %-4s %-38s %-20s %s %s %s %s \n", $2, $3, $4, $5, $6, $8, $7}'
- printf "\n"
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- update_vm_specifications () {
- echo "specs updated on $(date +%s)" > $VmSpecListFile
- chmod 600 $VmSpecListFile
- # load vm specs from all hosts
- for VboxHostLogin in $VboxHostLoginList ; do
- HostCounter=${HostCounter:-0}
- HostCounter=$(($HostCounter+1))
- Host=$(echo $VboxHostLogin | cut -d "@" -f2)
- User=$(echo $VboxHostLogin | cut -d "@" -f1)
- printf "\n%-70s" " updating virtual machine specifications from $VboxHostLogin" >&2
- CMDTimeout=$(($SSHCheckConnectionTimeout+1))
- # get host vm information details - local execution - no ssh connection required
- if [[ -n $( grep localhost <<< "$VboxHostLogin") ]]; then
- # check for correct user on local machine
- if [[ ! $User == $(whoami) ]]; then
- host_connection_check $VboxHostLogin >&2
- continue
- fi
- HostVMListDetails=$(for i in $(VBoxManage list vms ) ; do vboxmanage showvminfo $i 2>> /dev/null ; done && echo VirtualHarddisks: && VBoxManage list hdds)
- if [[ $? == 0 ]]; then
- printf "$(tput setaf 2)done$(tput sgr0)" >&2
- else
- printf "$(tput setaf 1)unknown error$(tput sgr0)" >&2
- fi
- # get host vm information details - ssh connection required
- else
- HostVMListDetails=$(timeout $CMDTimeout ssh $VboxHostLogin 2>/dev/null \
- '''for i in $(VBoxManage list vms ) ; do vboxmanage showvminfo $i 2>> /dev/null ; done && echo VirtualHarddisks: && VBoxManage list hdds ''')
- # if host is offline run single connection check and quit loop
- if [[ ! $? == 0 ]]; then
- UpdateSpecsErrorMSG=UpdateSpecsError
- host_connection_check $VboxHostLogin >&2
- else
- printf "$(tput setaf 2)done$(tput sgr0)" >&2
- fi
- fi
- printf "\n$HostCounter.0||||||||Virtual Machines located on: $VboxHostLogin $UpdateSpecsErrorMSG\n"
- UpdateSpecsErrorMSG=
- # Filter VM parameter
- VMUUIDList=$(echo "$HostVMListDetails" | grep -A4 "^Name:" | grep UUID: | awk '{print $2}')
- SAVEIFS=$IFS
- IFS=$(echo -en "\n\b")
- VMNumber=0
- for VMUUID in $VMUUIDList ; do
- VMNumber=$(($VMNumber+1))
- VMName=$(echo "$HostVMListDetails" | grep -B4 $VMUUID | grep "Name:" | awk '{print $2}')
- GuestOS=$(echo "$HostVMListDetails" | grep -B1 $VMUUID | grep "Guest OS:" | awk '{print $3,$4}' | sed 's/ //')
- VMCPU="$(echo "$HostVMListDetails" | grep -A100 $VMUUID | grep "CPU exec cap:" | awk '{print $4}')%"
- VMRAM=$(echo "$HostVMListDetails" | grep -A100 $VMUUID | grep "Memory size" | awk '{print $3}')
- VMNet=$(echo "$HostVMListDetails" | grep "NIC 1: MAC:" | awk '{print $3}') # not needed
- VMGuiRes=$(echo "$HostVMListDetails" | grep -A100 $VMUUID | grep "Video mode:" | awk '{print $3}') # value only if vm runs,
- RDPPort=$(echo "$HostVMListDetails" | grep -A150 $VMUUID | grep "VRDE port:" | awk '{print $3}') # VBox 6.x
- if [[ -z $RDPPort ]]; then
- RDPPort=$(echo "$HostVMListDetails" | grep -A150 $VMUUID | grep "VRDE property .* : TCP/Ports = " | awk '{print $NF}' | tr -d '"') # VBox 5.X
- fi
- RDPPort=${RDPPort:- none}
- # write new line for each virtual disk
- VMDiskPathAll=$(echo "$HostVMListDetails" | grep -A100 $VMUUID | grep "vmdk\|vdi" | awk -F ": " '{print $2}' | sed 's/ (UUID.*$//' )
- for VMDiskPath in $VMDiskPathAll ; do
- VMDiskSize="$(echo "$HostVMListDetails" | grep -A100 "VirtualHarddisks:" | grep -A2 $VMDiskPath | grep "Capacity" | awk '{print $2}')MB"
- printf "$HostCounter.$VMNumber|$User|$Host|$VMUUID|:$RDPPort|$VMCPU|$VMRAM|$GuestOS|$VMName|$VMDiskPath|$VMDiskSize|\n"
- done
- done
- IFS=$SAVEIFS
- done >> $VmSpecListFile
- printf "\n\n"
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- show_vm_specifications () {
- # 1 2 3 4 5 6 7 8 9 10 11
- (echo "Nr.| User|Host | UUID| RDP| CPU| RAM| OS|VM-Name|VM-Disk-Path| Disk" && echo "$VmSpecList" | grep -v "specs updated on") \
- | awk -F "|" '{printf " %3-s %-38s %20s%s %-8s %-15s %5s %8s %10s %-37s %s %s \n",$1, $9, $3, $5, $2, $8, $6, $7, $11, $4, $10 ,$1}'
- printf "\n last update: $(date -d @$(echo $(echo "$VmSpecList" | grep 'specs updated on ') | awk -F 'specs updated on ' '{printf $NF}'))\n"
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- parse_numeric_processing_input () { # usage: parse_numeric_processing_input <1.1|1-X.1-X>
- proccessing_vm_input () {
- VMs=$( cut -d "." -f2 <<< $HostVMProcessing)
- # processing vms
- if [[ -n $(grep "-" <<< $VMs) ]]; then
- for VMs in $(seq $(sed 's/-/ /' <<< $VMs)); do
- printf "$Host.$VMs\n"
- done
- else
- printf "$Host.$VMs\n"
- fi
- }
- # proccessing input options
- for HostVMProcessing in $( tr " " "\n" <<< $@) ; do
- Host=$( cut -d "." -f1 <<< $HostVMProcessing)
- # processing hosts
- if [[ -n $(grep "-" <<< $Host) ]]; then
- for Host in $(seq $(sed 's/-/ /' <<< $Host) | tr "\n" " "); do
- proccessing_vm_input
- done
- else
- proccessing_vm_input
- fi
- done
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- proccessing_vm_control_options () {
- for VMControlOption in -b -rv -pv -r -h -s -p -c -C -q ; do
- # read option line
- OptionProccessingSyntax=$(echo $@ | sed 's/ -/ \n-/g'| grep '\'$VMControlOption'[0-9]' | cut -c 3-100 | tr -d [[:alpha:]])
- # check for correct numeric input
- if [[ -n $(grep [[:alpha:]] <<< $OptionProccessingSyntax) ]]; then
- printf "Syntax error for option: $VMControlOption$OptionProccessingSyntax\n" >&2
- continue
- elif [[ -n $(grep "\." <<< $OptionProccessingSyntax) ]] && [[ -n $(echo " $OptionProccessingSyntax" | grep '\'$VMControlOption) ]]; then
- printf "\n$(tput setaf 1)Error: Virtual machine $HostVMNumner not found$(tput sgr0)" >&2
- continue
- elif [[ -n $(echo $OptionProccessingSyntax | grep "\.0" ) ]]; then
- printf "\n$(tput setaf 1)Error: $OptionProccessingSyntax is a Host$(tput sgr0)" >&2
- continue
- elif [[ -n $(echo $OptionProccessingSyntax | grep "^0\." ) ]]; then
- printf "\n$(tput setaf 1)Error: $OptionProccessingSyntax is not a Host$(tput sgr0)" >&2
- continue
- elif [[ -n $(echo $OptionProccessingSyntax | grep "0-" ) ]]; then
- printf "\n$(tput setaf 1)Error: $OptionProccessingSyntax is not a Host$(tput sgr0)" >&2
- continue
- fi
- # parse multi inputs for single processing and load var for each selected VM Number for further proccessing | clear for 0.0 input
- #for HostVMNumner in $(parse_numeric_processing_input "$OptionProccessingSyntax" | sed '/.0/d' | sed '/0./d') ; do #X.10 does not work
- for HostVMNumner in $(parse_numeric_processing_input "$OptionProccessingSyntax" ) ; do
- set_vm_vars_from_configfileline $(parse_numeric_processing_input "$HostVMNumner")
- if [[ $VarLoadError == 1 ]]; then
- continue
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-b" ]]; then
- printf " start virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage startvm --type headless $VMID
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-h" ]]; then
- printf " hibernate virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage controlvm $VMID savestate
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-pv" ]]; then
- printf " pause virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage controlvm $VMID pause
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-rv" ]]; then
- printf " resume virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage controlvm $VMID resume
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-s" ]]; then
- printf "shutdown (acpi) virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage controlvm $VMID acpipowerbutton
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-r" ]]; then
- printf " reset off virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage controlvm $VMID reset
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-p" ]]; then
- printf " power off virtual machine: $VMName\n"
- ssh $User@$Host -t -t vboxmanage controlvm $VMID poweroff
- fi
- # connect VBOX host, execute command
- if [[ $VMControlOption == "-k" ]]; then
- printf " kill virtual machine: $VMName\n"
- ssh $User@$Host -t -t VBoxManage startvm $VMID --type emergencystop
- fi
- # processing options
- if [[ $VMControlOption == "-c" ]]; then
- printf " connect virtual machine via rdp protokoll: $VMName\n"
- printf " execute => xfreerdp -u $User -p V\!rtlMchn -g $ScreenRes -T $VMName @ $Host$RDPPort ($User) $Host$RDPPort & \n"
- # xfreerdp -u $User -p V\!rtlMchn -g $ScreenRes -T "$VMName @ $Host$RDPPort ($User)" $Host$RDPPort
- # Temporary file to store the command's output
- local output_file=$(mktemp)
- # Run xfreerdp in the background and redirect output to the temporary file
- xfreerdp -u "$User" -p "$XfreeRDPPassword" -g "$ScreenRes" -T "$VMName @ $Host$RDPPort ($User)" "$Host$RDPPort" > "$output_file" 2>&1 &
- # Save the background process PID
- local pid=$!
- # Small delay to capture potential error messages
- sleep 1
- # Check if the background process is still running
- # if grep -q "Do you trust the above certificate?" "$output_file"; then # check only for certificate error
- if ! kill -0 "$pid" 2>/dev/null; then
- echo "An error occurred. Starting xfreerdp in the foreground..."
- # Re-run the command in the foreground to allow interactive input
- xfreerdp -u "$User" -p "$XfreeRDPPassword" -g "$ScreenRes" -T "$VMName @ $Host$RDPPort ($User)" "$Host$RDPPort"
- else
- echo "Command started successfully in the background. Process ID: $pid"
- fi
- # Remove the temporary file
- rm -f "$output_file"
- fi
- # processing options
- if [[ $VMControlOption == "-C" ]]; then
- printf " close RDP connection : $VMName\n "
- #ssh $User@$Host -t -t vboxmanage controlvm $VMID poweroff
- # connect VBOX host, execute command_check
- fi
- # processing options
- if [[ $VMControlOption == "-q" ]]; then
- printf " (q)uit (a)ll rdp sessions: $VMName\n "
- #ssh $User@$Host -t -t vboxmanage controlvm $VMID poweroff
- # connect VBOX host, execute command_check
- fi
- done
- done
- #echo "---------------------------------------------"
- #echo "|$Host|$User|$VMID|$RDPPort|$CPU|$RAM|$OS|$VMName|$VMDisk|$VMDiskSize|"
- #echo "---------------------------------------------"
- printf "\n"
- }
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- ############################################################################################################
- ############################################# start script #############################################
- ############################################################################################################
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- # check_input_options $@ #TODO if expressions does execute even if expressions match "-m" == -m"
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- check_config
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- check_execution_user
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- # check for monochrome output
- Reset='\033[0m'
- if [[ -z $Monochrome ]]; then
- load_color_codes
- fi
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- # check help dialog
- if [[ -z "$1" ]] || [[ -n "$HelpDialog" ]] ; then usage "help dialog" ; fi
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- # check for script information
- if [[ -n $ScriptInformation ]]; then script_information ; fi
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- ############################################################################################################
- ############################################# check config #############################################
- ############################################################################################################
- # load virtual machine specs to var
- VmSpecList=$(cat "$VmSpecListFile")
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- # processing main configuration options
- if [[ -n $NewConfig ]]; then
- printf "$(tput setaf 3) Create new configuration$(tput sgr0)"
- rm $ConfigFile &> /dev/null
- sleep 0.2
- $0 -
- exit
- fi
- if [[ -n $Reconfigure ]]; then
- printf "$(tput setaf 3) Start reconfiguration:$(tput sgr0)"
- echo "Reconfigure=true" >> $ConfigFile
- check_config
- fi
- if [[ -n $ShowConfig ]]; then
- printf "$(tput setaf 3) Configfile ($ConfigFile) content: \n$(tput sgr0)"
- cat $ConfigFile
- printf "\n"ConfigLine
- fi
- if [[ -n $CheckConfig ]] || [[ -n $(grep h <<< $ListVMStatus) ]]; then
- printf "$(tput setaf 3) Start host connection check: \n$(tput sgr0)"
- host_connection_check ALL
- fi
- if [[ -n $UpdateVMSpecs ]]; then
- printf "$(tput setaf 3) Start virtual machine spec update: $(tput sgr0)"
- update_vm_specifications
- fi
- if [[ -n $ShowVMSpecs ]]; then
- show_vm_specifications
- fi
- if [[ -n $ListVMStatus ]] && [[ ! $(grep h <<< $ListVMStatus) ]]; then
- list_VM_status
- fi
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- # processing VM specific configuration options
- if [[ -n $VMConfigSet ]]; then
- printf "$(tput setaf 3) Start virtual machine configuration mode\n$(tput sgr0)"
- # check for correct input VM Number
- VMConfigSetCommand=$(echo "$VMConfigSet" | tr " " "\n" | grep -v [[:digit:]] )
- VMConfigSetProcessingHosts=$(echo "$VMConfigSet" | sed 's/'$VMConfigSetCommand'//' 2> /dev/null)
- # check for input command
- if [[ $? == 1 ]]; then
- usage " missing command: $(echo "$@") <cmd> "
- elif [[ -z $VMConfigSetProcessingHosts ]]; then
- usage " missing virtual machine: -vmcfg <hostnumber.vmnumber> $VMConfigSetCommand "
- fi
- ConfigLine
- # parse multi inputs for single processing and load var for each selected VM number for further proccessing | clear for 0.0 input
- #for HostVMNumner in $(parse_numeric_processing_input "$VMConfigSetProcessingHosts" | sed '/.0/d' | sed '/0./d') ; do
- for HostVMNumner in $(parse_numeric_processing_input "$VMConfigSetProcessingHosts" ) ; do
- set_vm_vars_from_configfileline $(parse_numeric_processing_input "$HostVMNumner")
- # skip proccessing loop when error occurs
- if [[ $VarLoadError = 1 ]]; then
- continue
- fi
- # get virtual machines status - one/first time run
- if [[ -z $GetVMStatus ]]; then
- printf "$(tput setaf 3) Check virtual machine status \n$(tput sgr0)"
- VMStatusList=$(list_VM_status 2>&1)
- GetVMStatus=done
- fi
- ProcccessingVMLine=$(echo "$VMStatusList" | grep $VMID)
- # check for running virtual machine
- if [[ -n $(echo "$ProcccessingVMLine" | grep Online) ]]; then
- printf "\n$(tput setaf 1) Virtual machine is running, shutdown for configuration \n$(tput sgr0)"
- printf "$ProcccessingVMLine\n"
- continue
- fi
- # configure vm remote desktop paramerter | infosource : https://www.virtualbox.org/manual/ch07.html
- if [[ $VMConfigSetCommand == rdp ]]; then
- # configure vrdp parameter
- RDPport=$(($(echo 10"$(echo $HostVMNumner | cut -d "." -f1)00")+$(echo $HostVMNumner | cut -d "." -f2)))
- RDPServerListenAddress=$(ssh $User@$Host hostname -I) # 0.0.0.0 to accept all connections, security risk
- Executelist_VM_status=true
- ConfigLine="--vrde on --vrdeauthtype external --vrdeaddress $RDPServerListenAddress --vrdeport $RDPport"
- printf "\n$(tput setaf 3) Set configuration:$(tput sgr0) vboxmanage modifyvm $VMID $ConfigLine\n"
- printf "$ProcccessingVMLine\n"
- # enable / set vrdp functions
- printf " execute => ssh $User@$Host -t -t vboxmanage modifyvm $VMID $ConfigLine 2> /dev/null \n"
- ssh $User@$Host -t -t vboxmanage modifyvm $VMID $ConfigLine 2> /dev/null
- fi
- done
- printf "\n update virtual machines specifications to apply changes ( $(basename $0) -us )"
- fi
- #-------------------------------------------------------------------------------------------------------------------------------------------------------
- proccessing_vm_control_options $@ # to do -b 2.3 4.4 doenst work => works -b2.3 4.4
- #------------------------------------------------------------------------------- ------------------------------------------------------------------------
- exit 0
- #------------------------------------------------------------------------------------------------------------
- ############################################################################################################
- ########################################## changelog / notice ###########################################
- ############################################################################################################
- #------------------------------------------------------------------------------------------------------------
- # Configure Virtualbox Host for RDP connection, execute directly on host:
- #####################################################################################################
- # => ConfigLine="--vrde on --vrdeauthtype external --vrdeaddress 192.168.1.80 --vrdeport 10000"
- # => vboxmanage list vms
- # => vboxmanage modifyvm 6047df41-7c93-43f2-9dac-0de61e35f16d $ConfigLine
- #####################################################################################################
- # known issues :
- #
- # RDP connection failure solutions :
- # - Is RDP connection in VM configs enabled ?
- # - Is RDP connection for non local connecntion available ( Display => Remote desktop server port => LAN IP instead 127.0.0.1 )
- # => VBoxManage modifyvm "[VM_NAME]" --vrdeaddress [0.0.0.0|LAN_IP|$(hostname -I)]
- # create vbox internal rdp user => https://www.marcomadeit.com/2017/02/26/set-user-authentication-in-virtualbox-remote-desktop-rdp/
- # => https://docs.oracle.com/en/virtualization/virtualbox/6.1/admin/vrde.html
- # => https://github.com/phpvirtualbox/phpvirtualbox/issues/31
Quellcode
Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN