diff --git a/README.md b/README.md index 98b2937..0c9aefc 100644 --- a/README.md +++ b/README.md @@ -4,80 +4,40 @@ A simple script that turns Windows machines off and on automatically ## Description The script was built to run inside a linux machine for shutdown and wake up Windows machines on the local network. -## Quickstart -This guide covers faster script usage. - -### Installation +## Installation start-stop requires an installation of Python3 or greater. And run on a linux machine with some packages installed -Installing samba package with apt -```bash -$ sudo apt install samba -``` - -Installing wakeonlan package with apt +Installing packages with apt ```bash -$ sudo apt install wakeonlan +$ sudo apt install samba-common wakeonlan python3 ``` -### Windows configuration -* You must have a username with a password -* Open regedit and go to: `\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System` -* create the file DWORD (32 bits): `LocalAccountTokenFilterPolicy` and set its value to `1` -* Configure your motherboard to wake up with magic packages - -### Configuring the script -It is necessary to configure the script before starting to use it. - -Edit the parameters below as per your need -```python -# IP address and username and password of Windows machines -# Username and password syntax: 'username%password' -_address = [ - ('192.168.0.105', 'user1%password1'), - ('192.168.0.106', 'user2%password2') -] +## Windows configuration +* You must have a username with a password. +* Open regedit and go to: `\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System`. +* create the file DWORD (32 bits): `LocalAccountTokenFilterPolicy` and set its value to `1`. +* Configure your motherboard to wake up with magic packages. -# MAC address of Windows machines -_mac = [ - '00:00:00:00:00:00', - '11:11:11:11:11:11' -] +## Configuration file -# Shutdown time -_time_shutdown = [ - '21:00:00', - '22:00:00' -] +Change **start-stop.conf** parameters as needed. -# Monday: 0, Tuesday: 1, Wednesday: 2, Thursday: 3, Friday: 4, Saturday: 5, Sunday: 6 -_week_shutdown = [ - 0, # Monday - 1, # Tuesday - 2, # Wednesday - 3, # Thursday - 4, # Friday - 5, # Saturday - 6, # Sunday -] +You can create more than one machines session. -# Wake up on lan time -_time_wakeonlan = [ - '21:30:00', - '07:30:00' -] +```text +[LOG] +path=/var/log/start-stop.log -# Monday: 0, Tuesday: 1, Wednesday: 2, Thursday: 3, Friday: 4, Saturday: 5, Sunday: 6 -_week_wakeonlan = [ - 0, # Monday - 1, # Tuesday - 2, # Wednesday - 3, # Thursday - 4, # Friday - 5, # Saturday - 6, # Sunday -] +[PC1] +ip=192.168.0.2 +username=user +password=pass +mac=00:00:00:00:00:00 +time_shutdown=21:00:00 +time_wake=07:30:00 +day_shutdown=0,1,2,3,4,5,6 +day_wake=0,1,2,3,4,5,6 ``` -## Observation -wakeonlan doesn't handle machines that are outside the local network very well. \ No newline at end of file +# Observation +Wakeonlan doesn't handle machines that are outside the local network very well. \ No newline at end of file diff --git a/deb/start-stop.deb b/deb/start-stop.deb new file mode 100644 index 0000000..ac745e2 Binary files /dev/null and b/deb/start-stop.deb differ diff --git a/deb/start-stop/DEBIAN/conffiles b/deb/start-stop/DEBIAN/conffiles new file mode 100644 index 0000000..42762bc --- /dev/null +++ b/deb/start-stop/DEBIAN/conffiles @@ -0,0 +1 @@ +/etc/start-stop/start-stop.conf diff --git a/deb/start-stop/DEBIAN/control b/deb/start-stop/DEBIAN/control new file mode 100644 index 0000000..69b4f9b --- /dev/null +++ b/deb/start-stop/DEBIAN/control @@ -0,0 +1,6 @@ +Package: start-stop +Version: 2.0 +Architecture: amd64 +Depends: wakeonlan, samba-common, python3 +Maintainer: https://github.com/felipeucelli +Description: Turn on and shutdown machines on the local network diff --git a/deb/start-stop/DEBIAN/postinst b/deb/start-stop/DEBIAN/postinst new file mode 100644 index 0000000..a10db41 --- /dev/null +++ b/deb/start-stop/DEBIAN/postinst @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e + +systemctl daemon-reload + +service start-stop start + +systemctl enable start-stop.service + +exit 0 diff --git a/deb/start-stop/DEBIAN/postrm b/deb/start-stop/DEBIAN/postrm new file mode 100644 index 0000000..c7c1f60 --- /dev/null +++ b/deb/start-stop/DEBIAN/postrm @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +systemctl daemon-reload + +exit 0 diff --git a/deb/start-stop/DEBIAN/prerm b/deb/start-stop/DEBIAN/prerm new file mode 100644 index 0000000..460fba4 --- /dev/null +++ b/deb/start-stop/DEBIAN/prerm @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +service start-stop stop +systemctl disable start-stop.service + +exit 0 diff --git a/deb/start-stop/etc/start-stop/start-stop.conf b/deb/start-stop/etc/start-stop/start-stop.conf new file mode 100644 index 0000000..a8853e8 --- /dev/null +++ b/deb/start-stop/etc/start-stop/start-stop.conf @@ -0,0 +1,13 @@ +[LOG] +path=/var/log/start-stop.log + +[PC1] +ip=192.168.0.2 +username=user +password=pass +mac=00:00:00:00:00:00 +time_shutdown=21:00:00 +time_wake=07:30:00 +day_shutdown=0,1,2,3,4,5,6 +day_wake=0,1,2,3,4,5,6 + diff --git a/deb/start-stop/etc/start-stop/start-stop.py b/deb/start-stop/etc/start-stop/start-stop.py new file mode 100644 index 0000000..1ae10a7 --- /dev/null +++ b/deb/start-stop/etc/start-stop/start-stop.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +# @autor: Felipe Ucelli +# @github: github.com/felipeucelli + +# Built-in +import logging +import subprocess +import configparser +from time import sleep +from datetime import datetime, date + + +def shutdown(ip: str, username: str, password: str): + """ + Turn off the machines + :return: + """ + try: + result = subprocess.Popen( + ['net', 'rpc', 'shutdown', '-I', ip, '-U', username + '%' + password], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + result_stdout = result.stdout.read().decode() + result_stderr = result.stderr.read().decode() + + if result_stdout != '': + logging.info(f'{result_stdout} - {ip}') + else: + logging.error(f'{result_stderr}') + + except Exception as error: + logging.critical(error) + + +def wakeonlan(mac: str): + """ + Turn on the machines using Wake up on Lan + :param mac: List of macs of machines to be connected + :return: + """ + try: + result = subprocess.Popen( + ['wakeonlan', mac], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + result_stdout = result.stdout.read().decode() + result_stderr = result.stderr.read().decode() + + logging.info(f'{result_stdout}') if result_stdout != '' else logging.error(f'{result_stderr}') + + except Exception as error: + logging.critical(error) + + +def main(section: list): + """ + Checks the time list and calls the corresponding function when it is time + + :return: + """ + while True: + now = str(datetime.now().time()).split('.')[0] + day = str(date(date.today().year, date.today().month, date.today().day).weekday()) + sleep(1) + for items in section: + item = dict(config.items(items)) + if now in item['time_shutdown'] and day in item['day_shutdown']: + shutdown(item['ip'], item['username'], item['password']) + + if now in item['time_wake'] and day in item['day_wake']: + wakeonlan(item['mac']) + + + +config = configparser.RawConfigParser() +config.read('/etc/start-stop/start-stop.conf') + +log_format = '%(asctime)s - %(levelname)s : %(message)s' +log_path = config.get('LOG', 'path') + +logging.basicConfig( + filename=log_path, + level=logging.DEBUG, + format=log_format) + +if __name__ == '__main__': + main(list(config.sections()[1:])) diff --git a/deb/start-stop/etc/systemd/system/start-stop.service b/deb/start-stop/etc/systemd/system/start-stop.service new file mode 100644 index 0000000..0afcd83 --- /dev/null +++ b/deb/start-stop/etc/systemd/system/start-stop.service @@ -0,0 +1,13 @@ +[Unit] +Description="Turn on and shutdown machines on the local network" +After=network.target + +[Service] +Type=simple +ExecStart=/bin/python3 /etc/start-stop/start-stop.py +TimeoutStartSec=0 + +[Install] +WantedBy=default.target + + diff --git a/start-stop.conf b/start-stop.conf new file mode 100644 index 0000000..576299c --- /dev/null +++ b/start-stop.conf @@ -0,0 +1,22 @@ +[LOG] +path=/var/log/start-stop.log + +[PC1] +ip=192.168.0.2 +username=user +password=pass +mac=00:00:00:00:00:00 +time_shutdown=21:00:00 +time_wake=07:30:00 +day_shutdown=0,1,2,3,4,5,6 +day_wake=0,1,2,3,4,5,6 + +[PC2] +ip=192.168.0.3 +username=user +password=pass +mac=00:00:00:00:00:00 +time_shutdown=21:00:00 +time_wake=07:30:00 +day_shutdown=0,1,2,3,4,5,6 +day_wake=0,1,2,3,4,5,6 \ No newline at end of file diff --git a/start-stop.py b/start-stop.py index 11c64e8..475542c 100644 --- a/start-stop.py +++ b/start-stop.py @@ -6,145 +6,84 @@ # Built-in import logging import subprocess +import configparser from time import sleep from datetime import datetime, date -def shutdown(address: list): +def shutdown(ip: str, username: str, password: str): """ Turn off the machines - :param address: List with the IP addresses of the machines :return: """ try: - for i in range(len(address)): - result = subprocess.Popen( - ['net', 'rpc', 'shutdown', '-I', address[i][0], '-U', address[i][1]], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + result = subprocess.Popen( + ['net', 'rpc', 'shutdown', '-I', ip, '-U', username + '%' + password], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result_stdout = result.stdout.read().decode() - result_stderr = result.stderr.read().decode() + result_stdout = result.stdout.read().decode() + result_stderr = result.stderr.read().decode() - if result_stdout != '': - logging.info(f'{result_stdout} - {address[i][0]}') - else: + if result_stdout != '': + logging.info(f'{result_stdout} - {ip}') + else: logging.error(f'{result_stderr}') - except Exception as erro: - logging.critical(erro) + except Exception as error: + logging.critical(error) -def wakeonlan(mac: list): +def wakeonlan(mac: str): """ Turn on the machines using Wake up on Lan :param mac: List of macs of machines to be connected :return: """ try: - for i in range(len(mac)): - result = subprocess.Popen( - ['wakeonlan', mac[i]], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + result = subprocess.Popen( + ['wakeonlan', mac], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result_stdout = result.stdout.read().decode() - result_stderr = result.stderr.read().decode() + result_stdout = result.stdout.read().decode() + result_stderr = result.stderr.read().decode() - logging.info(f'{result_stdout}') if result_stdout != '' else logging.error(f'{result_stderr}') + logging.info(f'{result_stdout}') if result_stdout != '' else logging.error(f'{result_stderr}') - except Exception as erro: - logging.critical(erro) + except Exception as error: + logging.critical(error) -def main(address: list, - mac: list, - time_shutdown: list, - week_shutdown: list, - time_wakeonlan: list, - week_wakeonlan: list - ): +def main(section: list): """ Checks the time list and calls the corresponding function when it is time - :param address: List with the IP addresses of the machines - :param mac: List of macs of machines to be connected - :param time_shutdown: List of shutdown hours - :param week_shutdown: List of days of the week to turn off - :param time_wakeonlan: List with the hours to start the machines - :param week_wakeonlan: List of days of the week to turn on + :return: """ while True: + now = str(datetime.now().time()).split('.')[0] + day = str(date(date.today().year, date.today().month, date.today().day).weekday()) sleep(1) - for time1 in time_shutdown: - now = str(datetime.now().time()).split('.')[0] - week = date(date.today().year, date.today().month, date.today().day).weekday() - if now == time1 and week in week_shutdown: - shutdown(address=address) - for time2 in time_wakeonlan: - now = str(datetime.now().time()).split('.')[0] - week = date(date.today().year, date.today().month, date.today().day).weekday() - if now == time2 and week in week_wakeonlan: - wakeonlan(mac=mac) + print(now) + for items in section: + item = dict(config.items(items)) + if now in item['time_shutdown'] and day in item['day_shutdown']: + shutdown(item['ip'], item['username'], item['password']) + + if now in item['time_wake'] and day in item['day_wake']: + wakeonlan(item['mac']) + +config = configparser.RawConfigParser() +config.read('start-stop.conf') + log_format = '%(asctime)s - %(levelname)s : %(message)s' -log_path = '/var/log/start-stop.log' # Full path to save the log file +log_path = config.get('LOG', 'path') + logging.basicConfig( filename=log_path, level=logging.DEBUG, format=log_format) -# IP address and username and password of Windows machines -# Username and password syntax: 'username%password' -_address = [ - ('192.168.0.105', 'user1%password1'), - ('192.168.0.106', 'user2%password2') -] - -# MAC address of Windows machines -_mac = [ - '00:00:00:00:00:00', - '11:11:11:11:11:11' -] - -# Shutdown time -_time_shutdown = [ - '21:00:00', - '22:00:00' -] - -# Monday: 0, Tuesday: 1, Wednesday: 2, Thursday: 3, Friday: 4, Saturday: 5, Sunday: 6 -_week_shutdown = [ - 0, # Monday - 1, # Tuesday - 2, # Wednesday - 3, # Thursday - 4, # Friday - 5, # Saturday - 6, # Sunday -] - -# Wake up on lan time -_time_wakeonlan = [ - '21:30:00', - '07:30:00' -] - -# Monday: 0, Tuesday: 1, Wednesday: 2, Thursday: 3, Friday: 4, Saturday: 5, Sunday: 6 -_week_wakeonlan = [ - 0, # Monday - 1, # Tuesday - 2, # Wednesday - 3, # Thursday - 4, # Friday - 5, # Saturday - 6, # Sunday -] - if __name__ == '__main__': - main(address=_address, - mac=_mac, - time_shutdown=_time_shutdown, - week_shutdown=_week_shutdown, - time_wakeonlan=_time_wakeonlan, - week_wakeonlan=_week_wakeonlan - ) + main(list(config.sections()[1:]))