#!/bin/bash
# =======================================================
# ============= Ultimate Wake On Lan v1.3 ===============
# =======================================================
# Adds a fully automatic scan/wake mode and more output.
#
# USAGE:
# Make it executable: chmod +x wakeup.sh
# Run with sudo: sudo ./wakeup.sh
# --- Configuration ---
NETWORK="192.168.1.0/24"
KNOWN_HOSTS_FILE="${HOME}/.wol_known_hosts"
# --- Color Definitions ---
RED='\033[0;31m'
L_RED='\033[1;31m'
GREEN='\033[0;32m'
L_GREEN='\033[1;32m'
YELLOW='\033[0;33m'
L_YELLOW='\033[1;33m'
BLUE='\033[0;34m'
L_BLUE='\033[1;34m'
MAGENTA='\033[0;35m'
L_MAGENTA='\033[1;35m'
CYAN='\033[0;36m'
L_CYAN='\033[1;36m'
WHITE='\033[1;37m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# --- Core Functions ---
check_tools() {
local missing_tools=0
for tool in "$@"; do
if ! command -v "$tool" &> /dev/null; then echo -e "${RED}Error: Required command '${BOLD}$tool${RED}' is not installed.${NC}"; missing_tools=1; fi
done
if [ $missing_tools -ne 0 ]; then
echo -e "\n${YELLOW}Please install the missing tools to proceed.${NC}"; echo "On Debian/Ubuntu: ${CYAN}sudo apt-get install nmap wakeonlan${NC}"; echo "On Fedora/CentOS: ${CYAN}sudo dnf install nmap wakeonlan${NC}"; exit 1
fi
}
scan_network() {
local nmap_flags="$1"
echo -e "---------------------------------------------------------"
echo -e "${CYAN}Starting network scan on ${BOLD}${NETWORK}${CYAN} with flags: ${BOLD}${nmap_flags}${NC}"
echo -e "${YELLOW}Displaying nmap output live. This may take a while.${NC}"
echo -e "---------------------------------------------------------"
local nmap_output_file=$(mktemp)
local start_time=$(date +%s)
# Increased verbosity to -vv for more output
nmap -vv ${nmap_flags} "${NETWORK}" | tee "$nmap_output_file"
local end_time=$(date +%s)
local duration=$((end_time - start_time))
echo -e "---------------------------------------------------------"
echo -e "${GREEN}Parsing results...${NC}"
local devices
devices=$(awk -v ip_color="$L_GREEN" -v mac_color="$L_CYAN" -v nc="$NC" \
'/Nmap scan report for/{ip=$5} /MAC Address:/{mac=$3; vendor=substr($0, index($0,$4)); printf "%s%s%s %s%s%s %s\n", ip_color, ip, nc, mac_color, mac, nc, vendor}' "$nmap_output_file")
local device_count
# Use xargs to trim whitespace from wc -l output
device_count=$(echo "$devices" | wc -l | xargs)
echo -e "${L_GREEN}${BOLD}Scan Complete.${NC} Found ${WHITE}${BOLD}${device_count}${NC} devices in ${WHITE}${BOLD}${duration}${NC} seconds."
echo -e "---------------------------------------------------------"
rm "$nmap_output_file"
# Return the found devices for further action
echo "$devices"
}
wake_device() {
local mac=$1
echo -e "\n${MAGENTA}Sending Wake-on-LAN packet to ${L_CYAN}${BOLD}${mac}${MAGENTA}...${NC}"
wakeonlan "${mac}"; echo -e "${GREEN}Packet sent.${NC}"
}
# --- Menu Functions ---
action_menu() {
local devices="$1"
echo -e "${BLUE}${BOLD}--- Scan Results ---${NC}"
echo -e "${WHITE}$(echo -e "$devices" | cat -n)${NC}"
read -p "Save these devices to the known hosts list? (y/N): " save_choice
if [[ "$save_choice" =~ ^[Yy]$ ]]; then
touch "$KNOWN_HOSTS_FILE"
echo -e "$devices" | sed -r 's/\x1b\[[0-9;]*m//g' | while read -r device_line; do
local mac=$(echo "$device_line" | awk '{print $2}'); if ! grep -qF "$mac" "$KNOWN_HOSTS_FILE"; then echo "$device_line" >> "$KNOWN_HOSTS_FILE"; echo -e "${GREEN}Saved:${NC} $device_line"; fi
done
fi
PS3=$(echo -e "\n${YELLOW}Please choose an action: ${NC}")
local action_options=("Wake a Specific Device from Scan" "Wake All Devices from Scan" "Done")
select action in "${action_options[@]}"; do
case $action in
"Wake a Specific Device from Scan")
local device_options; mapfile -t device_options <<< "$devices"; device_options+=("Cancel")
PS3=$(echo -e "${YELLOW}Enter number of device to wake: ${NC}")
select choice in "${device_options[@]}"; do
if [[ "$choice" == "Cancel" ]]; then break; fi; if [[ -n "$choice" ]]; then wake_device "$(echo -e "$choice" | sed -r 's/\x1b\[[0-9;]*m//g' | awk '{print $2}')"; break; else echo -e "${RED}Invalid selection.${NC}"; fi
done; break ;;
"Wake All Devices from Scan") echo -e "$devices" | sed -r 's/\x1b\[[0-9;]*m//g' | awk '{print $2}' | while read -r mac; do wake_device "$mac"; done; break ;;
"Done") break ;;
*) echo -e "${RED}Invalid option $REPLY${NC}" ;;
esac
done
}
timing_menu() {
local profile_flags="$1"
echo -e "${L_BLUE}${BOLD}--- Step 2: Choose Scan Speed ---${NC}"
PS3=$(echo -e "\n${YELLOW}Aggressive (T4) is best for fast networks. Use Polite (T2) if you see errors.${NC}\nSelect a timing template: ")
local timing_options=("Paranoid (T0)" "Sneaky (T1)" "Polite (T2)" "Normal (T3)" "Aggressive (T4)" "Insane (T5)" "Cancel")
select timing_choice in "${timing_options[@]}"; do
local timing_flag=""; case $timing_choice in "Paranoid (T0)") timing_flag="-T0";; "Sneaky (T1)") timing_flag="-T1";; "Polite (T2)") timing_flag="-T2";; "Normal (T3)") timing_flag="-T3";; "Aggressive (T4)") timing_flag="-T4";; "Insane (T5)") timing_flag="-T5";; "Cancel") return;; *) echo -e "${RED}Invalid option $REPLY${NC}"; continue;; esac
local devices; devices=$(scan_network "${profile_flags} ${timing_flag}")
if [ -z "$devices" ]; then echo -e "${YELLOW}No devices with discoverable MAC addresses were found.${NC}"; else action_menu "$devices"; fi
break
done
}
scan_profile_menu() {
echo -e "${L_BLUE}${BOLD}--- Step 1: Choose Scan Profile ---${NC}"
PS3=$(echo -e "\n${YELLOW}Select what you want to find: ${NC}")
local profile_options=("Simple Host List (for WOL)" "Quick Port Scan" "Full TCP Port Scan" "Aggressive Scan (OS, Version)" "Back to Main Menu")
select opt in "${profile_options[@]}"; do
local nmap_params=""; case $opt in "Simple Host List (for WOL)") nmap_params="-sn";; "Quick Port Scan") nmap_params="-F";; "Full TCP Port Scan") nmap_params="-p-";; "Aggressive Scan (OS, Version)") nmap_params="-A";; "Back to Main Menu") return;; *) echo -e "${RED}Invalid option $REPLY${NC}"; continue;; esac
timing_menu "$nmap_params"; break
done
}
automatic_wake_all() {
echo -e "${L_BLUE}${BOLD}--- Automatic Scan & Wake All ---${NC}"
# Use the fastest, most reliable scan for finding WOL-ready hosts on a LAN.
local nmap_params="-sn -T4"
local devices
devices=$(scan_network "$nmap_params")
if [ -z "$devices" ]; then
echo -e "\n${YELLOW}No devices were found to wake up.${NC}"
else
echo -e "\n${GREEN}Waking up all discovered devices...${NC}"
# Extract just the MAC address (2nd column after stripping colors) and wake each one
echo -e "$devices" | sed -r 's/\x1b\[[0-9;]*m//g' | awk '{print $2}' | while read -r mac; do
wake_device "$mac"
done
echo -e "\n${GREEN}${BOLD}All WOL packets have been sent!${NC}"
fi
}
direct_wake_menu() { # (Unchanged)
echo -e "${L_MAGENTA}${BOLD}--- Direct Wake ---${NC}"; read -p "Enter the MAC address to wake: " mac_address
if [[ "$mac_address" =~ ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$ ]]; then wake_device "$mac_address"; else echo -e "${RED}Invalid MAC address format.${NC}"; fi
}
change_network_menu() { # (Unchanged)
echo -e "${L_MAGENTA}${BOLD}--- Change Network Target ---${NC}"; echo -e "Current network target is: ${L_CYAN}${NETWORK}${NC}"
read -p "Enter new network target in CIDR format (e.g., 10.0.0.0/24): " new_network
if [ -n "$new_network" ]; then NETWORK="$new_network"; echo -e "${GREEN}Network target updated to ${BOLD}${NETWORK}${NC} for this session."; else echo -e "${RED}No input provided.${NC}"; fi
}
saved_hosts_menu() { # (Unchanged)
echo -e "${L_MAGENTA}${BOLD}--- Wake from Saved List ---${NC}"
if [[ ! -f "$KNOWN_HOSTS_FILE" || ! -s "$KNOWN_HOSTS_FILE" ]]; then echo -e "${YELLOW}Known hosts file is empty.${NC}"; return; fi
echo -e "${WHITE}Available saved hosts:${NC}"; awk -v ip_color="$L_GREEN" -v mac_color="$L_CYAN" -v nc="$NC" '{printf "%s%s%s %s%s%s %s\n", ip_color, $1, nc, mac_color, $2, nc, substr($0, index($0,$3))}' "$KNOWN_HOSTS_FILE" | cat -n
PS3=$(echo -e "\n${YELLOW}Choose an option for saved hosts: ${NC}"); local saved_options=("Wake a Specific Saved Host" "Wake ALL Saved Hosts" "Delete a Saved Host" "Cancel")
select opt in "${saved_options[@]}"; do
case $opt in
"Wake a Specific Saved Host"|"Delete a Saved Host") local device_options; mapfile -t device_options < "$KNOWN_HOSTS_FILE"; device_options+=("Cancel"); PS3=$(echo -e "${YELLOW}Select a host to ${opt// a Saved Host/}: ${NC}"); select choice in "${device_options[@]}"; do if [[ "$choice" == "Cancel" ]]; then break; fi; if [[ -n "$choice" ]]; then if [[ "$opt" == "Wake a Specific Saved Host" ]]; then wake_device "$(echo "$choice" | awk '{print $2}')"; else grep -vFw "$choice" "$KNOWN_HOSTS_FILE" > "$KNOWN_HOSTS_FILE.tmp" && mv "$KNOWN_HOSTS_FILE.tmp" "$KNOWN_HOSTS_FILE"; echo -e "${GREEN}Deleted entry:${NC} $choice"; fi; break; else echo -e "${RED}Invalid selection.${NC}"; fi; done; break ;;
"Wake ALL Saved Hosts") awk '{print $2}' "$KNOWN_HOSTS_FILE" | while read -r mac; do wake_device "$mac"; done; break ;;
"Cancel") break ;;
*) echo -e "${RED}Invalid option $REPLY${NC}";;
esac
done
}
help_menu() {
echo -e "${L_MAGENTA}${BOLD}--- Help & Information ---${NC}"
echo -e "Welcome to the ${BOLD}Ultimate Wake On Lan${NC} script (v1.3)."
echo -e "\n${BOLD}Menu Options:${NC}"
echo -e " ${L_RED}Automatic Scan & Wake:${NC} The express option. Immediately scans for all devices"
echo -e " on the network and sends a WOL packet to each one."
echo -e " ${L_GREEN}Manual Scan Network:${NC} Provides full control over the scan. You first choose a"
echo -e " Scan Profile (what to look for), then a Timing Template"
echo -e " (how fast to scan)."
echo -e " ${L_CYAN}Saved & Direct Wake:${NC} Wake devices from your saved list or by entering a"
echo -e " MAC address manually."
echo -e "\n${BOLD}Scan Timing (-T0 to -T5):${NC}"
echo -e " If you get ${L_RED}timeout errors${NC}, your network can't keep up. Slow down the scan!"
echo -e " ${L_GREEN}-T4 (Aggressive):${NC} Recommended for fast, modern LANs."
echo -e " ${L_YELLOW}-T3 (Normal):${NC} Nmap's default behavior."
echo -e " ${L_RED}-T2 (Polite):${NC} Slower scan that uses less bandwidth. Try this if T4/T3 fail."
}
main_menu() {
while true; do
echo -e "${L_RED}${BOLD}U${L_YELLOW}l${L_GREEN}t${L_CYAN}i${L_BLUE}m${L_MAGENTA}a${L_RED}t${L_YELLOW}e ${L_GREEN}W${L_CYAN}a${L_BLUE}k${L_MAGENTA}e ${L_RED}O${L_YELLOW}n ${L_GREEN}L${L_CYAN}a${L_BLUE}n${NC} ${WHITE}v1.3${NC}"
echo -e "${BLUE}=======================================================${NC}"
echo -e " Network Target: ${L_CYAN}${BOLD}${NETWORK}${NC}"
echo -e "${BLUE}=======================================================${NC}"
PS3=$(echo -e "\n${WHITE}${BOLD}Select an option: ${NC}")
local options=(
"$(echo -e "${L_RED}🚀${NC} Automatic Scan & Wake All")"
"$(echo -e "${L_GREEN}★${NC} Manual Scan Network")"
"$(echo -e "${L_CYAN}★${NC} Wake from Saved List")"
"$(echo -e "${L_BLUE}★${NC} Wake a MAC Address Directly")"
"$(echo -e "${L_MAGENTA}★${NC} Change Network Target")"
"$(echo -e "${L_YELLOW}★${NC} Help & Information")"
"$(echo -e "${WHITE}★${NC} Exit")"
)
select opt in "${options[@]}"; do
local clean_opt; clean_opt=$(echo "$opt" | sed -r 's/\x1b\[[0-9;]*m//g' | sed -r 's/🚀 |★ //g')
case "$clean_opt" in
"Automatic Scan & Wake All") automatic_wake_all; break ;;
"Manual Scan Network") scan_profile_menu; break ;;
"Wake from Saved List") saved_hosts_menu; break ;;
"Wake a MAC Address Directly") direct_wake_menu; break ;;
"Change Network Target") change_network_menu; break ;;
"Help & Information") help_menu; break ;;
"Exit") echo -e "${GREEN}Exiting. Goodbye!${NC}"; exit 0 ;;
*) echo -e "${RED}Invalid option $REPLY. Please choose a number from the list.${NC}" ;;
esac
done
echo -e "\n${YELLOW}Press any key to return to the main menu...${NC}"
read -n 1 -s -r
clear
done
}
# --- Script Start ---
clear
check_tools "nmap" "wakeonlan"
if [ "$EUID" -ne 0 ]; then echo -e "${RED}${BOLD}Root Access Required${NC}\n${YELLOW}Please run with sudo for best results.${NC}"; exit 1; fi
main_menu