#!/bin/bash ## ## Introduction: ## My preferred SHELL is ksh, as we have had a long and illustrious ## career together; however I have used BASH here to keep things ## simpler for this automation "demonstration" project. ## ## I.E. show my scripting skills using a shell that should be ## on any Linux system in existence by default. ## ## If I were writing an application I would use Perl OR Java. ## This however is an OS service setup automation and BASH ## will suit us well. ## ## AUTHOR: ancient.wizard@verizon.net (V Burns) ## DATE: 2014/Mar-Apr ## ## LICENSE: "Artistic License" ## ## ## TESTED ON: ## Fedora 20 minimal server install. Expected to work ## on earlier versions also ## CentOS 6.4 minimal server; expected to work on 3.x - 6.x ## including RedHat ## Ubuntu 12.04 desktop/server; fully expect it to work on ## the 10.04 through "current" releases. ## Debian 7 minimal server; wget https broken, added curl ## as fallback on a wget fail. (yuck!) ## OpenSUSE 13.1; expected to work with 11.X and above ## 10.x is suffciently different it will *not* work ## even though the server is capable of providing PXE ## services. ## Arch-Linux base install ## ## NOTES: ## This script is not comprehensive or production ready. It ## makes too many assumptions and provides no options or ## flexibility for alternative solutions. It simply shows ## one simple way to build a PXE boot server quickly. It is ## a demonstration after all! ## ## ASSUMPTIONS & ISSUES: ## 1) The system to be PXE enabled has networking up and working ## properly. (kind of the point) ## 2) The system to be PXE enabled is the "default/minimal" install ## without local standards applied. For example a system with ## iptables enabled on which otherwise would not be enabled ## could be a problem as it may not be enabled properly to ## allow connections to services by this script. In that case ## disable the firewall or manually configure it yourself. The ## primary issue will be that we were unable to "save" the ## firewall filters before a restart so they were lost. Check the ## logs after the run fpor the comamnd used to "add" the filter ## and you can deal with saving to allow fro reboots and restarts ## remembering this/these setting(s). ## 3) The curl package should be pre-installed on Debian because wget ## may fail to work with the https: protocol to pull menu content. ## 4) The system to be PXE enabled is not doing something important ## (we will break any exising dhcp & tftp servers on the system, ## the script assumes it has control) ## 5) The PXE system has Internet access to allow package installation. ## Configurating proxies is yours todo before using the script! ## 6) Local Network has standard DHCP services from a local router ## [ home OR office etc ] ( we don't need fixed IP's for this, ## and we only want to handle PXE DHCP requests if we can ) ## 7) Other system(s)/VM(s) with PXE client enabled NIC's are available ## (we need the server and at least one client to demo example) ## 8) Arch Linux may not work; during my tests the pxelinux.0 which ## is offered by teh Arch system crashes my test PXE client. ## ## Enjoy! ## #-- Build PATH PATH=/usr/bin:/bin [ -d /usr/sbin ] && PATH=${PATH}:/usr/sbin [ -d /sbin ] && PATH=${PATH}:/sbin #-- Detect (problem) Commands CMD_IP=$(which ip 2>/dev/null||echo ip-notfound) CMD_IPCALC=$(which ipcalc 2>/dev/null||echo ipcalc-notfound) CMD_IFCFG=$(which ifconfig 2>/dev/null||echo ifconfig-notfound) CMD_SERVICE=$(which service 2>/dev/null||echo service-notfound) CMD_SYSTEMCTL=$(which systemctl 2>/dev/null||echo systemctl-notfound) CMD_FWCMD=$(which firewall-cmd 2>/dev/null||echo firewall-cmd-notfound) ## Define a few Functions isNicUP() { [ -x $CMD_IP ] && { $CMD_IP link show ${1-eth0} 2>/dev/null|grep -qi up; return $?; } [ -x $CMD_IFCFG ] && $CMD_IFCFG ${1-eth0} > /dev/null 2>&1 return $? } getNicIP() { [ -x $CMD_IP ] && { echo $($CMD_IP addr show ${1-eth0}|grep 'inet '|awk '{print $2}'|sed 's=/.*==' 2>/dev/null) return $? } [ -x $CMD_IFCFG ] && echo $( $CMD_IFCFG ${1-eth0}|grep 'inet '|awk '{print $2}'|sed 's/^addr://' ) } getNicBcst() { BCST= [ -x $CMD_IP -a -x $CMD_IPCALC ] && { IPMASK=$($CMD_IP addr show ${1-eth0}|grep 'inet '|awk '{print $2}' 2>/dev/null) BCST=$($CMD_IPCALC -b $IPMASK) BCST=${BCST#*=} } [ -x $CMD_IP -a "$BCST" == '' ] && { BCST=$($CMD_IP addr show ${1-eth0}|grep 'inet '|awk '{print $4}' 2>/dev/null) } [ -x $CMD_IFCFG -a "$BCST" == '' ] && { BCST=$( /sbin/ifconfig ${1-eth0}|grep 'inet addr:'|awk '{print $3}'|awk -F: '{print $2}' ) } [ -x $CMD_IFCFG -a "$BCST" == '' ] && { BCST=$( $CMD_IFCFG ${1-eth0}|grep 'inet ' | \ sed 's/netmask /netmask:/g' | \ sed 's/broadcast /broadcast:/g' | \ awk '{print $4}'|awk -F: '{print $2}' ) } echo $BCST } getNicMask() { MASK= [ -x $CMD_IP -a -x $CMD_IPCALC ] && { IPMASK=$($CMD_IP addr show ${1-eth0}|grep 'inet '|awk '{print $2}' 2>/dev/null) MASK=$( $CMD_IPCALC -m $IPMASK) MASK=${MASK#*=} } [ -x $CMD_IP -a "${MASK}" == '' ] && { MASK=$($CMD_IP addr show ${1-eth0}|grep 'inet '|awk '{print $2}'|sed 's=.*/==' 2>/dev/null) case $MASK in 24) MASK='255.255.255.0' ;; esac } # MASK=$( $CMD_IFCFG ${1-eth0}|grep 'inet addr:'|awk '{print $4}'|awk -F: '{print $2}' ) [ -x $CMD_IFCFG -a "${MASK}" == '' ] && { MASK=$( $CMD_IFCFG ${1-eth0}|grep 'inet ' | \ sed 's/netmask /netmask:/g' | \ sed 's/broadcast /broadcast:/g' | \ awk '{print $3}'|awk -F: '{print $2}' ) } echo $MASK } getDefaultRoute() { ip route show|grep -i default|head -1|awk '{print $3}' 2> /dev/null } isNicIPed() { IP=$(getNicIP ${1-eth0}) [ '' != "$IP" ] return $? } CheckNic() { #-- Selected NIC NIC=${1-eth0} isNicUP $NIC && isNicIPed $NIC && \ { showMessage "NIC Status ($NIC)" showStatus $? } return $? } OK=0 FAIL=1 WARN=-1 INFO=-2 showMessage() { printf " %-32s : " "$1"; } showStatus() { STA=$1 # Status NOT=$2 # Note [ $STA -eq 0 ] && ST=OK || ST=FAIL [ $STA -eq -1 ] && { ST=WARN; STA=1; } [ $STA -eq -2 ] && { ST=INFO; STA=1; } [ '' == "$NOT" ] && echo $ST [ '' == "$NOT" ] || printf "%-4s [ %s ]\n" $ST "$NOT" return $STA } processAction() { MSG=$1 CMD=$2 LOG=$3 STATUS=0 showMessage "$MSG" ( echo '#'; echo "# $CMD" ) >> ${LOG}.$$ 2>&1 $CMD >> ${LOG}.$$ 2>&1 STATUS=$? showStatus $STATUS "check: ${LOG}.$$" return $STATUS } ## ## Announce our title ## Detect OS "TYPE OR STyle" ## locate a package installer ## echo echo ' PXE Environment Setup Tool' echo ' ( an automation demonstration script )' echo showMessage 'Prune Logs from prior runs' /bin/rm -f /tmp/pxe-*.log.[0-9]* showStatus 0 || exit $? OS_NAME= OS_Ubuntu=0 OS_openSUSE=0 OS_Fedora=0 OS_RedHat=0 OS_CentOS=0 OS_Debian=0 OS_Arch=0 showMessage 'Detect OS Name' while : do release=os-release if [ -f /etc/$release ] then OS_NAME=$(grep -i '^name' /etc/$release) OS_NAME=${OS_NAME#*=} OS_NAME=${OS_NAME#\"} OS_NAME=${OS_NAME%\"} OS_NAME=${OS_NAME%% *} break fi release=system-release if [ -f /etc/$release ] then OS_NAME=$( head -1 /etc/$release ) OS_NAME=${OS_NAME%% *} break fi release=lsb-release if [ -f /etc/$release ] then OS_NAME=$(grep -i 'id=' /etc/$release|head -1) OS_NAME=${OS_NAME#*=} OS_NAME=${OS_NAME#\"} OS_NAME=${OS_NAME%\"} OS_NAME=${OS_NAME%% *} break fi release=redhat-release if [ -f /etc/$release ] then OS_NAME=$(head -1 /etc/$release|sed 's= ==') OS_NAME=${OS_NAME%% *} break fi break done if [ "$OS_NAME" == '' ] then showStatus $INFO 'Not Detected' ls -l /etc/*release echo exit 1 else showStatus $INFO "$OS_NAME" fi #-- Set an OS FLAG case $OS_NAME in Ubuntu) OS_Ubuntu=1 ;; openSUSE) OS_openSUSE=1 ;; Fedora) OS_Fedora=1 ;; RedHat) OS_RedHat=1 ;; CentOS) OS_CentOS=1 ;; Debian) OS_Debian=1 ;; Arch) OS_Arch=1 ;; esac INSTALLER= [ -x /usr/bin/pacman ] && INSTALLER='/usr/bin/pacman --sync --noconfirm' [ -x /usr/bin/yum ] && INSTALLER='/usr/bin/yum --assumeyes install' [ -x /usr/bin/apt-get ] && INSTALLER='/usr/bin/apt-get --assume-yes install' [ -x /usr/bin/zypper ] && INSTALLER='/usr/bin/zypper --non-interactive install' [ '' == "$INSTALLER" ] && iFound=1 || iFound=0 showMessage 'Locate package installer' showStatus $iFound "$INSTALLER" || exit $? ## ## The Steps we/YOU need to take to bring PXE booting to life. ## ## 1) Build a system/VM using a Linux Distro that this ## script supports; you must do this yourself and download ## this script to it. ## ## Yes - this step is on you! ## ## ## 2) Verify we have at least one working network interface. ## We'll be configuring DHCP for the first that is working. ## It is possible to use all of them and setup services to ## respond to each interface properly to make this work. ## (I could add this feature if properly motivated) ## #-- First NIC UP wins! NICS=$( cd /sys/class/net/; ls -d * | egrep -v 'all|default|lo' ) for NIC in ${NICS} do CheckNic $NIC && break done [ $? -eq 1 ] && exit $? showMessage "NIC IP ($NIC)" showStatus $INFO "$(getNicIP $NIC)" showMessage "NIC Mask ($NIC)" showStatus $INFO "$(getNicMask $NIC)" showMessage "NIC Broadcast ($NIC)" showStatus $INFO "$(getNicBcst $NIC)" ## ## 3) Install packages we'll be needing to implement this solution. ## ## Primarily: tftpd, inetd, dhcpd and syslinux ## dhcpd: Answers bootp/dhcp requests from PXE systems needing ## an IP and other information to start the booting process ## from the network. ## inetd: Monitors the tftpd network port and runs ftpd to handle ## incoming tftp requests. ## tftpd: Provides files to PXE systems. ## (poor mans filesystem in a sense) ## syslinux: Includes binaries used by PXE ## ## Secondary: wget, curl, lsof, tftp ## wget & curl: used by script to pull PXE menus from internet ## and install in the tftpboot directory. (example menus) ## others: Useful for troubleshooting if things do not work as ## expected. ## #-- Install selected packages and dependencies msg='Installing Packages' log='/tmp/pxe-packages.log' pkg='wget curl lsof tftp' ## SYSLINX for everyone pkg="syslinux $pkg" ## Packages we need to get tftpd and some form of inetd istalled case $OS_NAME in RedHat|CentOS|Fedora) pkg="tftp-server $pkg" ;; openSUSE) pkg="tftp yast2-tftp-server $pkg" ;; Arch) pkg="iputils xinetd $pkg" ;; *) pkg="tftpd $pkg" ;; esac ## Packages we need to get DHCPD installed case $OS_NAME in RedHat|CentOS|Fedora|Arch) pkg="dhcp $pkg" ;; openSUSE) pkg="yast2-dhcp-server dhcp-server $pkg" ;; *) pkg="dhcp3-server $pkg" ;; esac showMessage "Package List ($OS_NAME)" showStatus $INFO "$pkg" processAction "$msg" "$INSTALLER $pkg" $log || exit $? ## ## 4) Configure & restart services ## ## - tftpd ## - inetd / xinetd ## - dhcp ## - firewall rules ## #-- Provide a /etc/xinetd.d/tftp ## (if not included in package YUCK!) if [ -d /etc/xinetd.d ] then if [ ! -f /etc/xinetd.d/tftp ] then showMessage 'Install /etc/xinetd.d/tftp' cat > /etc/xinetd.d/tftp < $cmd <> ${log}.$$ 2>&1 fi if [ -d /srv/tftpboot -a ! -h /srv/tftpboot ] then rmdir /srv/tftpboot >> ${log}.$$ 2>&1 fi if [ -d /srv -a -d /var/lib/tftpboot -a ! -e /srv/tftpboot ] then processAction "Symlink /srv/tftpboot" 'ln -s /var/lib/tftpboot /srv/' $log || exit $? fi #-- Enable tftpd msg='Enabling TFTPD' log=/tmp/pxe-tftpd-service.log if [ -x /sbin/yast2 ] then processAction "$msg (enab)" '/sbin/yast2 tftp-server status enable' $log || exit $? processAction "$msg (show)" '/sbin/yast2 tftp-server status show' $log || exit $? processAction "$msg (path)" '/sbin/yast2 tftp-server directory path=/var/lib/tftpboot' $log || exit $? processAction "$msg (list)" '/sbin/yast2 tftp-server directory list' $log || exit $? elif [ -x /sbin/chkconfig ]; then processAction "$msg" "/sbin/chkconfig tftp on" $log || exit $? else showMessage "$msg" showStatus 0 'Assumed' || exit $? fi #-- verify (Hard Cases - manual) if [ -f /etc/inetd.conf -a "$OS_NAME" == 'Debian' ] then showMessage "$msg (inetd.conf)" echo "sed -i '/^tftp/ s=/srv/tftp=/var/lib/tftpboot=' /etc/inetd.conf" >> ${log}.$$ 2>&1 sed -i '/^tftp/ s=/srv/tftp=/var/lib/tftpboot=' /etc/inetd.conf >> ${log}.$$ 2>&1 showStatus $? "check: ${log}.$$" || exit $? # processAction "$msg" "sed -i '/^tftp/ s=/srv/tftp=/var/lib/tftpboot=' /etc/inetd.conf" $log || exit $? fi if [ -f /etc/xinetd.d/tftp ] then #-- Verify disable setting TFTPD_DISABLED=$(grep -i disable /etc/xinetd.d/tftp|awk -F= '{print $2}'|sed 's=[ \"]==g') showMessage "$msg (manual)" if [ "$TFTPD_DISABLED" == 'yes' ] then sed -i '/disable/ s/yes/no/i' /etc/xinetd.d/tftp >> ${log}.$$ 2>&1 showStatus $? "enabled ${log}.$$" || exit $? else showStatus 0 "Verified ${log}.$$" || exit $? fi #-- Verify tftpboot location TFTPD_BOOTDIR=$(grep -i server_args /etc/xinetd.d/tftp|awk -F= '{print $2}'|sed 's=-[a-z]=='|sed 's=[ \"]==g') showMessage "Configure tftpboot dir" if [ "$TFTPD_BOOTDIR" == '/var/lib/tftpboot' ] then showStatus 0 'Verified - /var/lib/tftpboot' || exit $? else TFTPD_BOOTDIR=$(echo $TFTPD_BOOTDIR|sed 's=/=\\/=g') sed -i '/server_args/ s/'${TFTPD_BOOTDIR}'/\/var\/lib\/tftpboot/' /etc/xinetd.d/tftp showStatus $? 'set: /var/lib/tftpboot' || exit $? fi fi #-- Restart xinetd # default == xinetd # Debian == openbsd-inetd msg='Service' log=/tmp/pxe-inetd-service.log pkg=xinetd case $OS_NAME in Debian) pkg='openbsd-inetd' ;; esac msg="$msg $pkg" if [ -x $CMD_SYSTEMCTL ] then processAction "$msg (start)" "$CMD_SYSTEMCTL start $pkg" $log || exit $? processAction "$msg (enable)" "$CMD_SYSTEMCTL enable $pkg" $log || exit $? processAction "$msg (status)" "$CMD_SYSTEMCTL status $pkg" $log || exit $? elif [ -x $CMD_SERVICE ]; then processAction "$msg" "$CMD_SERVICE $pkg restart" $log || exit $? processAction '$msg (status)' "$CMD_SERVICE $pkg status" $log || exit $? else showMessage 'Service (re)start script' showStatus $WARN 'undetected' fi #-- Configure firewall for tftpd # (I did not need to adjust firewall for dhcp) # iptables --verbose --insert INPUT 5 -m state --state NEW --proto udp --dport 67 -j ACCEPT log=/tmp/pxe-iptables.log case $OS_NAME in openSUSE) #-- (openSUSE) msg='Configure Firewall Rules' for svc in 'service:dhcp-server' 'service:tftp' do processAction "Firewall $svc" "/sbin/yast2 firewall services add service=$svc zone=EXT" $log || exit $? done ;; RedHat|CentOS) #-- (CentOS & RH) msg='Firewall rules' showMessage "$msg (iptables)" /sbin/iptables --list --line-numbers >> ${log}.$$ echo '/sbin/iptables --insert INPUT 5 -m state --state NEW --proto udp --dport 69 -j ACCEPT' >> \ ${log}.$$ 2>&1 /sbin/iptables --list --line-numbers | grep -q tftp || \ /sbin/iptables --insert INPUT 5 -m state --state NEW --proto udp --dport 69 -j ACCEPT >> \ ${log}.$$ 2>&1 showStatus 0 "check: ${log}.$$" || exit $? msg='Save firewall rules (iptables)' processAction "$msg" "$CMD_SERVICE iptables save" $log || exit $? ;; Fedora) #-- (Fedora) msg='Firewall rules' showMessage "$msg (iptables)" ( echo '# using iptables' echo '# /sbin/iptables --insert IN_public_allow 1 -m state --state NEW --proto udp --dport 69 -j ACCEPT' /sbin/iptables --list --line-numbers | grep -q tftp || \ /sbin/iptables --insert IN_public_allow 1 -m state --state NEW --proto udp --dport 69 -j ACCEPT ) >> ${log}.$$ 2>&1 showStatus 0 "check: ${log}.$$" || exit $? if [ -x $CMD_FWCMD ] then processAction "$msg (firewall-cmd)" "${CMD_FWCMD} --permanent --add-service=tftp" $log || exit $? fi ## Not needed when firewalld is in use; but harmless [ -f /etc/sysconfig/iptables-config ] && \ sed -i '/IPTABLES_SAVE_ON_RESTART=/ s/no/yes/i' /etc/sysconfig/iptables-config >> \ ${log}.$$ 2>&1 msg='Restart firewalld' processAction "$msg" "$CMD_SYSTEMCTL restart firewalld" $log || exit $? ;; *) showMessage 'Configure Firewall Rules' showStatus -2 'Skipped: assumed not required' ;; esac #-- Prepare the /var/lib/tftpboot/ dir for usage ## (populate it!) ( log=/tmp/pxe-populate-tftpboot.log TFTPBOOTTGT=/var/lib/tftpboot PXEIP=$(getNicIP $NIC) [ -d $TFTPBOOTTGT ] || { echo 'Failed to find tftpboot dir'; exit 1; } cd $TFTPBOOTTGT || exit 1 showMessage 'Populating tftpboot PXE menus' ( cat < $FIL WGETST=$? [ -f $FIL ] && grep -q '' $FIL && \ sed -i "// s==${PXEIP=}=" $FIL [ $WGETST -eq 0 ] ) done >> ${log}.$$ 2>&1 showStatus $? "check: ${log}.$$" || exit $? cd $TFTPBOOTTGT || exit 1 ST=0 showMessage 'Populating tftpboot binaries' ( SLBASE=$(dirname $(find /usr -name pxelinux.0|head -1)) [ -f pxelinux.0 ] || { ln ${SLBASE}/pxelinux.0 || ST=1; } [ -d bin ] || mkdir bin cd bin || ST=1 [ -f menu.c32 ] || { ln ${SLBASE}/menu.c32 || ST=1; } [ -f vesamenu.c32 ] || { ln ${SLBASE}/vesamenu.c32 || ST=1; } [ -f memdisk ] || { ln ${SLBASE}/memdisk || ST=1; } ) >> ${log}.$$ 2>&1 showStatus $ST "check: ${log}.$$" ) #-- Compute Network values from the "UP" NIC ## use them to build a simple dhcpd.conf file. showMessage 'Building dhcpd.conf file' NIC_ADDR=$(getNicIP $NIC) NIC_MASK=$(getNicMask $NIC) NIC_BCST=$(getNicBcst $NIC) NIC_DRTR=$( getDefaultRoute ) declare -a ADDR=( $(echo $NIC_ADDR|sed 's/[.]/ /g') ) declare -a MASK=( $(echo $NIC_MASK|sed 's/[.]/ /g') ) declare -a BCST=( $(echo $NIC_BCST|sed 's/[.]/ /g') ) NIC_NET="$(( ${ADDR[0]} & ${MASK[0]} )).$(( ${ADDR[1]} & ${MASK[1]} ))" NIC_NET="${NIC_NET}.$(( ${ADDR[2]} & ${MASK[2]} ))" NIC_NET="${NIC_NET}.$(( ${ADDR[3]} & ${MASK[3]} ))" NIC_NST="$(( ${ADDR[0]} & ${MASK[0]} )).$(( ${ADDR[1]} & ${MASK[1]} ))" NIC_NST="${NIC_NST}.$(( ${ADDR[2]} & ${MASK[2]} ))" NIC_NST="${NIC_NST}.$(( ( ${ADDR[3]} & ${MASK[3]} ) + 1 ))" NIC_NED="${BCST[0]}.${BCST[1]}.${BCST[2]}.$(( ${BCST[3]} - 1 ))" NIC_RNG="${BCST[0]}.${BCST[1]}.${BCST[2]}.$(( ${BCST[3]} - 15 ))" cat > /tmp/dhcpd.conf < /etc/dhcpd.conf >> ${log}.$$ 2>&1 fi if diff /tmp/dhcpd.conf $DHCPDCONF >> ${log}.$$ 2>&1 then showStatus 0 'check: /tmp/dhcpd.conf - no change, not installed' else if [ $( grep -v '^#' $DHCPDCONF | grep -v '^$' | awk '{print $1}' | wc -l ) -gt 10 ] then showStatus 0 'check: /tmp/dhcpd.conf - existing config not overwritten' showMessage '' echo " ( install manually as needed )" else [ -f /tmp/dhcpd.conf ] && cat /tmp/dhcpd.conf > $DHCPDCONF && \ /bin/rm -f /tmp/dhcpd.conf showStatus $? "check: $DHCPDCONF and /tmp/dhcpd.conf" fi fi #-- Enable DHCPD msg='Enabling DHCP server' log=/tmp/pxe-dhcpd-service.log pkg=isc-dhcp-server case $OS_NAME in RedHat|CentOS) pkg=dhcpd ;; openSUSE) pkg=dhcpd ;; Fedora) pkg=dhcpd ;; Arch) pkg=dhcpd4 ;; esac if [ -x /sbin/yast2 ] then processAction "$msg (intr)" "/sbin/yast2 dhcp-server interface select=$NIC" $log || exit $? processAction "$msg (enab)" '/sbin/yast2 dhcp-server enable' $log || exit $? #-- Always fails even though it works - some kind of bug # processAction "$msg (curr)" "/sbin/yast2 dhcp-server interface current" $log || exit $? # processAction "$msg (stat)" '/sbin/yast2 dhcp-server status' $log || exit $? elif [ -x /sbin/chkconfig ]; then processAction "$msg" "/sbin/chkconfig $pkg on" $log || exit $? elif [ -x $CMD_SYSTEMCTL ]; then processAction "$msg (disable)" "$CMD_SYSTEMCTL disable $pkg" $log || exit $? processAction "$msg (enable)" "$CMD_SYSTEMCTL enable $pkg" $log || exit $? else showMessage "$msg" showStatus 0 'Assumed' || exit $? fi #-- Start/Restart DHCP server msg="Service $pkg" if [ -x $CMD_SYSTEMCTL ] then processAction "$msg (start)" "$CMD_SYSTEMCTL restart $pkg" $log || exit $? processAction "$msg (status)" "$CMD_SYSTEMCTL status $pkg" $log || exit $? elif [ -x $CMD_SERVICE ]; then processAction "$msg" "$CMD_SERVICE $pkg restart" $log || exit $? else showMessage "$msg" showStatus $WARN 'Restart script unknown' fi echo '' echo ' TODO:' echo ' 1) Inspect the dhcpd.conf file and change as needed to' echo ' meet the needs of your local network such as MAC addresses' echo ' 2) Inspect the tftpboot directory!' echo ' 3) Inspect that dhcp, tftp and xinetd (or simular) are enabled' echo ' and running as expected.' echo ' 4) Inspect firewall settings to ensure they "took" when' echo ' when applied by the script; or dieable the firewall.' echo ' In some system the rules are applied but do not get saved' echo ' during the rirewall restart. Command used is found in a' echo ' log file above.' echo ' 5) PXE boot a system and enjoy the results.' echo '' # END