#!/usr/bin/env bash ############# # Variables # ############# # Define formatting variables fb="$(tput bold)" ; readonly fb fr="$(tput sgr0)" ; readonly fr # Define name regular expression name_regex='[^a-zA-Z0-9]' ; readonly name_regex script_editor="" ; readonly script_editor # Script editor ############# # Functions # ############# display_usage() { local help_msg # Define local variable help_msg="Usage: '${0}' Purpose: Create new systemd timer. Variables to set: script_editor Program to use for editing files. By default, the script will respect your environment's ${fb}EDITOR${fr} value. If this value is not configured, you can set ${fb}script_editor${fr} to your editor of choice." echo "${help_msg}" } # Parse arguments parse_args() { local parsed_args inv_ents parsed_args="$(getopt \ -n "${0##*/}" \ -o h \ --long help \ -- "${@}")" # Check for invalid entries inv_ents="${?}" ; readonly inv_ents if [[ "${inv_ents}" -ne 0 ]]; then echo '' display_usage exit 1 fi # Set positional parameters using parsed argument string eval set -- "${parsed_args}" # Evaluate options while true; do case "${1}" in '-h' | '--help') display_usage exit 0 ;; '--') ## End of options shift break ;; esac done } # Run initialization checks run_init_cks() { local err_msg # Override EDITOR with script_editor if [[ "${script_editor}" ]]; then EDITOR="${script_editor}" fi # Verify that an editor is set if ! [[ "${EDITOR}" || "${script_editor}" ]]; then # Prompt user to set required variable and exit err_msg="\nSet either ${fb}EDITOR${fr} or ${fb}script_editor${fr} " err_msg+='before running the script again.' echo -e "${err_msg}" 1>&2 exit 1 fi } # Sanitize name clean_name() { local cleaned # Replace most non-alphanumeric characters with underscores cleaned="${1//${name_regex}/_}" # Squeeze underscores and lowercase name cleaned="$(echo -n "${cleaned}" | tr -s '_' | tr '[:upper:]' '[:lower:]')" echo "${cleaned}" } # .timer unit creation function timer_matter() { { echo '[Unit]' echo -e "Description=${timer_description}\\n" echo '[Timer]' echo "${timer_directive}" echo -e 'Persistent=true\n' echo '[Install]' echo 'WantedBy=timers.target' } > "${HOME}/.config/systemd/user/${unit_name}.timer" } # .service unit creation function service_matter() { { echo '[Unit]' echo -e "Description=${service_description}\\n" echo '[Service]' echo "ExecStart=${service_command}" } > "${HOME}/.config/systemd/user/${unit_name}.service" } # Function to pause script pause() { echo '' read -n 1 -rs -p 'Press any key to continue...' echo '' } # Define starting point for execution of the program main() { parse_args "${@}" run_init_cks # Create systemd user unit directory, and parent directories, # if they do not exist if ! "${HOME}/.config/systemd/user" > '/dev/null' 2>&1; then mkdir -p "${HOME}/.config/systemd/user" fi # Output systemd directives reference sysd_ref='\nsystemd Directives Reference\nhttps://www.freedesktop.org/' sysd_ref+='software/systemd/man/systemd.directives.html' echo -e "${sysd_ref}" # Get unit name echo '' read -p 'Enter unit name: ' -r unit_name unit_name="$(clean_name "${unit_name}")" # Sanitize input # Gather .timer unit description read -p 'Enter .timer description: ' -r timer_description timer_description="${timer_description//[^a-zA-Z0-9 ,]/}" # Sanitize input # Gather .timer unit directive read -p 'Enter .timer directive: ' -r timer_directive timer_directive="${timer_directive//[^a-zA-Z0-9 =]/}" # Sanitize input # Gather .service unit description read -p 'Enter .service description: ' -r service_description # Sanitize input service_description="${service_description//[^a-zA-Z0-9 ,]/}" # Gather .service unit command read -p 'Enter .service command: ' -r service_command timer_matter # Create .timer unit service_matter # Create .service unit while true; do # Present option to open units in editor echo '' read -p 'Open units in editor? (y or n): ' -r edit if [[ "${edit}" == 'y' || "${edit}" == 'n' ]]; then break elif [[ "${edit}" == 'q' ]]; then exit 0 else err_msg='\nInvalid input. Try again or enter q to quit.' echo -e "${err_msg}" 1>&2 fi done # Open units in editor if [[ "${edit}" == 'y' ]]; then "${EDITOR}" "${HOME}/.config/systemd/user/${unit_name}.timer" \ "${HOME}/.config/systemd/user/${unit_name}.service" pause fi # Enable and start units systemctl --user enable --now "${unit_name}.timer" # Check units' status systemctl --user status "${unit_name}.timer" "${unit_name}.service" } ########### # Program # ########### main "${@}" # Start program exit 0 # Exit script with successful exit status