#!/bin/bash
# Attempts to start Proxmox VM that matches MAC address received on WOL message
# This could be dangerous if abused by spamming the interface with many packages
# so I would like to try no more than once per 5 seconds.
# In my case useful with Moonlight client
# Uses tcpdump on default proxmox interface, change the interface if needed.
while true; do
sleep 5
wake_mac=$(tcpdump -c 1 -UlnXi vmbr0 ether proto 0x0842 or udp port 9 2>/dev/null |\
sed -nE 's/^.*20: (ffff|.... ....) (..)(..) (..)(..) (..)(..).*$/\2:\3:\4:\5:\6:\7/p')
echo "Captured magic packet for address: \"${wake_mac}\""
echo -n "Looking for existing VM: "
matches=($(grep -il ${wake_mac} /etc/pve/qemu-server/*))
if [[ ${#matches[*]} -eq 0 ]]; then
echo "${#matches[*]} found"
continue
elif [[ ${#matches[*]} -gt 1 ]]; then
echo "${#matches[*]} found, using first found"
else
echo "${#matches[*]} found"
fi
vm_file=$(basename ${matches[0]})
vm_id=${vm_file%.*}
details=$(qm status ${vm_id} -verbose | egrep "^name|^status")
name=$(echo ${details} | awk '{print $2}')
status=$(echo ${details} | awk '{print $4}')
if [[ "${status}" != "stopped" ]]; then
echo "SKIPPED VM ${vm_id} : ${name} is ${status}"
else
echo "STARTING VM ${vm_id} : ${name} is ${status}"
qm start ${vm_id}
fi
done
Excellent. Your script seems to work reliably. I'll keep watching it. Thank you very much for your efforts.I have something similar that I wrote for my own needs and it works good so far, decided to share it here. Although I use it only for VMs not containers as my primary use is from Moonlight client to wake up a couple of VM gaming machines. One could adapt it easelly to handle LXC too :
Bash:#!/bin/bash # Attempts to start Proxmox VM that matches MAC address received on WOL message # This could be dangerous if abused by spamming the interface with many packages # so I would like to try no more than once per 5 seconds. # In my case useful with Moonlight client # Uses tcpdump on default proxmox interface, change the interface if needed. while true; do sleep 5 wake_mac=$(tcpdump -c 1 -UlnXi vmbr0 ether proto 0x0842 or udp port 9 2>/dev/null |\ sed -nE 's/^.*20: (ffff|.... ....) (..)(..) (..)(..) (..)(..).*$/\2:\3:\4:\5:\6:\7/p') echo "Captured magic packet for address: \"${wake_mac}\"" echo -n "Looking for existing VM: " matches=($(grep -il ${wake_mac} /etc/pve/qemu-server/*)) if [[ ${#matches[*]} -eq 0 ]]; then echo "${#matches[*]} found" continue elif [[ ${#matches[*]} -gt 1 ]]; then echo "${#matches[*]} found, using first found" else echo "${#matches[*]} found" fi vm_file=$(basename ${matches[0]}) vm_id=${vm_file%.*} details=$(qm status ${vm_id} -verbose | egrep "^name|^status") name=$(echo ${details} | awk '{print $2}') status=$(echo ${details} | awk '{print $4}') if [[ "${status}" != "stopped" ]]; then echo "SKIPPED VM ${vm_id} : ${name} is ${status}" else echo "STARTING VM ${vm_id} : ${name} is ${status}" qm start ${vm_id} fi done
Started as a manually executed shell script, it works wonderfully. In crontab via: @reboot /root/wol.sh > /dev/nullI have something similar that I wrote for my own needs and it works good so far, decided to share it here. Although I use it only for VMs not containers as my primary use is from Moonlight client to wake up a couple of VM gaming machines. One could adapt it easelly to handle LXC too :
Bash:#!/bin/bash # Attempts to start Proxmox VM that matches MAC address received on WOL message # This could be dangerous if abused by spamming the interface with many packages # so I would like to try no more than once per 5 seconds. # In my case useful with Moonlight client # Uses tcpdump on default proxmox interface, change the interface if needed. while true; do sleep 5 wake_mac=$(tcpdump -c 1 -UlnXi vmbr0 ether proto 0x0842 or udp port 9 2>/dev/null |\ sed -nE 's/^.*20: (ffff|.... ....) (..)(..) (..)(..) (..)(..).*$/\2:\3:\4:\5:\6:\7/p') echo "Captured magic packet for address: \"${wake_mac}\"" echo -n "Looking for existing VM: " matches=($(grep -il ${wake_mac} /etc/pve/qemu-server/*)) if [[ ${#matches[*]} -eq 0 ]]; then echo "${#matches[*]} found" continue elif [[ ${#matches[*]} -gt 1 ]]; then echo "${#matches[*]} found, using first found" else echo "${#matches[*]} found" fi vm_file=$(basename ${matches[0]}) vm_id=${vm_file%.*} details=$(qm status ${vm_id} -verbose | egrep "^name|^status") name=$(echo ${details} | awk '{print $2}') status=$(echo ${details} | awk '{print $4}') if [[ "${status}" != "stopped" ]]; then echo "SKIPPED VM ${vm_id} : ${name} is ${status}" else echo "STARTING VM ${vm_id} : ${name} is ${status}" qm start ${vm_id} fi done
This was exactly my use case and the solution I was looking for.I have something similar that I wrote for my own needs and it works good so far, decided to share it here. Although I use it only for VMs not containers as my primary use is from Moonlight client to wake up a couple of VM gaming machines. One could adapt it easelly to handle LXC too :
Bash:#!/bin/bash # Attempts to start Proxmox VM that matches MAC address received on WOL message # This could be dangerous if abused by spamming the interface with many packages # so I would like to try no more than once per 5 seconds. # In my case useful with Moonlight client # Uses tcpdump on default proxmox interface, change the interface if needed. while true; do sleep 5 wake_mac=$(tcpdump -c 1 -UlnXi vmbr0 ether proto 0x0842 or udp port 9 2>/dev/null |\ sed -nE 's/^.*20: (ffff|.... ....) (..)(..) (..)(..) (..)(..).*$/\2:\3:\4:\5:\6:\7/p') echo "Captured magic packet for address: \"${wake_mac}\"" echo -n "Looking for existing VM: " matches=($(grep -il ${wake_mac} /etc/pve/qemu-server/*)) if [[ ${#matches[*]} -eq 0 ]]; then echo "${#matches[*]} found" continue elif [[ ${#matches[*]} -gt 1 ]]; then echo "${#matches[*]} found, using first found" else echo "${#matches[*]} found" fi vm_file=$(basename ${matches[0]}) vm_id=${vm_file%.*} details=$(qm status ${vm_id} -verbose | egrep "^name|^status") name=$(echo ${details} | awk '{print $2}') status=$(echo ${details} | awk '{print $4}') if [[ "${status}" != "stopped" ]]; then echo "SKIPPED VM ${vm_id} : ${name} is ${status}" else echo "STARTING VM ${vm_id} : ${name} is ${status}" qm start ${vm_id} fi done
Did you compare system service vs. crontab bash?This was exactly my use case and the solution I was looking for.
I’m not sure what the “right” way to implement it is, but I created a systems service that runs on startup and it seems to work perfectly. Thank you!
I did not, I figured systemd was the way to go, so that's what I went with. Also not sure if it needs to run as root, I based it off of other solutions I found trying to achieve something similar.Did you compare system service vs. crontab bash?
[Unit]
Description=Wake-on-LAN for Proxmox Virtual Environments
After=network.target
[Service]
Type=simple
Restart=always
User=root
ExecStart=/usr/sbin/pve_vm_wol.sh
[Install]
WantedBy=multi-user.target
Hey man, THIS version (that uses tcpdump) is the only working one for me. The other one that relies on "nc" does not exit the loop that reads from it. Yours actually does!!!I have something similar that I wrote for my own needs and it works good so far, decided to share it here. Although I use it only for VMs not containers as my primary use is from Moonlight client to wake up a couple of VM gaming machines. One could adapt it easelly to handle LXC too :
Bash:#!/bin/bash # Attempts to start Proxmox VM that matches MAC address received on WOL message # This could be dangerous if abused by spamming the interface with many packages # so I would like to try no more than once per 5 seconds. # In my case useful with Moonlight client # Uses tcpdump on default proxmox interface, change the interface if needed. while true; do sleep 5 wake_mac=$(tcpdump -c 1 -UlnXi vmbr0 ether proto 0x0842 or udp port 9 2>/dev/null |\ sed -nE 's/^.*20: (ffff|.... ....) (..)(..) (..)(..) (..)(..).*$/\2:\3:\4:\5:\6:\7/p') echo "Captured magic packet for address: \"${wake_mac}\"" echo -n "Looking for existing VM: " matches=($(grep -il ${wake_mac} /etc/pve/qemu-server/*)) if [[ ${#matches[*]} -eq 0 ]]; then echo "${#matches[*]} found" continue elif [[ ${#matches[*]} -gt 1 ]]; then echo "${#matches[*]} found, using first found" else echo "${#matches[*]} found" fi vm_file=$(basename ${matches[0]}) vm_id=${vm_file%.*} details=$(qm status ${vm_id} -verbose | egrep "^name|^status") name=$(echo ${details} | awk '{print $2}') status=$(echo ${details} | awk '{print $4}') if [[ "${status}" != "stopped" ]]; then echo "SKIPPED VM ${vm_id} : ${name} is ${status}" else echo "STARTING VM ${vm_id} : ${name} is ${status}" qm start ${vm_id} fi done
#!/bin/bash
# Attempts to start Proxmox VM or LXC that matches MAC address received on WOL message
# This could be dangerous if abused by spamming the interface with many packages
# so I would like to try no more than once per 5 seconds.
# In my case useful with Moonlight client
# Uses tcpdump on default proxmox interface, change the interface if needed.
while true; do
sleep 5
wake_mac=$(tcpdump -c 1 -UlnXi vmbr1 ether proto 0x0842 or udp port 9 2>/dev/null |\
sed -nE 's/^.*20: (ffff|.... ....) (..)(..) (..)(..) (..)(..).*$/\2:\3:\4:\5:\6:\7/p')
echo "Captured magic packet for address: \"${wake_mac}\""
echo -n "Looking for existing VM: "
matches=($(grep -il ${wake_mac} /etc/pve/qemu-server/*))
if [[ ${#matches[*]} -eq 0 ]]; then
echo "${#matches[*]} found"
echo -n "Looking for existing LXC: "
matches=($(grep -il ${wake_mac} /etc/pve/lxc/*))
if [[ ${#matches[*]} -eq 0 ]]; then
echo "${#matches[*]} found"
continue
elif [[ ${#matches[*]} -gt 1 ]]; then
echo "${#matches[*]} found, using first found"
else
echo "${#matches[*]} found"
fi
vm_file=$(basename ${matches[0]})
vm_id=${vm_file%.*}
details=$(pct status ${vm_id} -verbose | egrep "^name|^status")
name=$(echo ${details} | awk '{print $2}')
status=$(echo ${details} | awk '{print $4}')
if [[ "${status}" != "stopped" ]]; then
echo "SKIPPED CONTAINER ${vm_id} : ${name} is ${status}"
else
echo "STARTING CONTAINER ${vm_id} : ${name} is ${status}"
pct start ${vm_id}
fi
continue
elif [[ ${#matches[*]} -gt 1 ]]; then
echo "${#matches[*]} found, using first found"
else
echo "${#matches[*]} found"
fi
vm_file=$(basename ${matches[0]})
vm_id=${vm_file%.*}
details=$(qm status ${vm_id} -verbose | egrep "^name|^status")
name=$(echo ${details} | awk '{print $2}')
status=$(echo ${details} | awk '{print $4}')
if [[ "${status}" != "stopped" ]]; then
echo "SKIPPED VM ${vm_id} : ${name} is ${status}"
else
echo "STARTING VM ${vm_id} : ${name} is ${status}"
qm start ${vm_id}
fi
done
echo -n "Looking for existing VM: " | systemd-cat -t wol_vm -p info
I keep getting this error: stdbuf: failed to run command ‘xxd’: No such file or directory
Idk if it's because I'm using PVE 8.0.3, but I would like to use this script for my config.