Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: lcm-logger disk quota option #464

Open
judfs opened this issue Jul 13, 2023 · 1 comment
Open

Feature request: lcm-logger disk quota option #464

judfs opened this issue Jul 13, 2023 · 1 comment

Comments

@judfs
Copy link
Contributor

judfs commented Jul 13, 2023

An option to say --disk-quota 50gb and have logger exit if the drive being written to has less than 50gb free would be useful.

Alternatively, if there is an external utility that is generally recommended for this purpose, I think calling it out in --help would be broadly helpful.

@judfs
Copy link
Contributor Author

judfs commented Jul 13, 2023

fwiw, this is the external script I cobbled together for linux:

import os
import sys
import subprocess
from subprocess import PIPE
import threading
import time as pytime

# ---------------------------
# Sec
POOL_INTERVAL = 60
# GB
MIN_FREE_SPACE = int(os.environ.get("MIN_FREE_SPACE", 50))
START_TIME = pytime.time()
# ---------------------------


def hhmmss(sec:float):
    sec = int(sec)
    hours, rem = divmod(sec, 60*60) # Sec / sec_p_hour
    minutes, seconds = divmod(rem, 60)
    return f'{hours:0>2}:{minutes:0>2}:{int(seconds):0>2}'

def elapsed():
    now = pytime.time()
    delta = now - START_TIME
    print(f"Elapsed time: {hhmmss(delta)}", flush=True)


def free_gb():
    # Not bothering to understand
    # https://docs.python.org/3/library/os.html#os.statvfs
    cmd = 'df --output=avail -h /home'.split()
    p = subprocess.run(cmd, stdout=PIPE)
    # ie
    # b'Avail\n 536G\n'
    avail = p.stdout.decode().split('\n')[1].strip()
    if 'G' not in avail:
        print("Failed to parse df")
        return 0
    # print(f'\n\n----------\n{avail.split("G")[0]}')
    return int(avail.split("G")[0])

# ---------------------------


class State():
    # running = True
    abort_event = threading.Event()
    disk_full_event = threading.Event()


def poll_df(state: State):
    debug_counter = 0
    while not state.abort_event.is_set():
        debug_counter += 1
        if free_gb() < MIN_FREE_SPACE:
            # if debug_counter > 10:
            print("Low disk space. Aborting.", flush=True)
            state.abort_event.set()
            state.disk_full_event.set()
            return
        # print("world")
        state.abort_event.wait(POOL_INTERVAL)


def main():
    cmd = sys.argv[1:]
    # cmd = "ping google.com -i 10".split()
    # print("hello")
    state = State()

    t = threading.Thread(target=poll_df, args=[state])

    try:
        t.start()

        p = subprocess.Popen(cmd)
        state.disk_full_event.wait()
        
        p.kill()
    except:
        state.abort_event.set()
        print("\nKeyboardInterrupt -- stopping")
        # t.
    finally:
        elapsed()
        sys.exit(1)

    # print("world")
    pass


try:
    main()
except KeyboardInterrupt:
    print("\nKeyboardInterrupt -- stopping")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant