top | item 39759809

(no title)

muxator | 1 year ago

No big deal, but instead of running "wakeonlan" as a subprocess:

    import subprocess
    [...]
    result = subprocess.run(["wakeonlan", "MY:MA:CA:DD:RE:SS"], capture_output=True)

The magic packet could be built and broadcast in pure python, without introducing a dependency on an external binary.

For example, one could take inspiration from the code at https://github.com/remcohaszing/pywakeonlan/blob/main/wakeon...

discuss

order

iam-TJ|1 year ago

I wrote a pure bash shell version for use on my IPv6-only networks. I initially wanted to make pure POSIX sh but the ease of being able to use ${param,,} and more importantly /dev/udp/$IP/$PORT makes bash more suitable for the use-case.

  #!/usr/bin/env bash

  config_sys="${config_sys:-/etc/wol}"
  config_user="${config_user:=$HOME/.config/wol}"
  PORT="${PORT:-9999}"

  cat <<EOF
  WoL Wake-On-LAN Magic Packet transmitter
  Copyright 2023 Tj <hacker@iam.tj>
  Licensed on the terms of the GNU General Public Licence version 3.

  EOF

  ls() {
        shopt -s nullglob
        for f in $@; do
                printf "%s\n" "${f##*/}"
        done
  }

  if [ -z "$1" ]; then
        cat <<-EOF
        Please specify the hostname. Currently defined:
        System ($config_sys/): $(ls "$config_sys/*" 2>/dev/null)
        User ($config_user/):  $(ls "$config_user/*" 2>/dev/null)

        Config files should be named for the target host
        Content is shell variable definitions
        Required: IP= and MAC=
        Optional: PORT= (default is ${PORT})
        E.g:
        MAC="60:45:cb:9f:42:fb"
        IP="fddc:7e00:e001:ee80::2"
        EOF
        exit 1
  fi

  for conf in "$config_sys" "$config_user"; do
        if [[ -r "$conf/$1" ]]; then
                . "$conf/$1"
                # don't break; allow user override
        fi
  done

  if [[ -z "$IP" ]] || [[ -z "$MAC" ]]; then
        >&2 printf "Error: required configuration missing IP='%s' MAC='%s'\n" "$IP" "$MAC"
        exit 2
  fi

  target="/dev/udp/$IP/$PORT"

  hex2char() # $1 = 2 hex digits
  {
        case "${#1},${1,,}" in
                (2,*[!0-9a-f]*) return 2 ;;
                (2,*) printf '%b' "\x$1" ;;
                (*) return 1 ;;
        esac
  }

  make_payload() # $1 = Ethernet MAC address with ":" separators
  {
        IFS=":" read -r -a mac < <(echo "$1")
        for h in "${mac[@]}"; do
                magic="$magic$(hex2char "$h")"
        done
        payload=""
        ff="$(hex2char "ff")"
        for ((i=0; i < 6; i++)); do
                payload="${payload}${ff}"
        done
        for ((i=0; i < 16; i++)); do
                payload="${payload}${magic}"
        done

  }

  printf "Sending magic packet to %s (%s port %s [MAC %s])\n" "$1" "$IP" "$PORT" "$MAC"
  make_payload "$MAC"
  printf "%s" "$payload" > "$target" || printf "error: failed to send (error %s)\n" "$?"

tekknolagi|1 year ago

I am very lazy :)

tekknolagi|1 year ago

(Though, to be clear, I do like the idea of doing it purely in Python!)