From 984141e9e2a1319c960df7114f3de872b40291ad Mon Sep 17 00:00:00 2001 From: Farley Date: Thu, 27 May 2021 18:53:20 +1200 Subject: [PATCH] adding windows support --- README.md | 4 ++-- run.py | 14 +++++++++----- tasks-windows.yml | 11 +++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 tasks-windows.yml diff --git a/README.md b/README.md index c052600..4cdf563 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The simplicity of this code also helps promote its support, usage, and adaptatio # Usage (Installation) -To get started simply install the requirements with `pip install pyyaml` or `pip install -r requirements.txt` and then `python3 run.py` or `./run.py`. It should immediately start up and run on Linux/Mac. On Windows you will need a different config file (todo, add an example for windows). +To get started simply install the requirements with `pip install pyyaml` or `pip install -r requirements.txt` and then `python3 run.py` or `./run.py`. It should immediately start up and run on Linux/Mac. On Windows you will need an slightly different config file, basically just use Windows-specific paths for chdir. See `tasks-windows.yml`. Also on Windows CTRL-C doesn't always kill the entire engine and all children. You may need to force-kill the process from the task manager, or simply close the window if you ran it in an Windows Command Prompt/shell. To begin configuring the tasks you wish to run, please edit the `tasks.yml` file and add the commands you wish to run. The file is well documented and self explanatory. Put in the tasks you wish to add, and re-run `run.py` and watch it work. @@ -84,7 +84,6 @@ To this above Docker image you will install the threaded engine, then add your c * Make init script(s) for some popular Linux distributions * Package this and submit it to package repositories (Ubuntu/Debian/CentOS) * Alternatively, package and distribute this via pip -* Do some/more Windows testing, add documentation and examples for Windows. It _should_ work but the author is mainly an OS-X/Linux guy. * Write some tests for each of the various features to be sure it works and continues to work as intended * Make all logs pre-thread have a forced prefix? Would need to buffer output to accomplish this, and it might break some output data formats especially multi-line ones (eg: JSON, or a stacktrace) * Others / Profit ??? @@ -97,6 +96,7 @@ Note: With any of these above, consider the goal of this codebase is to stay sim * Documented and cleaned up the codebase, added this awesome readme * Integrated the max_runtime feature directly into the codebase instead of being an (annoying) helper script * Making a few variables configurable via env vars making it easier to Dockerize in the future +* Do some/more Windows testing, add documentation and examples for Windows. # History diff --git a/run.py b/run.py index 286f07d..527528e 100755 --- a/run.py +++ b/run.py @@ -1,7 +1,10 @@ #!/usr/bin/env python3 from __future__ import print_function from subprocess import Popen, TimeoutExpired +from pathlib import Path import threading +import platform +import tempfile import datetime import signal import time @@ -20,11 +23,12 @@ def readEnvOrDefault(envname, default=False): return default # Tmpdir, this MUST end in / -tmpdir = readEnvOrDefault('TMPDIR', '/tmp/') +system_tempdir = Path("/tmp" if platform.system() == "Darwin" else tempfile.gettempdir()) +tmpdir = readEnvOrDefault('TMPDIR', system_tempdir) # To prevent flooding, sleep this amount between launching threads thread_launch_interval = int(readEnvOrDefault('THREADLAUNCHINTERVAL', '1')) # Config file path, defining our tasks to run, default to cwd tasks.yml file -configpath = readEnvOrDefault('CONFIGPATH', './tasks.yml') +configpath = readEnvOrDefault('CONFIGPATH', 'tasks.yml') # Open our configuration file to load our job configuration try: with open(configpath, 'r') as stream: @@ -34,7 +38,7 @@ def readEnvOrDefault(envname, default=False): jobs = yaml.load(stream) # This is a fallback to using an older pyyaml without the security patch except: print("Fatal error: Unable to read or parse {}".format(configpath)) - raise + raise ################### @@ -70,7 +74,7 @@ def worker(label, command, interval, start=None, end=None, chdir=None, max_runti """thread worker function""" print('{}: Worker started for in interval {}'.format(label, interval)) tmpfile_path = "{}{}.lastrun".format(tmpdir,label) - + if chdir is not None: print('{}: Worker chdir {}'.format(label, chdir)) os.chdir(chdir) @@ -162,6 +166,6 @@ def worker(label, command, interval, start=None, end=None, chdir=None, max_runti ) threads.append(t) t.start() - + # To prevent flooding of our system, sleep 1 second between new thread creations, just incase time.sleep(thread_launch_interval) diff --git a/tasks-windows.yml b/tasks-windows.yml new file mode 100644 index 0000000..10463c7 --- /dev/null +++ b/tasks-windows.yml @@ -0,0 +1,11 @@ +# Simple windows-specific examples +test-1: + command: echo "test-1 run" + interval: 6 # 10 seconds + max_runtime: 3 # 5 seconds + +# This one has no max runtime, runs forever (until child script exits), simplest example +chdir-test: + chdir: C:\Users + command: echo "chdir test ok" + interval: 3600 # 1 hour