From 40decbd7692d9c08ed25ad3e39b16af084c8be44 Mon Sep 17 00:00:00 2001 From: Schark Date: Tue, 5 Dec 2023 21:47:49 -0800 Subject: Init scripts --- README.md | 35 ++++++++++++++++++++ backup.py | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ commandhelper | 73 ++++++++++++++++++++++++++++++++++++++++ internet-status | 14 ++++++++ process-rss | 27 +++++++++++++++ random-music | 12 +++++++ 6 files changed, 262 insertions(+) create mode 100644 README.md create mode 100644 backup.py create mode 100755 commandhelper create mode 100755 internet-status create mode 100755 process-rss create mode 100755 random-music diff --git a/README.md b/README.md new file mode 100644 index 0000000..11bb5f1 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Scripts + +A collection of various scripts I've created. Below is a list of their function and usage. + +## commandhelper + +Lists out DWM functional shortcuts for my window manager. + +`./commandhelper` + +## internet-status + +Returns 'Online' or 'Offline' depending on the results of a wget call (may move this to a simple ping in the future). + +`./internet-status` + +## process-rss + +INCOMPLETE: automatically feed a blog post HTML file into my RSS file. + +`./process-rss $BLOG_POST.HTML $RSS_FEED.XML` + +## random-music + +Grabs a random list of songs to feed into an mpv playlist. + +TODO: allow directories to be passed in + +`./random-music $NUM_OF_SONGS` + +## backup.py + +Creates file copies on another drive and an external server. + +TODO: switch this to shell diff --git a/backup.py b/backup.py new file mode 100644 index 0000000..e5ab6c0 --- /dev/null +++ b/backup.py @@ -0,0 +1,101 @@ +""" Python script to automate regular backups via external HDD and server upload""" +# TODO: bash instead? >.> +# TODO: Generate and add package list and basic system info to sync + +import re # Regex for str parsing +import subprocess # Executes OS functions +from datetime import datetime # Handles dir_date creation +from pathlib import Path # Handles paths nicer +from typing import List # Handles lists nicer + +# GLOBALS +BACKUP_DIRECTORIES: List[Path] = [Path("/etc/"), Path("/home/schark/"] +BACKUP_DESTINATION: Path = Path("/mnt/backup/") +BACKUP_UUID: Path = Path("e2408718-ac56-4d92-a4e3-4a775b60b347") +UPLOAD_SERVER: str = "root@schark.online" +UPLOAD_DIR: Path = Path("/samurai-backup") +UPLOAD_DESTINATION: Path = Path(f"{UPLOAD_SERVER}:{UPLOAD_DIR}") +LOGFILE: Path = Path(f"/home/schark/BACKUP_{datetime.today().strftime('%Y-%m-%d')}.log") + +IGNORE_LIST: List[Path] = [Path("*cache*"), Path("*Cache*"), Path("*.config/discord*"), Path("*.dbus*"), Path("*.fontconfig*"), Path("*.java*"), Path("*.local*"), Path("*.mozilla*"), Path("*.steam*"), Path("*.thunderbird*"), Path("*.var*"), Path("*/videos/*")] + +def _logger(msg: str): + print(f"\n[Backup] {msg}") + with open(LOGFILE, 'a+') as file: + file.write(f"\n[Backup] {msg}") + +_logger("Starting logging service...") + +# ensure /mnt/backup is mounted +_logger(f"Checking that {BACKUP_DESTINATION} is mounted...") +try: + subprocess.run(['findmnt', '-rn', '-S', BACKUP_UUID, BACKUP_DESTINATION], check=True) +except subprocess.CalledProcessError: + _logger(f"{BACKUP_DESTINATION} is not mounted. Attempting to mount...") + subprocess.run(['mount', f'UUID={BACKUP_UUID}', BACKUP_DESTINATION]) + +# check storage use of BACKUP_DESTINATION +_logger(f"Checking disk usage of {BACKUP_DESTINATION}...") +output = subprocess.run(['df', BACKUP_DESTINATION, '--output=pcent'], capture_output=True, text=True) +percent = int(re.findall(r'\d+', output.stdout.strip().split('\n')[1])[0]) +if percent >= 90: + _logger(f"Disk usage >90%! Cleaning oldest backup...") + output = subprocess.run(['ls', BACKUP_DESTINATION], capture_output=True, text=True) + oldest = Path(BACKUP_DESTINATION / output.stdout.strip().split('\n')[0]) + subprocess.run(['rm', '-rf', oldest]) + _logger(f"{output} has been deleted from the system.") + +# rsync /etc/* and /home/schark/* to /mnt/backup/{date} +_logger(f"Syncing the following directories: {BACKUP_DIRECTORIES}") +date_dir = Path(BACKUP_DESTINATION / datetime.today().strftime('%Y-%m-%d')) +with open("/home/schark/ignore-list", "w+") as file: + for path in IGNORE_LIST: + file.write(f"{path}\n") +try: + _logger(f"Syncing with drive {date_dir}...") + for path in BACKUP_DIRECTORIES: + subprocess.run(['rsync', '-aH', '--progress', '--exclude-from=/home/schark/ignore-list', path, date_dir], text=True) +except subprocess.CalledProcessError: + raise Exception(f"Error in syncing!") + +# change ownership and umount +_logger(f'Changing ownership on drive...') +subprocess.run(['chown', 'schark', '-R', date_dir]) +subprocess.run(['chgrp', 'schark', '-R', date_dir]) +_logger(f'Unmounting drive...') +subprocess.run(['umount', BACKUP_DESTINATION]) + +# rsync /etc/* and /home/schark/* to root@schark.online:/samurai-backup/{$DATE} +date_dir = Path(UPLOAD_DESTINATION / datetime.today().strftime('%Y-%m-%d')) +try: + _logger(f"Uploading to the server {date_dir}...") + for path in BACKUP_DIRECTORIES: + # NOTE: It is important we run this as root, as we have a special ssh key configured to complete + # this command without need for an additional password entry + subprocess.run(['rsync', '-aH', '--progress', '--exclude-from=/home/schark/ignore-list', path, date_dir], text=True) +except subprocess.CalledProcessError: + raise Exception(f"Error in uploading!") + +# delete old backup from root@schark.online:/samurai-backup +def _run_ssh_command(cmd): + try: + return subprocess.run(['ssh', UPLOAD_SERVER, cmd], capture_output=True, text=True, check=True) + except: + raise Exception(f"Failed ssh command [{cmd}]") + +uploaded_backups = _run_ssh_command(f'ls {UPLOAD_DIR}') +parse_backups = uploaded_backups.stdout.strip().split('\n') +if len(parse_backups) > 1: + old_backup = Path(UPLOAD_DIR / parse_backups[0]) + _logger(f'Deleting old backup {old_backup}') + _run_ssh_command(f'rm -rf {old_backup}') + +# clean up uneeded files +_logger(f'Cleaning up ignore-list...') +subprocess.run(['rm', '/home/schark/ignore-list']) + +_logger('Backup successful!') +_logger('Awaiting manual termination...\n') +while True: + continue + diff --git a/commandhelper b/commandhelper new file mode 100755 index 0000000..17cd553 --- /dev/null +++ b/commandhelper @@ -0,0 +1,73 @@ +#!/bin/bash + +# Clear the screen +clear + +# Start a subshell for all echos to be piped to less +( + + # HEADER + width=$(tput cols) + first_command="Schark's DWM Config" + second_command="==========================" + text_length=${#first_command} + text2_length=${#second_command} + padding=$(( (width - text_length) / 2 )) + padding2=$(( (width - text2_length) / 2 )) + printf "%${padding}s%s\n" "" "$first_command" + printf "%${padding2}s%s\n" "" "$second_command" + echo "" + echo -e "Here's a shortlist of the (sometimes convoluted) keybinds and shortcuts for my DWM config. Includes sections regarding window navigation and management, executing programs, list of preferred installations, and performing system actions all from the keyboard. This is NOT an automatically populated list, if any discrepancies are found please check the dwm/config.h file containing the up-to-date shortcuts and update acordingly. This file is usuallyi stored in /home/schark/program-files/suckless/dwm/." + echo "" + echo -e "Quick note on keybind syntax- a keybind written as \e[1m\e[0m indicates that the ALT key must be pressed at the same time as either J or K for the listed effects to take place." + echo "" + echo -e "To close this window at any time press \e[1m\e[0m, or use the \e[1m\e[0m keybind." + echo "" + echo "" + + # NAVIGATION + nav_header="[Navigation & Management]" + text_length=${#nav_header} + padding=$(( (width - text_length) / 2 )) + printf "%${padding}s%s\n" "" "$nav_header" + echo "" + echo -e "\e[1m\e[0m - Change the focus between the different windows on a screen depending on level of priority (typically left->right, up->down). \e[1mJ\e[0m will move up the priority list, while \e[1mK\e[0m will move down the priority list. You can identify the focused window based on the border highlights of each window." + echo "" + echo -e "\e[1m\e[0m - Switch between different monitors left or right, with the capability of looping around as well (i.e, switching left on the leftmost monitor will move you to the rightmost monitor). You can indentify the current monitor based on the highlighted title bar on the bottom of the screen." + echo "" + echo -e "\e[1m\e[0m - Move the highlighted, focused window onto the screen of the left/right monitor." + echo "" + echo -e "\e[1m\e[0m - Change to the desired screen tab of that particular monitor. Each monitor should have 9 unique screen tabs that may hold their own windows. Selecting the \e[1m0\e[0m tab will show all windows across all screen tabs of that monitor." + echo "" + echo -e "\e[1m\e[0m - Move the highlighted, focused window onto the #'d screen tab of the current monitor." + echo "" + echo -e "\e[1m\e[0m - Terminate and close the focused window." + echo "" + echo -e "\e[1m\e[0m - Zooms onto the current highlighted window, increasing its priority to #1 of that screen's list." + echo "" + echo -e "\e[1m\e[0m - Toggle the ability for a window to be classified as 'floating', and therefore residing atop the remaining windows on the screen. Great for temporary visibility, but leads to usability problems with accessing programs under it." + echo "" + echo -e "\e[1m\e[0m - Sets the monitor window layout to [T]iling. This is the default configuration that will result in automatic window sizing/placement." + echo "" + echo -e "\e[1m\e[0m - Sets the monitor window layout to '[W]indows.' Similar to the Microsoft operating system, windows will float and be uniquely sized. " + echo "" + echo -e "\e[1m\e[0m - For windows sharing a screen, adjust where the divide in priority lies in visibility, either left/right." + echo "" + echo -e "\e[1m\e[0m - Adjust the location of a window based on the X-axis, either left/right." + echo "" + echo -e "\e[1m\e[0m - Adjust the location of a window based on the Y-axis, either down/up." + + # Calculate the number of blank lines needed to push the exit prompt to the bottom + # Subtract the number of printed lines from the total terminal height + num_lines=$(tput lines) # Get the total number of lines in the terminal + num_commands=2 # Replace with the actual number of echo commands above + let "padding = num_lines - num_commands - 3" # 3 is for extra spacing and the exit prompt + + # Print the necessary number of blank lines + for ((i=0; i < padding; i++)); do + echo "" + done + + # Prompt for exiting + echo -e "\nPress 'q' to exit the list." +) | less -R diff --git a/internet-status b/internet-status new file mode 100755 index 0000000..e562c23 --- /dev/null +++ b/internet-status @@ -0,0 +1,14 @@ +#!/bin/bash + +wget -q --spider https://gentoo.org/ + +if [ $? -eq 0 ]; then + echo "Online" +else + # Backup + wget -q --spider https://google.com/ + if [ $? -eq 0 ]; then + echo "Online" + fi + echo "Offline" +fi diff --git a/process-rss b/process-rss new file mode 100755 index 0000000..4044fe9 --- /dev/null +++ b/process-rss @@ -0,0 +1,27 @@ +#!/bin/bash + +# Check if a file was provided +if [ "$#" -ne 1 ]; then + echo "Usage: $0 [file]" + exit 1 +fi + +# File to be processed +FILE="$1" + +# Check if the file exists +if [ ! -f "$FILE" ]; then + echo "Error: File not found." + exit 1 +fi + +# Create a backup of the original file +cp "$FILE" "$FILE.bak" + +# Replace special characters within tags using sed +sed -i '/^/,/<\/description>/ s/&/\&/g; s//\>/g; s/"/\"/g; s/'"'"'/\'/g' "$FILE" + +echo "Processing complete. Original file backed up as $FILE.bak" + + + diff --git a/random-music b/random-music new file mode 100755 index 0000000..f06ee8c --- /dev/null +++ b/random-music @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ -z "$1" ]; then + echo "No song amount provided. Defaulting to 10." + arg=10 +else + arg=$1 +fi + +find /mnt/music/ -type f -name "*.*" | shuf -n $arg | mpv --playlist=- --no-audio-display + +exit 0 -- cgit v1.2.3-18-g5258