diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0f3b1aa --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "lib/krakenx"] + path = lib/krakenx + url = https://github.com/KsenijaS/krakenx.git +[submodule "lib/bright"] + path = lib/bright + url = https://github.com/src-run/bash-bright-library.git +[submodule "lib/bright-library"] + path = lib/bright-library + url = https://github.com/src-run/bash-bright-library.git +[submodule "lib/raspberry-scripts-bash"] + path = lib/raspberry-scripts-bash + url = git@github.com:robfrawley/raspberry-scripts-bash.git diff --git a/bin b/bin new file mode 120000 index 0000000..e455e73 --- /dev/null +++ b/bin @@ -0,0 +1 @@ +bin-enabled \ No newline at end of file diff --git a/bin-available/.disk-op-sizes-monitor.bash.swp b/bin-available/.disk-op-sizes-monitor.bash.swp new file mode 100644 index 0000000..4d3c7fa Binary files /dev/null and b/bin-available/.disk-op-sizes-monitor.bash.swp differ diff --git a/bin-available/afc.bash b/bin-available/afc.bash new file mode 100755 index 0000000..200b1ff --- /dev/null +++ b/bin-available/afc.bash @@ -0,0 +1,600 @@ +#!/bin/bash + +## +## This file is part of the `src-run/user-scripts-server` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +# +# resolve the script name +# +function get_script_name { + basename "${BASH_SOURCE}" +} + +# +# exit script with optional message +# +function do_exit { + local exit_code="${1:-255}" + local exit_desc="${2:-}" + + if [[ ! -z "${exit_desc}" ]]; then + write_normal_line "${exit_desc}" + fi + + exit ${exit_code} +} + +# +# output new line +# +function write_newline { + printf '\n' +} + +# +# output (write) text using printf notation +# +function write_normal_text { + local format="${1}" + shift + + printf "${format}" "${@}" +} + +# +# output (write) styled text using bright library and printf notation +# +function write_styled_text { + _out "${@}" +} + +# +# output (write) line of text using printf notation +# +function write_normal_line { + local format="${1}" + shift + + write_normal_text "${format}" "${@}" + write_newline +} + +# +# output (write) styled text using bright library and printf notation +# +function write_styled_line { + _out 'ctl:use-nl' 'ctl:use-interpret' 'ctl:auto-reset' "${@}" +} + +# +# output error message to stderr +# +function write_error { + local header="${1}" + shift + local format="${1}" + shift + local error + + error="$(printf "${format}" "${@}")" + + write_styled_text " ERROR: ${header} " \ + 'fg:red bg:black style:bold style:reverse' >&2 + write_styled_text " ${error}" \ + 'fg:red style:bold' >&2 + write_newline +} + +# +# output error message to stderr +# +function write_critical { + write_error "${@}" + + do_exit 255 +} + +function write_usage_header { + local header="${1}" + + write_styled_line "${header^^}" 'style:bold' +} + +function write_usage_action { + local action_name="${1}" + local action_long="${2}" + local action_desc="${3}" + + write_normal_text " ${action_name:0:1} $(printf '%-16s' "${action_long}")" + write_styled_line "${action_desc}" 'style:dim' +} + +function write_usage_arg { + local arg_name="${1}" + shift + local arg_long="${1}" + shift + local arg_type="${1}" + local arg_type_optional=0 + shift + local num_desc=1 + local arg_long_typed="${arg_long}" + + if [[ "${arg_type:0:1}" == "!" ]]; then + arg_type_optional=1 + arg_type="${arg_type:1}" + fi + + if \ + [[ ! -z "${arg_type}" ]] && \ + [[ "${arg_type}" != "null" ]]; \ + then + if [[ ${arg_type_optional} -eq 1 ]]; then + arg_long_typed="${arg_long}[=${arg_type^^}]" + else + arg_long_typed="${arg_long}=${arg_type^^}" + fi + fi + + write_normal_text " -${arg_name:0:1} --$(printf '%-14s' "${arg_long_typed}")" + + for line in "${@}"; do + if [[ ${num_desc} -gt 1 ]]; then + printf ' ' + fi + + write_styled_line "${line}" 'style:dim' + num_desc=$((${num_desc} + 1)) + done +} + +function write_usage_desc { + for line in "${@}"; do + write_styled_line " ${line}" 'style:dim' + done +} + +# +# output script usage information +# +function write_usage { + write_newline + + write_usage_header 'Description' + write_usage_desc \ + 'This script toggles the attached/detached state of the internal' \ + 'keyboard registered to the x environment. This effectively allows '\ + 'you to turn a laptop keyboard on and off, which can be useful '\ + 'when using an external keyboard.' + + write_newline + write_usage_header 'Usage' + write_normal_line ' ./%s ARGUMENTS [ACTION CONTEXT]' "$(get_script_name)" + + write_newline + write_usage_header 'Actions' + write_usage_action 's' 'status' \ + 'Display the active (current) state of the internal keyboard.' + write_usage_action 'a' 'attach' \ + 'Enable (attach) the internal keyboard to the x environment.' + write_usage_action 'd' 'detach' \ + 'Disable (detach) the internal keyboard from the x environment.' + write_usage_action 'l' 'list' \ + 'Output a list of all xinput devices with their respective IDs.' + + write_newline + write_usage_header 'Contexts' + write_usage_action 'k' 'keyboard' \ + 'Display the active (current) state of the internal keyboard.' + write_usage_action 't' 'touch-pad' \ + 'Enable (attach) the internal touch pad to the x environment.' + write_usage_action 'p' 'track-point' \ + 'Disable (detach) the internal track point from the x environment.' + + write_newline + write_usage_header 'Arguments' + write_usage_arg 'k' 'keyboard-slave-id' 'id' \ + 'Specify the xinput slave keyboard device ID. The auto-detected ID'\ + "of \"$(get_xinput_keyboard_slave_id)\" will be used otherwise." + write_usage_arg 'K' 'keyboard-master-id' 'id' \ + 'Specify the xinput master keyboard device ID. The auto-detected ID'\ + "of \"$(get_xinput_keyboard_master_id)\" will be used otherwise." + write_usage_arg 't' 'touch-pad-slave-id' 'id' \ + 'Specify the xinput slave touch pad device ID. The auto-detected ID'\ + "of \"$(get_xinput_touch_pad_slave_id)\" will be used otherwise." + write_usage_arg 'T' 'touch-pad-master-id' 'id' \ + 'Specify the xinput master touch pad device ID. The auto-detected ID'\ + "of \"$(get_xinput_track_touch_pad_master_id)\" will be used otherwise." + write_usage_arg 'p' 'track-point-slave-id' 'id' \ + 'Specify the xinput slave track point device ID. The auto-detected ID'\ + "of \"$(get_xinput_track_point_slave_id)\" will be used otherwise." + write_usage_arg 'P' 'track-point-master-id' 'id' \ + 'Specify the xinput master track point device ID. The auto-detected'\ + "ID of \"$(get_xinput_track_touch_pad_master_id)\" will be used otherwise." + write_usage_arg 'x' 'test' '!time' \ + 'Perform the requested changes in test mode where: they are applied,'\ + 'we wait for the specified time, and then changes are rolled back.' + write_usage_arg 'h' 'help' 'null' \ + 'Display the help information for this script (what you are reading).' + write_usage_arg 'v' 'version' 'null' \ + 'Display the version information for this script.' + write_newline +} + +# +# resolve the xinput device if of the requested device name +# +function get_xinput_device_id { + local name="${1}" + + xinput list 2> /dev/null | \ + grep "${name}" 2> /dev/null | \ + cut -f2 2> /dev/null | \ + cut -d'=' -f2 2> /dev/null +} + +# +# resolve the xinput device id of the keyboard +# +function get_xinput_track_point_slave_id { + get_xinput_device_id 'TPPS/2 IBM TrackPoint' +} + +# +# resolve the xinput device id of the keyboard +# +function get_xinput_touch_pad_slave_id { + get_xinput_device_id 'SynPS/2 Synaptics TouchPad' +} + +# +# resolve the xinput device id of the keyboard +# +function get_xinput_track_touch_pad_master_id { + get_xinput_device_id 'Virtual core pointer' +} + +# +# resolve the xinput device id of the keyboard +# +function get_xinput_keyboard_slave_id { + get_xinput_device_id 'AT Translated Set' +} + +# +# resolve the xinput device id of the keyboard +# +function get_xinput_keyboard_master_id { + get_xinput_device_id 'Virtual core keyboard' +} + +# +# do attach action +# +function do_action_attach { + local context="${1}" + local device_id_slave="${2}" + local device_id_master="${3}" + + if [[ -z "${device_id_slave}" ]] || [[ -z "${device_id_master}" ]]; then + write_critical 'Unresolved device' \ + 'Failed to automatically resolve the device ID' + fi + + xinput reattach ${device_id_slave} ${device_id_master} + + if [[ $? -ne 0 ]]; then + write_critical 'Attach failure' \ + "Failed to attach slave device (${context}) to master!" + fi + + write_normal_line 'Device "%s" (%s) has been attached to "%s".' \ + "${device_id_slave}" \ + "${context}" \ + "${device_id_master}" + +} + +# +# do attach detach +# +function do_action_detach { + local context="${1}" + local device_id_slave="${2}" + local device_id_master="${3}" + + if [[ -z "${device_id_slave}" ]] || [[ -z "${device_id_master}" ]]; then + write_critical 'Unresolved device' \ + 'Failed to automatically resolve the device ID' + fi + + xinput float ${device_id_slave} + + if [[ $? -ne 0 ]]; then + write_critical 'Detach failure' \ + "Failed to detach slave device (${context}) from master!" + fi + + write_normal_line 'Device "%s" (%s) has been detached from "%s".' \ + "${device_id_slave}" \ + "${context}" \ + "${device_id_master}" +} + +# +# do attach action +# +function do_action_status { + local context="${1}" + local device_id_slave="${2}" + local device_id_master="${3}" + local search + + case "${context}" in + k|keyboard ) + search='AT Translated Set.+floating slave' + ;; + t|touch-pad ) + search='SynPS/2 Synaptics TouchPad.+floating slave' + ;; + p|track-point ) + search='TPPS/2 IBM TrackPoint.+floating slave' + ;; + esac + + xinput | grep -E "${search}" &> /dev/null + + if [[ $? -ne 0 ]]; then + write_normal_line 'Device "%s" (%s) is ATTACHED to "%s".' \ + "${device_id_slave}" \ + "${context}" \ + "${device_id_master}" + else + write_normal_line 'Device "%s" (%s) is DETACHED.' \ + "${device_id_slave}" \ + "${context}" + fi +} + +# +# do attach action +# +function do_action_list { + xinput | \ + grep -o -P '[A-Za-z][a-zA-Z0-9:\./ -]+\s+id=[0-9]+.+' | \ + sed -r -n -e 's/\[(slave|master)[ ]*([a-z]*)[ ]*\(([0-9]*)\)\]/master-id="\3"/p' | \ + sed -r -n -e 's/id=([0-9]+)/keyboard-slave-id="\1"/p' | \ + sed -r -n -e 's/^([A-Za-z][a-zA-Z0-9:\./ -]+)/name="\1"/p' | \ + column +} + +# +# main function +# +function main { + local rollback=0 + local rollback_time=60 + local keyboard_slave_id + local keyboard_master_id + local touch_pad_slave_id + local touch_pad_master_id + local track_point_slave_id + local track_point_master_id + local action + local contexts=() + + if [[ ! "$(which xinput)" ]]; then + write_critical 'Missing dependency' \ + 'Failed to locate the "xinput" command. Ensure the required X.org packages are installed and try again.' + fi + + while [[ $# -gt 0 ]] && [[ ."-${1}" = .--* ]]; do + opt="${1}" + shift + + case "${opt}" in + "--" ) + break 2 + ;; + -k=* | --keyboard-slave-id=* ) + keyboard_slave_id="${opt#*=}" + ;; + -K=* | --keyboard-master-id=* ) + keyboard_master_id="${opt#*=}" + ;; + -t=* | --touch-pad-slave-id=* ) + touch_pad_slave_id="${opt#*=}" + ;; + -T=* | --touch-pad-master-id=* ) + touch_pad_master_id="${opt#*=}" + ;; + -p=* | --track-point-slave-id=* ) + track_point_slave_id="${opt#*=}" + ;; + -P=* | --track-point-master-id=* ) + track_point_master_id="${opt#*=}" + ;; + -x | --test ) + rollback=1 + ;; + -x=* | --test=* ) + rollback=1 + rollback_wait="${opt#*=}" + ;; + -v | --version ) + printf '%s version 1.0.0\n' "$(get_script_name)" + exit + ;; + -h | --help ) + write_usage + exit + ;; + * ) + write_error 'Invalid option name' \ + 'An invalid argument option name was provided: "%s".' \ + "${opt}" + write_usage + do_exit + ;; + esac + + if [[ ${s} -eq 1 ]]; then + shift + fi + done + + if [[ -z "${keyboard_slave_id}" ]]; then + keyboard_slave_id="$(get_xinput_keyboard_slave_id)" + fi + + if [[ -z "${keyboard_master_id}" ]]; then + keyboard_master_id="$(get_xinput_keyboard_master_id)" + fi + + if [[ -z "${touch_pad_slave_id}" ]]; then + touch_pad_slave_id="$(get_xinput_touch_pad_slave_id)" + fi + + if [[ -z "${touch_pad_master_id}" ]]; then + touch_pad_master_id="$(get_xinput_track_touch_pad_master_id)" + fi + + if [[ -z "${track_point_slave_id}" ]]; then + track_point_slave_id="$(get_xinput_track_point_slave_id)" + fi + + if [[ -z "${track_point_master_id}" ]]; then + track_point_master_id="$(get_xinput_track_touch_pad_master_id)" + fi + + while [[ $# -gt 0 ]]; do + if [[ ! -z "${action}" ]]; then + write_critical 'Too many actions' \ + 'Only one action can be specified (use "%s" or "%s").' \ + "${action}" \ + "${1,,}" + fi + action="${1,,}" + shift + if [[ ! -z "${context}" ]]; then + write_critical 'Too many contexts' \ + 'Only one context can be specified (use "%s" or "%s").' \ + "${context}" \ + "${1,,}" + fi + context="${1,,}" + shift + done + + if [[ -z "${action}" ]]; then + write_error 'Unspecified action' \ + 'An action must be specified via the command arguments!' + write_usage + do_exit 255 + fi + + [[ -z "${context}" ]] && context='ktp' + [[ "${action}" == 'l' ]] || [[ "${action}" == 'list' ]] && context='k' + + if [[ ${rollback} -eq 1 ]]; then + write_critical 'Unimplemented' \ + 'The testing/rollback functionality has not yet been implemented!' + fi + + for c in $(echo ${context} | sed -e 's/[^a-z-]//g' | sed -e 's/./\0\n/g')\ + ; do + case "${c}" in + k|keyboard ) + c=keyboard + device_slave_id=${keyboard_slave_id} + device_master_id=${keyboard_master_id} + ;; + t|touch-pad ) + c=touch-pad + device_slave_id=${touch_pad_slave_id} + device_master_id=${touch_pad_master_id} + ;; + p|track-point ) + c=track-point + device_slave_id=${track_point_slave_id} + device_master_id=${track_point_master_id} + ;; + * ) + write_critical 'Invalid context' \ + 'An unknown context was specified "%s"!' \ + "${c}" + ;; + esac + + case "${action}" in + a|attach ) + do_action_attach \ + "${c}" \ + "${device_slave_id}" \ + "${device_master_id}" + ;; + d|detach ) + do_action_detach \ + "${c}" \ + "${device_slave_id}" \ + "${device_master_id}" + ;; + s|status ) + do_action_status \ + "${c}" \ + "${device_slave_id}" \ + "${device_master_id}" + ;; + l|list ) + do_action_list + ;; + * ) + write_critical 'Invalid action' \ + 'An unknown action was specified "%s"!' \ + "${action}" + ;; + esac + done +} + +# +# internal variables +# +readonly _SELF_PATH="$(dirname "$(readlink -m "${0}")")" + +# +# configuration +# +if [[ -z "${BRIGHT_LIBRARY_PATH}" ]]; then + BRIGHT_LIBRARY_PATH="${_SELF_PATH}/../lib/bright-library/bright.bash" +fi + +# +# check for required bright library dependency +# +if [[ ! -f "${BRIGHT_LIBRARY_PATH}" ]]; then + printf 'Failed to source required dependency: bright-library (%s)\n' \ + "${BRIGHT_LIBRARY_PATH}" + exit 255 +fi + +# +# source bright library dependency +# +source "${BRIGHT_LIBRARY_PATH}" + +# +# setup bright library configuration +# +BRIGHT_AUTO_NL=0 + +# +# go! +# +main "$@" diff --git a/bin-available/bash.bash b/bin-available/bash.bash deleted file mode 100644 index 9603dc5..0000000 --- a/bin-available/bash.bash +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -## -## This file is part of the `src-run/user-scripts-server` project. -## -## (c) Rob Frawley 2nd <rmf@src.run> -## -## For the full copyright and license information, please view the LICENSE.md -## file that was distributed with this source code. -## - -printf 'B0:"%s"\n' "${BASH_SOURCE[0]}" -printf 'B1:"%s"\n' "${BASH_SOURCE[1]}" -printf 'B2:"%s"\n' "${BASH_SOURCE[2]}" -printf 'B3:"%s"\n' "${BASH_SOURCE[3]}" diff --git a/bin-available/blocklist-dl.bash b/bin-available/blocklist-dl.bash index e7e1711..7167715 100755 --- a/bin-available/blocklist-dl.bash +++ b/bin-available/blocklist-dl.bash @@ -13,11 +13,12 @@ # configuration variables # -BLOCKLIST_URL="http://list.iblocklist.com/?list=bt_level2&fileformat=cidr&archiveformat=gz" -BLOCKLIST_EXT_TYPE="cidr" -BLOCKLIST_OUT_ROOT="/tmp" -BLOCKLIST_LOG_ROOT="/tmp" -BLOCKLIST_TMP_ROOT="/tmp" +BLOCKLIST_URL_LINK='http://list.iblocklist.com/?list=bt_level2&fileformat=cidr&archiveformat=gz' +BLOCKLIST_EXT_TYPE='cidr' +BLOCKLIST_DIR_BASE='/pool/torrent/blocklist-comprehensive' +BLOCKLIST_OUT_ROOT="${BLOCKLIST_DIR_BASE}/src" +BLOCKLIST_LOG_ROOT="${BLOCKLIST_DIR_BASE}/var" +BLOCKLIST_TMP_ROOT="${BLOCKLIST_DIR_BASE}/tmp" # # internal variables @@ -26,14 +27,108 @@ BLOCKLIST_TMP_ROOT="/tmp" BLOCKLIST_OUT="${BLOCKLIST_OUT_ROOT}/blocklist.${BLOCKLIST_EXT_TYPE}.txt" BLOCKLIST_LOG="${BLOCKLIST_LOG_ROOT}/blocklist.${BLOCKLIST_EXT_TYPE}.log" -function log_start() +function nuller() { - printf '\n[RUN @ "%s"]\n' "$(date)" >> "${BLOCKLIST_LOG}" + local nullable=${1:-$(</dev/stdin)} + + printf '[NULLABLE] => "%s"\n' "${nullable}" +} + +printf 'a fun little error message!' @> >(nuller) +printf 'a fun little error message!' 2>&1 1> >(nuller) +printf 'a fun little error message!' 1>&2 2> >(nuller) +exit +function fmt_date() +{ + local format="${1}" + + if [[ -n ${format} ]]; then + date +"${format}" 2> /dev/null | awk '{$1=$1};1' 2> /dev/null + + return $? + fi + + return 1 } -function out_title() +function get_date() { - local format="${1^^}" + local detail="${1:-1}" + local f_year='%Y' + local format='%m-%d' + + [[ ${detail} -eq 1 ]] && format="${f_year}:${format}" + + fmt_date "${format}" + + return $? +} + +function get_time() +{ + local detail="${1:-1}" + local format='' + + local f_h_24='%H' + local f_m_24='%M' + local f_s_24='%S' + local f_n_24='%N' + local f_p_24='' + local fmt_24="${f_h_24}:${f_m_24}" + + local f_h_12='%I' + local f_m_12='%M' + local f_s_12='%S' + local f_n_12='%N' + local f_p_12='%p' + local fmt_12="${f_h_12}:${f_m_24}" + + [[ ${detail} -eq 1 ]] && fmt_24="${fmt_24}" + [[ ${detail} -eq 2 ]] && fmt_24="${fmt_24}:${f_s_24}" + [[ ${detail} -eq 3 ]] && fmt_24="${fmt_24}:${f_s_24}.${f_n_24}" + + [[ ${detail} -eq -1 ]] && fmt_12="${fmt_12} ${f_p_12}" + [[ ${detail} -eq -2 ]] && fmt_12="${fmt_12}:${f_s_12} ${f_p_12}" + [[ ${detail} -eq -3 ]] && fmt_12="${fmt_12}:${f_s_12}.${f_n_12} ${f_p_12}" + + if [[ ${detail} -ge 0 ]]; then + format="${fmt_24}" + else + format="${fmt_12}" + fi + + fmt_date "${format}" + + return $? +} + +function get_unix() +{ + local detail="${1:-1}" + local f_nans='%N' + local format="%s" + + [[ ${detail} -eq 1 ]] && format+=".${f_nans}" + [[ ${detail} -eq -1 ]] && format="${f_nans}" + + fmt_date "${format}" + + return $? +} + +printf '[get_date ] => "%s"\n' "$(get_date)" +printf '[get_time ] => "%s"\n' "$(get_time)" +printf '[get_unix ] => "%s"\n' "$(get_unix)" +printf '[get_unix:1] => "%s"\n' "$(get_unix 1)" +printf '[get_unix:1] => "%s"\n' "$(get_unix 0)" + +exit + +#date +%Y-%m-%d\ \@\ %H:%M:%S\ \(%s\.%N\) + +function out_sect() +{ + local format=" [ ${1^^} ] " shift printf "${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" @@ -47,16 +142,22 @@ function out_info() printf " • ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" } -function out_error() +function out_warn() { local format="${1}" shift - printf " • [ERROR] ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" + printf " ! [WARN] ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" exit 255 } +function log_init() +{ + out_sect 'LOG-RUN @ "%s"' "$(date)" + printf '\n[RUN @ "%s"]\n' "$(date)" >> "${BLOCKLIST_LOG}" +} + function main() { local path="${BLOCKLIST_TMP_ROOT}/blocklist-download-temporary-work" @@ -82,15 +183,15 @@ function main() fi fi - log_start - out_title 'Updating blocklist:' "${BLOCKLIST_URL}" + log_init + out_sect 'Updating blocklist:' "${BLOCKLIST_URL_LINK}" out_info 'Logged blocklist stat: %s' "${BLOCKLIST_LOG}" if [[ ! -d "${path}" ]]; then mkdir -p "${path}" if [[ $? -ne 0 ]]; then - out_error 'Unable to create temporary working directory "%s"!' "${path}" + out_warn 'Unable to create temporary working directory "%s"!' "${path}" fi fi @@ -98,23 +199,23 @@ function main() rm "${file}" if [[ $? -ne 0 ]]; then - out_error 'Unable to remove old temporary working file "%s"!' "${file}" + out_warn 'Unable to remove old temporary working file "%s"!' "${file}" fi fi - out_info 'Fetch blocklist link: "%s"' "${BLOCKLIST_URL}" + out_info 'Fetch blocklist link: "%s"' "${BLOCKLIST_URL_LINK}" - wget -q -O "${file}" "${BLOCKLIST_URL}" + wget -q -O "${file}" "${BLOCKLIST_URL_LINK}" if [[ $? -ne 0 ]]; then - out_error 'Unable to download blocklist "%s"!' "${BLOCKLIST_URL}" + out_warn 'Unable to download blocklist "%s"!' "${BLOCKLIST_URL_LINK}" exit fi local size="$(gzip -dc "${file}" | grep -E '^[0-9]' | wc -l)" if [[ ${size} -eq 0 ]]; then - out_error 'Unable to create blocklist as download contains 0 lines!' + out_warn 'Unable to create blocklist as download contains 0 lines!' exit fi @@ -123,7 +224,7 @@ function main() gzip -dc "${file}" | grep -E '^[0-9]' | sort -u > "${BLOCKLIST_OUT}" if [[ $? -ne 0 ]]; then - out_error 'Unable to parse downloaded blocklist "%s"!' "${path}" + out_warn 'Unable to parse downloaded blocklist "%s"!' "${path}" fi out_info 'Clean temporary data: "%s"' "${path}" @@ -131,7 +232,7 @@ function main() rm -fr "${path}" if [[ $? -ne 0 ]]; then - out_error 'Unable to remove temporary working path "%s"!' "${path}" + out_warn 'Unable to remove temporary working path "%s"!' "${path}" fi } diff --git a/bin-available/build-ffmpeg.zsh b/bin-available/build-ffmpeg.zsh new file mode 100755 index 0000000..2b5115a --- /dev/null +++ b/bin-available/build-ffmpeg.zsh @@ -0,0 +1,327 @@ +#!/usr/bin/env zsh + +declare -ra DEPS_LIST=( + 'autoconf' + 'automake' + 'build-essential' + 'checkinstall' + 'cmake' + 'frei0r-plugins-dev' + 'gcc' + 'git' + 'git-core' + 'gnutls-dev' + 'ladspa-sdk' + 'libaom-dev' + 'libass-dev' + 'libavc1394-0' + 'libavc1394-dev' + 'libbluray-dev' + 'libbs2b-dev' + 'libbs2b0' + 'libcaca-dev' + 'libcdio-paranoia-dev' + 'libcodec2-dev' + 'libdc1394-22' + 'libdc1394-22-dev' + 'libdrm-dev' + 'libfdk-aac-dev' + 'libfontconfig1-dev' + 'libfreetype6-dev' + 'libfribidi-dev' + 'libgme-dev' + 'libgpac-dev' + 'libgsm1-dev' + 'libiec61883-0' + 'libiec61883-dev' + 'libjack-dev' + 'liblilv-dev' + 'libmodplug-dev' + 'libmp3lame-dev' + 'libopenal-dev' + 'libopencore-amrnb-dev' + 'libopencore-amrwb-dev' + 'libopenjp2-7-dev' + 'libopenmpt-dev' + 'libopus-dev' + 'libpulse-dev' + 'librsvg2-dev' + 'librtmp-dev' + 'librubberband-dev' + 'libsdl1.2-dev' + 'libsdl2-dev' + 'libshine-dev' + 'libsmbclient-dev' + 'libsnappy-dev' + 'libsoxr-dev' + 'libspeex-dev' + 'libssh-dev' + 'libtesseract-dev' + 'libtheora-dev' + 'libtool' + 'libtwolame-dev' + 'libv4l-dev' + 'libva-dev' + 'libvdpau-dev' + 'libvo-amrwbenc-dev' + 'libvorbis-dev' + 'libvpx-dev' + 'libwebp-dev' + 'libx11-dev' + 'libx264-dev' + 'libx265-dev' + 'libxcb-shm0-dev' + 'libxcb-xfixes0-dev' + 'libxcb1-dev' + 'libxext-dev' + 'libxfixes-dev' + 'libxml2-dev' + 'libxvidcore-dev' + 'libzvbi-dev' + 'nasm' + 'opencl-dev' + 'p11-kit' + 'pkg-config' + 'texi2html' + 'texinfo' + 'wget' + 'yasm' + 'zlib1g-dev' +) + +declare -r WORK_PATH="${1:-/opt/ffmpeg-sources}" +declare -r MAKE_JOBS="$(cat /proc/cpuinfo | grep processor | wc -l)" +declare -r LOGS_FILE="${WORK_PATH}/build-ffmpeg.$(date +%s).log" + +declare -r FDKA_VERS='2.0.2' +declare -r FDKA_PATH="${WORK_PATH}/libs_fdkaac-${FDKA_VERS}" +declare -r FDKA_LINK='https://github.com/mstorsjo/fdk-aac.git' + +declare -r LAME_VERS='3.100' +declare -r LAME_PATH="${WORK_PATH}/libs_lame-${LAME_VERS}" +declare -r LAME_LINK="https://sourceforge.net/projects/lame/files/lame/${LAME_VERS}/lame-${LAME_VERS}.tar.gz" +declare -r LAME_DLFN="${WORK_PATH}/$(basename "${LAME_LINK}")" + +declare -r FMPG_VERS='4.4.2' +declare -r FMPG_PATH="${WORK_PATH}/main_ffmpeg-${FMPG_VERS}" +declare -r FMPG_LINK="https://ffmpeg.org/releases/ffmpeg-${FMPG_VERS}.tar.gz" +declare -r FMPG_DLFN="${WORK_PATH}/$(basename "${FMPG_LINK}")" + +function out() { + local type="${1}" + local pref="$(printf -- '[build-ffmpeg@%.03f] (%s)' "$(date +%s\.%N)" "${type}")" + local cols="$(($(tput cols) - 10 - ${#pref}))" + local -a secs=("${(@f)$(printf -- "${@:2}" | fold -s -w "${cols}" | awk '{$1=$1;print}')}") + local ipos=1 + + if [[ ! -d "${WORK_PATH}" ]]; then + mkdir -p "${WORK_PATH}" &> /dev/null + out 'action' 'created working directory: "%s"' "${WORK_PATH}" + fi + + for l in ${(v)secs}; do + printf '# ' | tee -a "${LOGS_FILE}" 2> /dev/null + if [[ ${ipos} -eq 1 ]]; then + printf -- '%s' "${pref}" | tee -a "${LOGS_FILE}" 2> /dev/null + if [[ ${#secs[@]} -le 1 ]]; then + printf -- ' ─────▶' | tee -a "${LOGS_FILE}" 2> /dev/null + else + printf -- ' ──┬──▶' | tee -a "${LOGS_FILE}" 2> /dev/null + fi + else + for i in {1..${#pref}}; do printf -- ' ' | tee -a "${LOGS_FILE}" 2> /dev/null; done + if [[ ${#secs[@]} -eq ${ipos} ]]; then + printf -- ' └──▶' | tee -a "${LOGS_FILE}" 2> /dev/null + else + printf -- ' ├──▶' | tee -a "${LOGS_FILE}" 2> /dev/null + fi + fi + printf ' %s\n' "${l}" | tee -a "${LOGS_FILE}" 2> /dev/null + ipos=$((ipos + 1)) + done +} + +function err() { + out 'failed' "${@}" + out 'failed' 'exiting due to prior error...' + exit 1 +} + +out 'logger' 'writing command output to file "%s"' "${LOGS_FILE}" + +for f in "${LAME_DLFN}" "${FMPG_DLFN}"; do + if [[ -f "${f}" ]]; then + out 'cleans' 'removing existing dependency release archive: "%s"' "${f}" + rm -f "${f}" &>>| "${LOGS_FILE}" || err 'failed to remove file "%s"' "${f}" + fi +done + +for d in "${FDKA_PATH}" "${LAME_PATH}" "${LAME_PATH}"; do + if [[ -d "${d}" ]]; then + out 'cleans' 'cleaning up existing build directory: "%s"' "${d}" + rm -fr "${d}" &>>| "${LOGS_FILE}" || err 'failed to remove directory "%s"' "${d}" + fi +done + +out 'system' 'updading package caches' +DEBIAN_FRONTEND=noninteractive apt-get update < /dev/null &>>| "${LOGS_FILE}" + +out 'system' 'updading system packages' +DEBIAN_FRONTEND=noninteractive apt-get -y upgrade < /dev/null &>>| "${LOGS_FILE}" + +out 'system' 'installing dependencies: "%s"' "$(sed -E 's/[ ]/, /g' <<< "${DEPS_LIST[*]}")" +DEBIAN_FRONTEND=noninteractive apt-get -y install ${(v)DEPS_LIST} < /dev/null &>>| "${LOGS_FILE}" || err 'failed to install dependencies!' + +#out 'action' 'entering working directory: "%s"' "${WORK_PATH}" +#cd "${WORK_PATH}" &>>| "${LOGS_FILE}" || err 'failed to enter directory!' +# +#out 'source' 'cloning tag "%s" of repository "%s" to "%s"' "${FDKA_VERS}" "${FDKA_LINK}" "${FDKA_PATH}" +#git clone --depth 1 -b "v${FDKA_VERS}" "${FDKA_LINK}" "${FDKA_PATH}" &>>| "${LOGS_FILE}" || err 'failed to clone repository!' +# +#out 'action' 'entering dependency source directory: "%s"' "${FDKA_PATH}" +#cd "${FDKA_PATH}" &>>| "${LOGS_FILE}" || err 'failed to enter directory!' +# +#out 'builds' 'configuring source of libfdk-acc' +#autoreconf -fiv &>>| "${LOGS_FILE}" || err 'failed to run autoreconf!' +#./configure \ +# --prefix="${WORK_PATH}" \ +# --enable-shared \ +# &>>| "${LOGS_FILE}" || err 'failed to run configure!' +# +#out 'builds' 'compiling libfdk-acc using %d jobs' "${MAKE_JOBS}" +#make -j${MAKE_JOBS} &>>| "${LOGS_FILE}" || err 'failed to run make!' +# +#out 'builds' 'installing libfdk-acc to prefix "%s"' "${WORK_PATH}" +#make install &>>| "${LOGS_FILE}" || err 'failed to run make install!' +# +#out 'builds' 'cleaning up source build artifacts' +#make distclean &>>| "${LOGS_FILE}" || err 'failed to run make distclean!' +# +#out 'action' 'entering working directory: "%s"' "${WORK_PATH}" +#cd "${WORK_PATH}" &>>| "${LOGS_FILE}" || err 'failed to enter directory!' +# +#out 'action' 'creating dependency source directory: "%s"' "${LAME_PATH}" +#mkdir -p "${LAME_PATH}" &>>| "${LOGS_FILE}" || err 'failed to create directory!' +# +#out 'source' 'downloading release "%s" from "%s" to "%s"' "${LAME_VERS}" "${LAME_LINK}" "${LAME_DLFN}" +#wget "${LAME_LINK}" -O "${LAME_DLFN}" &>>| "${LOGS_FILE}" || err 'failed to download release archive!' +# +#out 'source' 'extracting "%s" to "%s"' "${LAME_DLFN}" "${LAME_PATH}" +#tar -xzvf "${LAME_DLFN}" -C "${LAME_PATH}" --strip-components=1 &>>| "${LOGS_FILE}" || err 'failed to extract release archive!' +# +#out 'action' 'entering dependency source directory: "%s"' "${LAME_PATH}" +#cd "${LAME_PATH}" &>>| "${LOGS_FILE}" || err 'failed to enter directory!' +# +#out 'builds' 'configuring source of liblame' +#./configure \ +# --prefix="${WORK_PATH}" \ +# --enable-nasm \ +# --enable-shared \ +# &>>| "${LOGS_FILE}" || err 'failed to run configure!' +# +#out 'builds' 'compiling liblame using %d jobs' "${MAKE_JOBS}" +#make -j${MAKE_JOBS} &>>| "${LOGS_FILE}" || err 'failed to run make!' +# +#out 'builds' 'installing liblame to prefix "%s"' "${WORK_PATH}" +#make install &>>| "${LOGS_FILE}" || err 'failed to run make install!' +# +#out 'builds' 'cleaning up source build artifacts' +#make distclean &>>| "${LOGS_FILE}" || err 'failed to run make distclean!' + +out 'action' 'entering working directory: "%s"' "${WORK_PATH}" +cd "${WORK_PATH}" &>>| "${LOGS_FILE}" || err 'failed to enter directory!' + +out 'action' 'creating dependency source directory: "%s"' "${FMPG_PATH}" +mkdir -p "${FMPG_PATH}" &>>| "${LOGS_FILE}" || err 'failed to create directory!' + +out 'source' 'downloading release "%s" from "%s" to "%s"' "${FMPG_VERS}" "${FMPG_LINK}" "${FMPG_DLFN}" +wget "${FMPG_LINK}" -O "${FMPG_DLFN}" &>>| "${LOGS_FILE}" || err 'failed to download release archive!' + +out 'source' 'extracting "%s" to "%s"' "${FMPG_DLFN}" "${FMPG_PATH}" +tar -xzvf "${FMPG_DLFN}" -C "${FMPG_PATH}" --strip-components=1 &>>| "${LOGS_FILE}" || err 'failed to extract release archive!' + +out 'action' 'entering dependency source directory: "%s"' "${FMPG_PATH}" +cd "${FMPG_PATH}" &>>| "${LOGS_FILE}" || err 'failed to enter directory!' + +out 'builds' 'configuring source of ffmpeg' +export PKG_CONFIG_PATH="${WORK_PATH}/lib/pkgconfig" +./configure \ + --prefix="${WORK_PATH}" \ + --bindir="${WORK_PATH}/bin" \ + --disable-stripping \ + --enable-avresample \ + --enable-frei0r \ + --enable-gmp \ + --enable-gnutls \ + --enable-gpl \ + --enable-ladspa \ + --enable-libaom \ + --enable-libass \ + --enable-libbluray \ + --enable-libbs2b \ + --enable-libcaca \ + --enable-libcdio \ + --enable-libcodec2 \ + --enable-libdc1394 \ + --enable-libdrm \ + --enable-libfdk-aac \ + --enable-libfontconfig \ + --enable-libfreetype \ + --enable-libfribidi \ + --enable-libgme \ + --enable-libgsm \ + --enable-libiec61883 \ + --enable-libjack \ + --enable-libmodplug \ + --enable-libmp3lame \ + --enable-libopencore-amrnb \ + --enable-libopencore-amrwb \ + --enable-libopenjpeg \ + --enable-libopenmpt \ + --enable-libopus \ + --enable-libpulse \ + --enable-librsvg \ + --enable-librtmp \ + --enable-librubberband \ + --enable-libshine \ + --enable-libsnappy \ + --enable-libsoxr \ + --enable-libspeex \ + --enable-libssh \ + --enable-libtesseract \ + --enable-libtheora \ + --enable-libtwolame \ + --enable-libv4l2 \ + --enable-libvo-amrwbenc \ + --enable-libvorbis \ + --enable-libvpx \ + --enable-libwebp \ + --enable-libx264 \ + --enable-libx265 \ + --enable-libxml2 \ + --enable-libxvid \ + --enable-libzvbi \ + --enable-lv2 \ + --enable-nonfree \ + --enable-openal \ + --enable-opencl \ + --enable-opengl \ + --enable-sdl2 \ + --enable-small \ + --enable-version3 \ + --enable-shared \ + --extra-version="0ubuntu0.2" \ + --toolchain="hardened" \ + &>>| "${LOGS_FILE}" || err 'failed to run configure!' + +# --incdir="/usr/include/x86_64-linux-gnu" \ +# --libdir="/usr/lib/x86_64-linux-gnu" \ + +out 'builds' 'compiling ffmpeg using %d jobs' "${MAKE_JOBS}" +make -j${MAKE_JOBS} &>>| "${LOGS_FILE}" || err 'failed to run make!' + +out 'builds' 'installing ffmpeg to prefix "%s" using bin directory "%s"' "${WORK_PATH}" "${WORK_PATH}/bin" +make install &>>| "${LOGS_FILE}" || err 'failed to run make install!' + +out 'builds' 'cleaning up source build artifacts' +make distclean &>>| "${LOGS_FILE}" || err 'failed to run make distclean!' diff --git a/bin-available/color-convert.bash b/bin-available/color-convert.bash index 16707ba..b4469fc 100755 --- a/bin-available/color-convert.bash +++ b/bin-available/color-convert.bash @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/bash ## ## This file is part of the `src-run/user-scripts-server` project. @@ -9,24 +9,24 @@ ## file that was distributed with this source code. ## -isRgbFormat() +function isRgbFormat() { [[ ${1} =~ ^((2[0-4][0-9]|25[0-5]|[01]?[0-9]?[0-9]),?\s?){3}$ ]]; return $? } -isHexFormat() +function isHexFormat() { [[ ${1} =~ ^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$ ]]; return $? } -writeRgbAsHex() +function writeRgbAsHex() { local rgb=($(echo ${1} | tr "," "\n")) printf "%02X%02X%02X\n" ${rgb[@]} } -writeHexAsRgb() +function writeHexAsRgb() { local h=${1} @@ -37,7 +37,7 @@ writeHexAsRgb() printf "%d,%d,%d\n" 0x${h:0:2} 0x${h:2:2} 0x${h:4:2} } -sanitizeFormat() +function sanitizeFormat() { local f="${1}" local v=(${@}) @@ -53,7 +53,7 @@ sanitizeFormat() fi } -main() { +function main() { local f=$(sanitizeFormat ${@}) if isHexFormat ${f}; then diff --git a/bin-available/deb-install.bash b/bin-available/deb-install.bash new file mode 100755 index 0000000..4c8c250 --- /dev/null +++ b/bin-available/deb-install.bash @@ -0,0 +1,29 @@ +#!/bin/bash + +function out_line { + local +} + +function main { + local deb_file="${1}" + local deb_opts="${@:2}" + + if [[ -z "${deb_file}" ]]; then +} + +if [[ ${#} -eq 0 ]]; then + printf 'Usage: ./$0 [DEB-PKG-FILE-NAME]\n' + exit 255 +fi + +if [[ ${#} -gt 1 ]]; then + sudo gdebi --option="${@:2}" "${1}" + +sudo gdebi --with-depends --tool apt ${@} + +if [[ $? -eq 0 ]]; then + printf 'Finished package install with options "%s"...\n' "${@}" +else + printf 'FAILED package install with options "%s"...\n' "${@}" + exit 255 +fi diff --git a/bin-available/diffr.bash b/bin-available/diffr.bash new file mode 100644 index 0000000..a40686e --- /dev/null +++ b/bin-available/diffr.bash @@ -0,0 +1,5 @@ +#!/bin/bash + +function main { + +} diff --git a/bin-available/disk-op-sizes-monitor.bash b/bin-available/disk-op-sizes-monitor.bash new file mode 100755 index 0000000..304364f --- /dev/null +++ b/bin-available/disk-op-sizes-monitor.bash @@ -0,0 +1,194 @@ +#!/usr/bin/env bash + +declare -A _NAME_CACHE_MAP=() +declare -A _SIZE_CACHE_MAP=() + +function out_text { printf -- "${@}"; } +function out_newl { out_text '\n'; } +function out_line { out_text "${1}\n" "${@:2}"; } +function out_head { out_line "## ${1}" "${@:2}"; } +function out_hdef { out_head '%s => "%s"' "${1^^}" "$(out_text "${@:2}")"; } + +function str_sub { + local str="${1:-$(</dev/stdin)}" + local beg="${2:-0}" + local end="${3:-$((${#str} - 1))}" + + (out_text "${str:${beg}:${end}}") 2> /dev/null +} + +function arr_maps_printf { + for val in "${@:2}"; do + out_text "${1}" "${val}" + done +} + +function resolve_interface_addr_type { + declare type_reqrd="${1}" + declare call_value='' + declare call_ilist='' + declare -A call_olist=( + [r]='-r' + [l]='' + ) + declare -a interfaces=( + eno1 + enp0s0 + enp1s0 + enp2s0 + enp3s0 + enp4s0 + enp5s0 + enp6s0 + enp7s0 + enp8s0 + ) + + case "${type_reqrd:l}" in + r|remote ) call_ilist=r ;; + l|local|*) call_ilist=l ;; + esac + + for i_name in "${interfaces[@]}"; do + if call_value="$(ip-info -i=${i_name} -m -q ${call_olist[${call_ilist}]})"; then + if [[ "${call_value}" =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; then + break + fi + fi + done + + out_text '%s' "${call_value}" +} + +function resolve_interface_addr_type_l { + resolve_interface_addr_type 'l' +} + +function resolve_interface_addr_type_r { + resolve_interface_addr_type 'r' +} + +function do_display_heading { + local -a names=("${@}") + + out_newl + out_head + out_head + + out_hdef \ + name \ + 'RTO Backup Archive Extraction Progress' + + out_hdef \ + date \ + "$(date)" + + out_head + + out_hdef \ + dist \ + '%s (%s)' \ + "$(lsb_release -d | cut -f2 )" \ + "$(lsb_release -c | cut -f2)" + + out_hdef \ + kern \ + '%s %s (%s)' \ + "$(uname -s)" \ + "$(uname -r)" \ + "$(uname -i)" + + out_hdef \ + host \ + '%s (%s)' \ + "$(hostname -f)" \ + "$( + hostname -a | \ + sed -E 's/[ ]+/\n/g' | \ + sed -E 's/^ip6-//g' | \ + sort -r | \ + uniq | \ + xargs + )" + + out_hdef \ + addr \ + '%s (%s)' \ + "$(resolve_interface_addr_type_l)" \ + "$(resolve_interface_addr_type_r)" + + out_head + + out_hdef \ + data \ + "$(str_sub '' '0' '-2' <<< "$(arr_maps_printf '%s, ' "${names[@]}")")" + + out_head + out_head + + out_newl +} + +function do_filecal_sizings { + echo + #"${R:-Compiling first-run statistics...}"; sleep 10; R="$(sudo du -h --max-depth=0 ./home ./home-rto-d.tar.xz)"; done +} + +function is_existing { + [[ -e "${1}" ]] || return 1 +} + +function get_name_resolver_cmd { + local -a resolver_list=(realpath readlink) + local resolver_path + + for resolver_name in "${resolver_list[@]}"; do + if resolver_path="$(command -v "${resolver_name}" 2> /dev/null)"; then + break + fi + done + + if [[ ! -n ${resolver_path} ]] || [[ ! -e ${resolver_path} ]]; then + return 1 + fi + + out_line "${resolver_path}" +} + +function obj_name_exists { + local -a fs_names=("${@}") + local fs_temps + local resolver + + if resolver="$(get_name_resolver_cmd)"; then + for i in $(seq 0 $(( ${#fs_names[@]} - 1 ))); do + if fs_temps="$("${resolver}" -e "${fs_names[${i}]}" 2> /dev/null)"; then + fs_names[${i}]="${fs_temps}" + fi + done + fi + + for name in "${fs_names[@]}"; do + is_existing "${name}" && out_line "${name}" + done +} + +function main { + local -a parms=("${@}") + local -a names=() + + mapfile -t names < <(obj_name_exists "${parms[@]}") + + do_display_heading "${names[@]}" + exit + + while true; do + do_display_heading "${names[@]}" + do_filecal_sizings + done +} + +main "${@}" + +_NAME_CACHE_MAP=() +_SIZE_CACHE_MAP=() diff --git a/bin-available/disk-op-sizes-monitor.bash~ b/bin-available/disk-op-sizes-monitor.bash~ new file mode 100755 index 0000000..88733c5 --- /dev/null +++ b/bin-available/disk-op-sizes-monitor.bash~ @@ -0,0 +1,194 @@ +#!/usr/bin/env bash + +declare -A _NAME_CACHE_MAP=() +declare -A _SIZE_CACHE_MAP=() + +function out_text { printf -- "${@}"; } +function out_newl { out_text '\n'; } +function out_line { out_text "${1}\n" "${@:2}"; } +function out_head { out_line "## ${1}" "${@:2}"; } +function out_hdef { out_head '%s => "%s"' "${1^^}" "$(out_text "${@:2}")"; } + +function str_sub { + local str="${1:-$(</dev/stdin)}" + local beg="${2:-0}" + local end="${3:-$((${#str} - 1))}" + + out_text "${str:${beg}:${end}}" +} + +function arr_maps_printf { + for val in "${@:2}"; do + out_text "${1}" "${val}" + done +} + +function resolve_interface_addr_type { + declare type_reqrd="${1}" + declare call_value='' + declare call_ilist='' + declare -A call_olist=( + [r]='-r' + [l]='' + ) + declare -a interfaces=( + eno1 + enp0s0 + enp1s0 + enp2s0 + enp3s0 + enp4s0 + enp5s0 + enp6s0 + enp7s0 + enp8s0 + ) + + case "${type_reqrd:l}" in + r|remote ) call_ilist=r ;; + l|local|*) call_ilist=l ;; + esac + + for i_name in "${interfaces[@]}"; do + if call_value="$(ip-info -i=${i_name} -m -q ${call_olist[${call_ilist}]})"; then + if [[ "${call_value}" =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; then + break + fi + fi + done + + out_text '%s' "${call_value}" +} + +function resolve_interface_addr_type_l { + resolve_interface_addr_type 'l' +} + +function resolve_interface_addr_type_r { + resolve_interface_addr_type 'r' +} + +function do_display_heading { + local -a names=("${@}") + + out_newl + out_head + out_head + + out_hdef \ + name \ + 'RTO Backup Archive Extraction Progress' + + out_hdef \ + date \ + "$(date)" + + out_head + + out_hdef \ + dist \ + '%s (%s)' \ + "$(lsb_release -d | cut -f2 )" \ + "$(lsb_release -c | cut -f2)" + + out_hdef \ + kern \ + '%s %s (%s)' \ + "$(uname -s)" \ + "$(uname -r)" \ + "$(uname -i)" + + out_hdef \ + host \ + '%s (%s)' \ + "$(hostname -f)" \ + "$( + hostname -a | \ + sed -E 's/[ ]+/\n/g' | \ + sed -E 's/^ip6-//g' | \ + sort -r | \ + uniq | \ + xargs + )" + + out_hdef \ + addr \ + '%s (%s)' \ + "$(resolve_interface_addr_type_l)" \ + "$(resolve_interface_addr_type_r)" + + out_head + + out_hdef \ + data \ + "$(str_sub '' '0' '-2' <<< "$(arr_maps_printf '%s, ' "${names[@]}")")" + + out_head + out_head + + out_newl +} + +function do_filecal_sizings { + echo + #"${R:-Compiling first-run statistics...}"; sleep 10; R="$(sudo du -h --max-depth=0 ./home ./home-rto-d.tar.xz)"; done +} + +function is_existing { + [[ -e "${1}" ]] || return 1 +} + +function get_name_resolver_cmd { + local -a resolver_list=(realpath readlink) + local resolver_path + + for resolver_name in "${resolver_list[@]}"; do + if resolver_path="$(command -v "${resolver_name}" 2> /dev/null)"; then + break + fi + done + + if [[ ! -n ${resolver_path} ]] || [[ ! -e ${resolver_path} ]]; then + return 1 + fi + + out_line "${resolver_path}" +} + +function obj_name_exists { + local -a fs_names=("${@}") + local fs_temps + local resolver + + if resolver="$(get_name_resolver_cmd)"; then + for i in $(seq 0 $(( ${#fs_names[@]} - 1 ))); do + if fs_temps="$("${resolver}" -e "${fs_names[${i}]}" 2> /dev/null)"; then + fs_names[${i}]="${fs_temps}" + fi + done + fi + + for name in "${fs_names[@]}"; do + is_existing "${name}" && out_line "${name}" + done +} + +function main { + local -a parms=("${@}") + local -a names=() + + mapfile -t names < <(obj_name_exists "${parms[@]}") + + do_display_heading "${names[@]}" + exit + + while true; do + do_display_heading "${names[@]}" + do_filecal_sizings + done +} + +main "${@}" + +_NAME_CACHE_MAP=() +_SIZE_CACHE_MAP=() diff --git a/bin-available/find-duplicates.zsh b/bin-available/find-duplicates.zsh new file mode 100755 index 0000000..150a2b9 --- /dev/null +++ b/bin-available/find-duplicates.zsh @@ -0,0 +1,74 @@ +#!/usr/bin/env zsh + +function out_info() +{ + local head_text="${1}" + local find_path="${2}" + local logs_path="${3}" + local call_exec="${4}" + local -a call_args=("${@:5}") + + printf -- '## Configuration:\n' + printf -- ' - FIND_PATH => "%s"\n' "${find_path}" + printf -- ' - LOGS_PATH => "%s"\n' "${logs_path}" + #printf -- ' - CALL_EXEC => "%s"\n' "${call_exec}" + printf -- ' - CALL_ARGS => "%s"\n' "${(@v)call_args:0:1}" + printf -- ' => "%s"\n' "${(@v)call_args:2}" + printf -- '## %s\n' "${head_text}" +} + +function main() +{ + local find_path="${1:-}" + local logs_path="${2:-/pool/var/fdupes$(sed -E 's/\//__/g' <<< "${find_path}").log}" + local call_exit=0 + local call_exec="$(command -v fdupes)" + local -a call_args=( + "${call_exec}" + '--recurse' + '--noempty' + '--nohidden' + '--size' + "${find_path}" + ) + + out_info 'Running operations:' "${find_path}" "${logs_path}" "${call_exec}" "${(@v)call_args}" + + if [[ -z "${call_exec}" ]] || [[ ! -e "${call_exec}" ]]; then + printf 'FAIL_TEXT[Unable to locate a suitable "fdupes" executable!]\n' + exit 1 + fi + + if [[ -z "${find_path}" ]]; then + printf 'FAIL_TEXT[No search path provided!]\n' + exit 1 + fi + + if [[ ! -d "${find_path}" ]]; then + printf 'FAIL_TEXT[Provided search path is not a directory!]\n' + exit 1 + fi + + "${(@v)call_args}" | tee "${logs_path}" + call_exit="${?}" + + out_info \ + "$( + printf -- 'Completed operations: (%s)' \ + "$( + if [[ "${call_exit}" -eq 0 ]]; then + printf -- 'success' + else + printf -- 'failure [code: %s]' "${call_exit}" + fi + )" + )" \ + "${find_path}" \ + "${logs_path}" \ + "${call_exec}" \ + "${(@v)call_args}" + + #fdupes --recurse --noempty --nohidden --size "${D}" | tee "/pool/var/fdupes$(sed -E 's/\//__/g' <<< "${D}").log" +} + +main "${@}" diff --git a/bin-available/ip-info.bash b/bin-available/ip-info.bash index 348dcba..e288834 100755 --- a/bin-available/ip-info.bash +++ b/bin-available/ip-info.bash @@ -14,6 +14,11 @@ # IP_INFO_OUTPUT_ERROR_SUPPRESS=0 +# +# count of prior errors +# +IP_INFO_THROWN_ERROR_NUMBERED=0 + # # resolve the script name # @@ -38,6 +43,8 @@ function write_error() local message="${1}" local do_exit="${2:--1}" + IP_INFO_THROWN_ERROR_NUMBERED="$((IP_INFO_THROWN_ERROR_NUMBERED + 1))" + if [[ ${IP_INFO_OUTPUT_ERROR_SUPPRESS} -ne 1 ]]; then printf '[ERROR] %s\n' "${message}" >&2 fi @@ -382,3 +389,4 @@ function main() } main "$@" +exit "${IP_INFO_THROWN_ERROR_NUMBERED}" diff --git a/bin-available/monitor-sensors.bash b/bin-available/monitor-sensors.bash index 5d1b6f9..c893ea6 100755 --- a/bin-available/monitor-sensors.bash +++ b/bin-available/monitor-sensors.bash @@ -80,12 +80,12 @@ while true do clear echo -e "\n--- [coretemp-isa-0000 sensors: $(date +"%Y-%m-%d@%H:%M:%S.%N")]\n"; \ - sensors coretemp-isa-0000 | tail -n6 | head -n 5 | sed -rn 's/^([^:]+):\s+([^(]+)\s+\(([^)]+)\).*$/\1\t\2\t\3/p' | sed -e's/ */ /g' | awk -F"\t" '{ printf "%-19s=> %-10s(%s)\n", $1, $2, $3 }'; \ + sensors coretemp-isa-0000 | tail -n11 | head -n 10 | sed -rn 's/^([^:]+):\s+([^(]+)\s+\(([^)]+)\).*$/\1\t\2\t\3/p' | sed -e's/ */ /g' | awk -F"\t" '{ printf "%-19s=> %-10s(%s)\n", $1, $2, $3 }'; \ echo -e "\n--- [nct6791-isa-0290 sensors: $(date +"%Y-%m-%d@%H:%M:%S.%N")]\n"; \ - sensors nct6791-isa-0290 | tail -n14 | head -n11 | sed -rn 's/^([^:]+):\s+([^(]+)\s+\(([^)]+)\).*$/\1\t\2\t\3/p' | sed -e's/ */ /g' | awk -F"\t" '{ printf "%-19s=> %-10s(%s)\n", $1, $2, $3 }'; - echo -e "\n--- [nzxt-kraken-pump: $(date +"%Y-%m-%d@%H:%M:%S.%N")]\n"; + sensors nct6791-isa-0290 | tail -n30 | head -n28 | sed -rn 's/^([^:]+):\s+([^(]+)\s+\(([^)]+)\).*$/\1\t\2\t\3/p' | sed -e's/ */ /g' | awk -F"\t" '{ printf "%-19s=> %-10s(%s)\n", $1, $2, $3 }'; +# echo -e "\n--- [nzxt-kraken-pump: $(date +"%Y-%m-%d@%H:%M:%S.%N")]\n"; COLOR=$(colorSelect) - sudo levctl -c "${COLOR}" | head -n4 | tail -n3 | sed -rn 's/^[ \t]*"([^"]+)": ([^,]+),?/\1\t\2/p' | sed -e's/_/ /g' | sed 's/[^ ]\+/\L\u&/g' | awk -F"\t" '{ printf "%-19s=> %-10s\n", $1, $2 }' - printf "Hex Color => %s\n" "${COLOR}" +# sudo levctl -c "${COLOR}" | head -n4 | tail -n3 | sed -rn 's/^[ \t]*"([^"]+)": ([^,]+),?/\1\t\2/p' | sed -e's/_/ /g' | sed 's/[^ ]\+/\L\u&/g' | awk -F"\t" '{ printf "%-19s=> %-10s\n", $1, $2 }' +# printf "Hex Color => %s\n" "${COLOR}" sleep ${POLLING_TIME} done diff --git a/bin-available/net-list-hostnames.bash b/bin-available/net-list-hostnames.bash new file mode 100755 index 0000000..8fca028 --- /dev/null +++ b/bin-available/net-list-hostnames.bash @@ -0,0 +1,19 @@ +#!/bin/bash + +printf 'Resolvable System Hostnames:\n\n' + +printf \ + '%s %s' \ + "$(hostname -a)" \ + "$(hostname -A)" | \ +sed \ + -E \ + 's/[ ]+/\n/g' | \ +sed \ + -E \ + 's/^ip6-//g' | \ +sort \ + -r | \ +uniq | \ +xargs \ + printf ' -> %s\n' diff --git a/bin-available/pixztar.bash b/bin-available/pixztar.bash new file mode 100755 index 0000000..0bb8fc4 --- /dev/null +++ b/bin-available/pixztar.bash @@ -0,0 +1,43 @@ +#!/bin/bash + +TAR_OPTS="" +TAR_FILE="" +TAR_PATH="" + +if ! TAR_EXEC="$(which tar)"; then + printf 'Failed to find "tar" binary in path: "%s"...\n' "${PATH}" + exit 255 +fi + +if ! PIXZ_EXEC="$(which pixz)"; then + printf 'Failed to find "pixz" binary in path: "%s"...\n' "${PATH}" + exit 255 +fi + + +if [[ ${1:0:1} == "-" ]]; then + TAR_OPTS="${1}" + shift +fi + +if [[ -n ${1} ]]; then + TAR_FILE="${1}" + shift +fi + +if [[ -n ${1} ]]; then + TAR_PATH="${1}" + shift +fi + +printf 'CALL[%s]\n' "${TAR_EXEC}" -I"${PIXZ_EXEC}" "${TAR_OPTS}" "${TAR_FILE}" "${TAR_PATH}" "${@}" + +IFS_BACK="${IFS}" +IFS=' +' + +"${TAR_EXEC}" -I"${PIXZ_EXEC}" "${TAR_OPTS}" "${TAR_FILE}" "${TAR_PATH}" "${@}" | while read f; do + printf 'FILE[%s]\n' "${f}" +done + +IFS="${IFS_BACK}" diff --git a/bin-available/plex-command-caller.zsh b/bin-available/plex-command-caller.zsh new file mode 100755 index 0000000..6f7037a --- /dev/null +++ b/bin-available/plex-command-caller.zsh @@ -0,0 +1,49 @@ +#!/usr/bin/env zsh + +function main() +{ + local -r call_name="${1}" + local -ra call_opts=("${@:2}") + local -r call_user='plex' + local -r vars_path='/var/lib/plexmediaserver' + local -r libs_path='/usr/lib/plexmediaserver' + local -r call_path="$( + command -v "${call_name}" || \ + printf -- '%s/%s\n' "${libs_path}" "${call_name}" + )" + local -r sudo_text='Please enter the %p user password to run command as the "%U" user: ' + + printf -- '##\n## CALL: sudo --login --user="%s" -- "%s" %s\n##\n' \ + "${call_user}" \ + "${call_path}" \ + "$(printf -- '"%s" ' "${(@v)call_opts}")" + + if [[ ! -x "${call_path}" ]]; then + printf -- '!! FAIL: Command "%s" not found in PATH or default directory of "%s"!\n' "${call_name}" "${libs_path}" >&2 + return 1 + fi + + if ! id "${call_user}" &>/dev/null; then + printf -- '!! FAIL: User "%s" does not exist!\n' "${call_user}" >&2 + return 1 + fi + + export LD_LIBRARY_PATH="${libs_path}" + export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR="${vars_path}/Library/Application Support" + export PLEX_MEDIA_SERVER_HOME="${libs_path}" + export PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS="$(lscpu | grep '^Core' | grep -oE '[0-9]+$')" + export PLEX_MEDIA_SERVER_INFO_VENDOR="$(grep '^NAME=' /etc/os-release | awk -F= '{print $2}' | tr -d \")"; + export PLEX_MEDIA_SERVER_INFO_DEVICE="PC"; + export PLEX_MEDIA_SERVER_INFO_MODEL="$(uname -m)"; + export PLEX_MEDIA_SERVER_INFO_PLATFORM_VERSION="$(grep '^VERSION=' /etc/os-release | awk -F= '{print $2}' | tr -d \")"; + + sudo \ + --login \ + --user="${call_user}" \ + --preserve-env='LD_LIBRARY_PATH,PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR,PLEX_MEDIA_SERVER_HOME,PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS,PLEX_MEDIA_SERVER_INFO_VENDOR,PLEX_MEDIA_SERVER_INFO_DEVICE,PLEX_MEDIA_SERVER_INFO_MODEL,PLEX_MEDIA_SERVER_INFO_PLATFORM_VERSION' \ + --prompt="${sudo_text}" \ + -- \ + "${call_path}" "${(@v)call_opts}" +} + +main "${@}" diff --git a/bin-available/plex-commercial-skipper.zsh b/bin-available/plex-commercial-skipper.zsh new file mode 100755 index 0000000..450c03b --- /dev/null +++ b/bin-available/plex-commercial-skipper.zsh @@ -0,0 +1,13 @@ +#!/usr/bin/env zsh + +function main() +{ + local -r extn_name='Plex Commercial Skipper' + local -ra call_opts=("${@}") + local -r call_name='plex-command-caller.zsh' + local -r self_path="${${(%):-%x}:A:h}" + + "${self_path}/${call_name}" "${extn_name}" "${(@v)call_opts}" +} + +main "${@}" diff --git a/bin-available/plex-media-fingerprinter.zsh b/bin-available/plex-media-fingerprinter.zsh new file mode 100755 index 0000000..1e4fe33 --- /dev/null +++ b/bin-available/plex-media-fingerprinter.zsh @@ -0,0 +1,13 @@ +#!/usr/bin/env zsh + +function main() +{ + local -r extn_name='Plex Media Fingerprinter' + local -ra call_opts=("${@}") + local -r call_name='plex-command-caller.zsh' + local -r self_path="${${(%):-%x}:A:h}" + + "${self_path}/${call_name}" "${extn_name}" "${(@v)call_opts}" +} + +main "${@}" diff --git a/bin-available/plex-media-scanner.zsh b/bin-available/plex-media-scanner.zsh new file mode 100755 index 0000000..0966428 --- /dev/null +++ b/bin-available/plex-media-scanner.zsh @@ -0,0 +1,13 @@ +#!/usr/bin/env zsh + +function main() +{ + local -r extn_name='Plex Media Scanner' + local -ra call_opts=("${@}") + local -r call_name='plex-command-caller.zsh' + local -r self_path="${${(%):-%x}:A:h}" + + "${self_path}/${call_name}" "${extn_name}" "${(@v)call_opts}" +} + +main "${@}" diff --git a/bin-available/plex-sqlite.zsh b/bin-available/plex-sqlite.zsh new file mode 100755 index 0000000..2b83e14 --- /dev/null +++ b/bin-available/plex-sqlite.zsh @@ -0,0 +1,13 @@ +#!/usr/bin/env zsh + +function main() +{ + local -r extn_name='Plex SQLite' + local -ra call_opts=("${@}") + local -r call_name='plex-command-caller.zsh' + local -r self_path="${${(%):-%x}:A:h}" + + "${self_path}/${call_name}" "${extn_name}" "${(@v)call_opts}" +} + +main "${@}" diff --git a/bin-available/plex-transcoder.zsh b/bin-available/plex-transcoder.zsh new file mode 100755 index 0000000..8bea200 --- /dev/null +++ b/bin-available/plex-transcoder.zsh @@ -0,0 +1,13 @@ +#!/usr/bin/env zsh + +function main() +{ + local -r extn_name='Plex Transcoder' + local -ra call_opts=("${@}") + local -r call_name='plex-command-caller.zsh' + local -r self_path="${${(%):-%x}:A:h}" + + "${self_path}/${call_name}" "${extn_name}" "${(@v)call_opts}" +} + +main "${@}" diff --git a/bin-available/query-kraken.bash b/bin-available/query-kraken.bash new file mode 100755 index 0000000..ba60833 --- /dev/null +++ b/bin-available/query-kraken.bash @@ -0,0 +1,150 @@ +#!/bin/bash + +## +## This file is part of the `src-run/user-scripts-server` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +# +# output information message +# +function out_info { + printf '[INFO] -- %s\n' "$(printf "${@}")" +} + +# +# output warning message +# +function out_warn { + >&2 printf '[WARN] ## %s\n' "$(printf "${@}")" +} + +# +# output critical error +# +function out_crit { + >&2 printf '[CRIT] !! %s\n' "$(printf "${@}")" +} + +# +# resolve real path of input path +# +function resolve_real_path { + local resolve_path="${1:-}" + local readlink_bin='readlink' + local readlink_opt='-m' + local realpath_bin='realpath' + local realpath_opt='-m' + + if [[ -z ${resolve_path} ]]; then + out_warn 'Failed to resolve real path on empty provided path!' + return + fi + + if readlink_bin="$(which "${readlink_bin}" 2> /dev/null)"; then + ${readlink_bin} ${readlink_opt} "${resolve_path}" + return $? + fi + + if realpath_bin="$(which "${realpath_bin}" 2> /dev/null)"; then + ${realpath_bin} ${realpath_opt} "${resolve_path}" + return $? + fi + + out_warn 'Failed to resolve real path of "%s" (readlink and realpath must both be missing).' "${resolve_path}" + printf '%s' "${resolve_path}" +} + +# +# output usage information +# +function out_usage() { + printf 'Usage: ./%s [OPTIONS]\n' "${_SELF_NAME}" + printf '\t-%s | --%-11s %s\n' f fan-speed 'Output the speed of the radiator fan(s).' + printf '\t-%s | --%-11s %s\n' p pump-speed 'Output the speed of the pump.' + printf '\t-%s | --%-11s %s\n' l liquid-temp 'Output the liquid temperature of the loop.' + printf '\t-%s | --%-11s %s\n' v fw-version 'Output the firmware version of the device controller.' + printf '\t-%s | --%-11s %s\n' h help 'Output this usage information.' + + exit 0 +} + +# +# get raw kraken stats data +# +function get_kraken_stats_data { + echo -n "${_DATA_KBIN}" +} + +# +# get one kraken stats line +# +function get_kraken_stats_line { + local index="${1}" + declare -A STATS + + [[ -z ${index} ]] && return 255 + + while IFS= read -r data; do + STATS[${data%%=*}]="${data#*=}" + done <<< $(get_kraken_stats_data) + + printf '%s\n' "${STATS[${index}]}" +} + +# +# output requested data +# +function main { + local opt="${1}" + + if [[ ${#} -ne 1 ]]; then + out_crit 'Detected invalid number of arguments! Expected 1 but got %d...' ${#} + out_usage + exit 255 + fi + + case "${opt}" in + -f|--fan-speed ) get_kraken_stats_line fan_speed ;; + -p|--pump-speed ) get_kraken_stats_line pump_speed ;; + -l|--liquid-temp ) get_kraken_stats_line liquid_temperature ;; + -v|--fw-version ) get_kraken_stats_line firmware_version ;; + -h|--help ) out_usage ;; + * ) out_crit "Invalid argument: '%s'..." "${opt}"; out_usage ;; + esac +} + +# +# determine real path name of self +# +readonly _SELF_REAL="$(resolve_real_path "${0}")" + +# +# determine real file name of self +# +readonly _SELF_NAME="$(basename "${_SELF_REAL}")" + +# +# determine real directory path of self +# +readonly _SELF_PATH="$(dirname "${_SELF_REAL}")" + +# +# determine real file path to kraken library executable +# +readonly _LIBS_KBIN="$(resolve_real_path "${_SELF_PATH}/../lib/krakenx/bin/colctl")" + +# +# read and format kraken status data +# +readonly _DATA_KBIN="$( + ${_LIBS_KBIN} -s 2> /dev/null \ + | tail -n4 \ + | sed -E 's/^([a-z_]+) ([0-9\.]+)$/\1=\2/' +)" + +main "${@}" diff --git a/bin-available/rsync-run-all.zsh b/bin-available/rsync-run-all.zsh new file mode 100755 index 0000000..cd27adf --- /dev/null +++ b/bin-available/rsync-run-all.zsh @@ -0,0 +1,159 @@ +#!/usr/bin/env zsh + +#function out_text() { printf -- "${@}" } +#function out_line() { out_text "${@}"; out_text '\n' } +#function out_text_type() { out_text '%.04f [ %s ] %s ...' "$(date +%s\.%N)" "${1}" "$(out_text "${@:2}")" } +#function out_line_type() { out_text_type "${@}"; out_text '\n' } +#function out_line_asks() { out_text '%.04f [ %s ] %s? [y\N]: ' "$(date +%s\.%N)" '??' "$(out_text "${@}")" } +#function out_line_info() { out_line_type '--' "${@}" } +#function out_line_note() { out_line_type '##' "${@}" } +#function out_line_warn() { out_line_type '!-' "${@}" } +#function out_line_fail() { out_line_type '!!' "${@}" } + +declare -r UNIX_BEG_SET=("$(date +%s\.%N)") +declare -a UNIX_END_SET=() +declare -r SLEEP_SECOND=20 +declare -r IONICE_CLASS="${1:-0}" +declare -r IONICE_GROUP="${2:-0}" +declare -r BACKUP_PATHS=("${@:3}") +declare -r SRCS_RM_PATH='/pool/' +declare -r DEST_RM_PATH='/tank/pool/' +declare -r LG_ROOT_PATH='/tank/rsync-logs' +declare -a RS_CALL_OPTS=( + '--recursive' + '--verbose' + '--human-readable' + '--progress' + '--links' + #'--copy-unsafe-links' + #'--keep-dirlinks' + '--owner' + '--group' + '--perms' + '--devices' + '--specials' + '--times' + '--force' + '--delete' + '--delete-before' + '--max-delete' '0' + '--ignore-errors' + '--sparse' + '--info' 'progress2' + '--stats' +) + +j=1 +for (( i=1; i<=${#BACKUP_PATHS[@]}; i=i+2 )); do + declare RS_PATH_SRCS="${SRCS_RM_PATH}${BACKUP_PATHS[${i}]/${SRCS_RM_PATH}/}" + + [[ -n ${BACKUP_PATHS[$(( i + 1 ))]} ]] \ + && declare RS_PATH_DEST="${DEST_RM_PATH}${BACKUP_PATHS[$(( i + 1 ))]/${DEST_RM_PATH}/}" \ + || declare RS_PATH_DEST="${DEST_RM_PATH}${RS_PATH_SRCS/${SRCS_RM_PATH}/}" + + declare LG_CALL_PATH="${LG_ROOT_PATH}_$( + sed -E 's/\//-/g' <<< "${BACKUP_PATHS[${i}]/${SRCS_RM_PATH}/}" | sed -E 's/(^-|-$)//g' + )_$( + date +%Y%m%d-%H%M + ).log" + + clear + printf '\n##\n## [date_time] => "%s"\n## [elapsed_s] => "%s"\n## [back_numb] => "%02d / %02d"\n' \ + "$(date)" \ + "$(($(date +%s\.%N) - ${UNIX_BEG_SET[1]}))" \ + "${j}" \ + "$((${#BACKUP_PATHS[@]} / 2))" + + printf '## [nice_io_c] => "%s" (classname: %s)\n' \ + "${IONICE_CLASS}" \ + "$( + case "${IONICE_CLASS}" in + 0) printf 'none' ;; + 1) printf 'realtime' ;; + 2) printf 'best-effort' ;; + 3) printf 'idle' ;; + *) printf 'undefined' ;; + esac + )" + + printf '## [nice_io_g] => "%s" (priority : %s)\n' \ + "${IONICE_GROUP}" \ + "$( + if [[ ${IONICE_CLASS} -ne 1 ]] && [[ ${IONICE_CLASS} -ne 2 ]]; then + printf 'unavailable' + else + case "${IONICE_CLASS}" in + 0|1) printf 'highest' ;; + 2 ) printf 'high' ;; + 3|4) printf 'middle' ;; + 5 ) printf 'low' ;; + 6|7) printf 'lowest' ;; + * ) printf 'undefined' ;; + esac + fi + )" + + printf '## [srcs_path] => "%s" (copy mode: %s)\n' \ + "${RS_PATH_SRCS}" \ + "$( + if [[ ${RS_PATH_SRCS} =~ /$ ]]; then + printf 'src path sub-folders' + else + printf 'src path included' + fi + )" + + printf '## [dest_path] => "%s" (copy mode: %s)\n' \ + "${RS_PATH_DEST}" \ + "$( + if [[ ${RS_PATH_DEST} =~ /$ ]]; then + printf 'src path sub-folders' + else + printf 'src path included' + fi + )" + + printf '## [logs_file] => "%s"\n' \ + "${LG_CALL_PATH}" + + printf '## [call_opts] => "%s"\n##\n\n' \ + "$( + fold --spaces --width=$(($(tput cols) - 20)) <<< "--log-file \"${LG_CALL_PATH}\" ${RS_CALL_OPTS[*]} \"${RS_PATH_SRCS}\" \"${RS_PATH_DEST}\"" \ + | sed -e '2,$s/^/## "/' -e '$!s/[ ]*$/''"/g' + )" + + printf -- '?? Continue using the above enumerated configuration values? [y/N]: ' + + if [[ -n ${RSYNC_NON_INTERACTIVE} ]] && [[ ${RSYNC_NON_INTERACTIVE} -ge 1 ]]; then + printf -- '(automatically continuing in non-interactive mode)\n' + elif ! read -s -q; then + printf -- '(continuing)\n' + fi + + printf -- '\n-- Performing backup in %d seconds ...' \ + "${SLEEP_SECOND}" + + for z in {1..${SLEEP_SECOND}}; do + printf '.' + sleep 1 + done + + printf '\n\n' + + sudo \ + ionice \ + -c "${IONICE_CLASS}" \ + -n "${IONICE_GROUP}" \ + 2> /dev/null \ + rsync \ + --log-file "${LG_CALL_PATH}" \ + "${RS_CALL_OPTS[@]}" \ + "${RS_PATH_SRCS}" \ + "${RS_PATH_DEST}" + + printf -- '\n## Completed operation(s) %d of %d ...\n' \ + "${j}" \ + "$((${#BACKUP_PATHS[@]} / 2))" + + j=$((j + 1)) +done diff --git a/bin-available/rsync-run-set_pool-backup.zsh b/bin-available/rsync-run-set_pool-backup.zsh new file mode 100755 index 0000000..8083777 --- /dev/null +++ b/bin-available/rsync-run-set_pool-backup.zsh @@ -0,0 +1 @@ +/home/rmf/rsync-run.bash 3 0 /pool/backup/ /tank/pool/backup/ diff --git a/bin-available/rsync-run-set_pool-media.zsh b/bin-available/rsync-run-set_pool-media.zsh new file mode 100755 index 0000000..61ba506 --- /dev/null +++ b/bin-available/rsync-run-set_pool-media.zsh @@ -0,0 +1 @@ +/home/rmf/rsync-run.bash 2 0 /pool/media/ diff --git a/bin-available/rsync-run-set_pool-others.zsh b/bin-available/rsync-run-set_pool-others.zsh new file mode 100755 index 0000000..21e72e3 --- /dev/null +++ b/bin-available/rsync-run-set_pool-others.zsh @@ -0,0 +1,70 @@ +#!/usr/bin/env zsh + +declare -a BACK_PATHS=( + '/code/' + '/var/lib/sonarr/' + '/home/ans/' + '/home/linuxbrew/' + '/home/rmf/' + '/home/rto/' + '/home/rtorrent/' + '/home/srl/' + '/home/stream/' +) + +declare -a POOL_BASE_PATH_NAMES=( + 'backups' + 'backup-twoface' + 'cloud' + 'documents' + 'games' + 'google-drive' + 'openvpn-rto' + 'opt' + 'plexmediaserver' + 'projects' + 'repositories' + 'scripts' + 'scripts-rmf' + 'scripts-rto' + 'software' + 'torrent' + 'var' + 'vms' + 'web' +) + +declare -a RSYNC_RUN_OPTS=() + +for p in ${(v)POOL_BASE_PATH_NAMES}; do + declare source_path="/pool/${p}/" + declare target_path="/tank/pool/${p}/" + + RSYNC_RUN_OPTS+=("${source_path}" "${target_path}") +done + +for p in ${(v)BACK_PATHS}; do + declare source_path="$(sed -E 's/\/+/\//g' <<< "${p}")" + declare target_path="/tank/pool/backup-twoface-2205/$(sed -E 's/\//--/g' <<< "${source_path}" | sed -E 's/(^-+|-+$)//g')/" + + RSYNC_RUN_OPTS+=("${source_path}" "${target_path}") +done + +printf -- '##\n## date_time => "%s"\n## path_list => array(\n' \ + "$(date '+%Y-%m-%d %H:%M:%S')" + +i=1 +for p in ${(v)RSYNC_RUN_OPTS}; do + printf -- '## %02i -> "%s"\n' \ + "${i}" \ + "${p}" + i=$((i + 1)) +done + +printf '## ) [%d items]\n##\n' \ + "${#RSYNC_RUN_OPTS[@]}" + +printf -- '--\n-- Press ENTER to continue (use ^C to cancel) ...\n--\n' +read + +RSYNC_NON_INTERACTIVE=1 /home/rmf/rsync-run.bash 2 6 "${(@v)RSYNC_RUN_OPTS}" diff --git a/bin-available/staples-business-cards-downloader.bash b/bin-available/staples-business-cards-downloader.bash new file mode 100755 index 0000000..3600c73 --- /dev/null +++ b/bin-available/staples-business-cards-downloader.bash @@ -0,0 +1,254 @@ +#!/bin/bash + +function absolute_int() { + tr -d - <<< "${1}" 2>/dev/null +} + +function print_txt() { + if [[ $# -gt 0 ]]; then + printf -- "${@}" 2>/dev/null + fi +} + +function print_int() { + echo -e "$(print_txt "${@}")" +} + +function print_nls() { + for i in $(seq 1 "$(absolute_int "${1:-1}")"); do + print_txt '\n' + done +} + +function print_end() { + print_txt "${@}" + print_nls +} + +function cli_style() { + _get @ctl:auto-reset "${@}" +} + +function str_repeat() { + local str="${1}" + local num="${2:-1}" + + for i in $(seq 1 ${num}); do + print_txt "${str}" + done +} + +function resolve_printer_type_name() { + case "${1,,}" in + c|c[a-z]*) print_txt 'crit' ;; + f|f[a-z]*) print_txt 'fail' ;; + e|e[a-z]*) print_txt 'fail' ;; + w|w[a-z]*) print_txt 'warn' ;; + n|n[a-z]*) print_txt 'note' ;; + i|i[a-z]*) print_txt 'info' ;; + d|d[a-z]*) print_txt 'debg' ;; + *) print_txt 'unkn' ;; + esac +} + +function resolve_printer_type_char() { + case "${1}" in + crit) print_txt '!' ;; + fail) print_txt '!' ;; + warn) print_txt '#' ;; + note) print_txt '+' ;; + info) print_txt '-' ;; + debg) print_txt '-' ;; + *) print_txt '=' ;; + esac +} + +function compile_printer_self_name() { + local type="${1}" + local name="${2:-${BASH_SOURCE[0]}}" + local temp + + if ! temp="$(realpath -e "${name}" 2>/dev/null)"; then + temp="$(readlink -e "${name}" 2>/dev/null)" + fi + + cli_style @style:bold @fg:black "$( + basename "${temp:-${name}}" 2>/dev/null || print_txt "${name}" + )" +} + +function compile_printer_time_frac() { + local type="${1}" + local prec="${2:-4}" + local time="$( + print_txt \ + "$(print_txt '%%.0%df' "${prec}")" \ + "$(date +%s\.%N)" + )" + + cli_style @style:bold @fg:black "(${time})" +} + +function compile_printer_defs_type() { + local type="${1}" + + +} + +function compile_printer_defs_char() { + local type="${1}" + local char="$(resolve_printer_type_char "${type}")" + local decs='@fg:white @bg:black @style:bold' + + case "${1}" in + crit) decs='@fg:white @bg:red @style:bold' ;; + fail) decs='@fg:black @bg:red' ;; + warn) decs='@fg:black @bg:yellow' ;; + note) decs='@fg:white @bg:magenta @style:bold ' ;; + info) decs='@fg:white @bg:blue @style:bold ' ;; + debg) decs='@fg:black @bg:white' ;; + esac + + cli_style ${decs} " $(str_repeat "${char}" 3) " +} + +function print_def() { + def_type="$(resolve_printer_type_name "${1}")" + + print_int 'self_name[%s]\n' "$(compile_printer_self_name "${def_type}")" + print_int 'time_frac[%s]\n' "$(compile_printer_time_frac "${def_type}")" + print_int 'defs_type[%s]\n' "$(compile_printer_defs_type "${def_type}")" + print_int 'defs_char[%s]\n' "$(compile_printer_defs_char "${def_type}")" + print_int 'user_text[%s]\n' "$(print_txt "${@:2}")" + print_nls + + print_int '%s %s %s %s %s' \ + "$(compile_printer_self_name "${def_type}")" \ + "$(compile_printer_time_frac "${def_type}")" \ + "$(compile_printer_defs_type "${def_type}")" \ + "$(compile_printer_defs_char "${def_type}")" \ + "$(print_txt "${@:2}")" + + print_nls 2 +} + +function print_def_n() { + print_txt '' +} + +function print_def_info_n() { + print_txt '' +} + +function print_def_fail_n() { + print_txt '' +} + +function make_req_path_norm() { + if [[ ! -d "${1}" ]] && ! mkdir "${1}" &> /dev/null; then + print_txt '! [FAIL] Could not create required path: "%s"\n' "${1}" && return 255 + fi +} + +function make_req_path_dirn() { + make_req_path_norm "$( + dirname "${1}" 2>/dev/null || print_txt "${1}" + )" +} + +function read_file_contents() { + cat "${1}" 2>/dev/null +} + +function line_count_of_file() { + grep -oE ^http <<< "$(read_file_contents "${1}")" 2>/dev/null \ + | wc -l 2>/dev/null +} + +function resolve_get_link() { + sed -E "s/\/[0-9]{3}\//\/${2}\//g" <<< "${1}" 2>/dev/null +} + +function resolve_out_path() { + sed -E "s/https:\/\/splus-phoenix-render.pnimedia.com\/api\/v3\/thumb\/([A-Z]+)\/([^\/]+)\/[0-9]+\/([^\/]+)\/[0-9]{3}\/([A-Z][a-z]+)\.([a-z]+)\?[a-zA-Z]+=([A-Za-z0-9]+)[^\n]+/\1-\2-\3_\4-\6_${2}.\5/g" <<< "${1}" 2>/dev/null +} + +function main() +{ + uri_path="${1:-${HOME}/cards.txt}" + out_root="${2:-${HOME}/downloads-${1:-undefined}/}" + get_wdth="${3:-10240}" + log_path="/tmp/.bash-curl-fail-text_$(sed -E 's/[^a-zA-Z0-9\._-]//g' <<< "${BASH_SOURCE[0]}").log" + + for raw_link in $(read_file_contents "${uri_path}"); do + num_loop="$((${num_loop:-0} + 1))" + get_link="$( + resolve_get_link "${raw_link}" "${get_wdth}" + )" + out_path="${out_root}/$( + resolve_out_path "${raw_link}" "${get_wdth}" + )" + + make_req_path_dirn "${out_path}" || return $? + make_req_path_dirn "${log_path}" || return $? + + print_txt -- '- [%03d/%03d] "%s" --> "%s" ... ' "${num_loop}" "$(line_count_of_file "${uri_path}")" "${get_link}" "${out_path}" + + [[ -f "${out_path}" ]] && print_txt 'SKIP (%s)\n' "exists" && continue + + curl --silent --show-error --output "${out_path}" "${get_link}" && \ + print_txt 'DONE (%s)\n' "$(du -h "${out_path}" | cut -f1)" || \ + print_txt 'FAIL (%s)\n' "$(cat "${out_path}" | paste -sd " " -)" + + purge_file "${log_path}" + done + + return 0 +} + +function unlink_file() { + if [[ -f "${1}" ]] && ! rm "${1}" &>/dev/null; then + print_def_fail_n 'Could not unlink file: "%s"' "${1}" + print_nls + fi +} + +function create_file() { + print_txt '' +} + +# +# internal variables +# +readonly _SELF_PATH="$(dirname "$(readlink -m "${0}")")" + +# +# configuration +# +if [[ -z "${BRIGHT_LIBRARY_PATH}" ]]; then + BRIGHT_LIBRARY_PATH="${_SELF_PATH}/../lib/bright/bright.bash" +fi + +# +# check for required bright library dependency +# +if [[ ! -f "${BRIGHT_LIBRARY_PATH}" ]]; then + print_txt 'Failed to source required dependency: bright-library (%s)\n' \ + "${BRIGHT_LIBRARY_PATH}" + exit 255 +fi + +# +# source bright library dependency +# +source "${BRIGHT_LIBRARY_PATH}" + +#main "${@}" + +print_def crit 'this is %d %sof type "%s"...' 1 'message string' crit +print_def fail 'this is %d %sof type "%s"...' 1 'message string' fail +print_def warn 'this is %d %sof type "%s"...' 1 'message string' warn +print_def note 'this is %d %sof type "%s"...' 1 'message string' note +print_def info 'this is %d %sof type "%s"...' 1 'message string' info +print_def debg 'this is %d %sof type "%s"...' 1 'message string' debg +print_def unkn 'this is %d %sof type "%s"...' 1 'message string' unkn diff --git a/bin-available/stapusardown.bash b/bin-available/stapusardown.bash new file mode 100755 index 0000000..69d78e5 --- /dev/null +++ b/bin-available/stapusardown.bash @@ -0,0 +1,260 @@ +#!/bin/bash + +function absolute_int() { + tr -d - <<< "${1}" 2>/dev/null +} + +function print_txt() { + if [[ $# -gt 0 ]]; then + printf -- "${@}" 2>/dev/null + fi +} + +function print_int() { + echo -ne "$(print_txt "${@}")" +} + +function print_nls() { + for i in $(seq 1 "$(absolute_int "${1:-1}")"); do + print_txt '\n' + done +} + +function print_end() { + print_txt "${@}" + print_nls +} + +function cli_style() { + _get @ctl:auto-reset "${@}" +} + +function str_repeat() { + local str="${1}" + local num="${2:-1}" + + for i in $(seq 1 ${num}); do + print_txt "${str}" + done +} + +function resolve_printer_type_name() { + case "${1,,}" in + c|c[a-z]*) print_txt 'crit' ;; + f|f[a-z]*) print_txt 'fail' ;; + e|e[a-z]*) print_txt 'fail' ;; + w|w[a-z]*) print_txt 'warn' ;; + n|n[a-z]*) print_txt 'note' ;; + i|i[a-z]*) print_txt 'info' ;; + d|d[a-z]*) print_txt 'debg' ;; + *) print_txt 'unkn' ;; + esac +} + +function resolve_printer_type_char() { + case "${1}" in + crit) print_txt '!' ;; + fail) print_txt '!' ;; + warn) print_txt '#' ;; + note) print_txt '+' ;; + info) print_txt '-' ;; + debg) print_txt '-' ;; + *) print_txt '=' ;; + esac +} + +function compile_printer_self_name() { + local type="${1}" + local name="${2:-${BASH_SOURCE[0]}}" + local temp + + if ! temp="$(realpath -e "${name}" 2>/dev/null)"; then + temp="$(readlink -e "${name}" 2>/dev/null)" + fi + + cli_style @style:bold @fg:black "[$( + basename \ + "${temp:-${name}}" \ + "$( + grep -oE '\.[a-z0-9]+$' <<< "${temp:-${name}}" 2>/dev/null\ + )" 2>/dev/null || print_txt "${name}" + )]" +} + +function compile_printer_time_frac() { + local type="${1}" + local prec="${2:-4}" + local time="$( + print_txt \ + "$(print_txt '%%.0%df' "${prec}")" \ + "$(date +%s\.%N)" + )" + + cli_style @style:bold @fg:black "(${time})" +} + +function compile_printer_defs_type() { + local type="${1}" + local decs='@fg:white @bg:black @style:bold' + + case "${1}" in + crit) decs='@fg:white @bg:red' ;; + fail) decs='@fg:black @bg:red' ;; + warn) decs='@fg:black @bg:yellow' ;; + note) decs='@fg:white @bg:magenta @style:bold' ;; + info) decs='@fg:white @bg:blue @style:bold' ;; + debg) decs='@fg:black @bg:white' ;; + esac + + cli_style ${decs} " ${type^^} " +} + +function compile_printer_defs_char() { + local type="${1}" + local char="$(resolve_printer_type_char "${type}")" + local decs='@fg:white' + + case "${1}" in + crit) decs='@fg:red @style:bold' ;; + fail) decs='@fg:red' ;; + warn) decs='@fg:yellow @style:bold' ;; + note) decs='@fg:magenta @style:bold' ;; + info) decs='@fg:blue @style:bold' ;; + debg) decs='@fg:white @style:bold' ;; + esac + + cli_style ${decs} "$(str_repeat "${char}" 3)" +} + +function print_def() { + def_type="$(resolve_printer_type_name "${1}")" + + print_int '%s %s %s %s %s' \ + "$(compile_printer_self_name "${def_type}")" \ + "$(compile_printer_time_frac "${def_type}")" \ + "$(compile_printer_defs_type "${def_type}")" \ + "$(compile_printer_defs_char "${def_type}")" \ + "$(print_txt "${@:2}")" +} + +function print_def_n() { + print_def "${@}" + print_nls +} + +function print_def_info_n() { + print_def_n info "${@}" +} + +function print_def_fail_n() { + print_def_n fail "${@}" +} + +function make_req_path_norm() { + if [[ ! -d "${1}" ]] && ! mkdir "${1}" &> /dev/null; then + print_txt '! [FAIL] Could not create required path: "%s"\n' "${1}" && return 255 + fi +} + +function make_req_path_dirn() { + make_req_path_norm "$( + dirname "${1}" 2>/dev/null || print_txt "${1}" + )" +} + +function read_file_contents() { + cat "${1}" 2>/dev/null +} + +function line_count_of_file() { + grep -oE ^http <<< "$(read_file_contents "${1}")" 2>/dev/null \ + | wc -l 2>/dev/null +} + +function resolve_get_link() { + sed -E "s/\/[0-9]{3}\//\/${2}\//g" <<< "${1}" 2>/dev/null +} + +function resolve_out_path() { + sed -E "s/https:\/\/splus-phoenix-render.pnimedia.com\/api\/v3\/thumb\/([A-Z]+)\/([^\/]+)\/[0-9]+\/([^\/]+)\/[0-9]{3}\/([A-Z][a-z]+)\.([a-z]+)\?[a-zA-Z]+=([A-Za-z0-9]+)[^\n]+/\1-\2-\3_\4-\6_${2}.\5/g" <<< "${1}" 2>/dev/null +} + +function main() +{ + uri_path="${1:-${HOME}/cards.txt}" + out_root="${2:-${HOME}/downloads-${1:-undefined}/}" + get_wdth="${3:-10240}" + log_path="/tmp/.bash-curl-fail-text_$(sed -E 's/[^a-zA-Z0-9\._-]//g' <<< "${BASH_SOURCE[0]}").log" + + for raw_link in $(read_file_contents "${uri_path}"); do + num_loop="$((${num_loop:-0} + 1))" + get_link="$( + resolve_get_link "${raw_link}" "${get_wdth}" + )" + out_path="${out_root}/$( + resolve_out_path "${raw_link}" "${get_wdth}" + )" + + make_req_path_dirn "${out_path}" || return $? + make_req_path_dirn "${log_path}" || return $? + + print_txt -- '- [%03d/%03d] "%s" --> "%s" ... ' "${num_loop}" "$(line_count_of_file "${uri_path}")" "${get_link}" "${out_path}" + + [[ -f "${out_path}" ]] && print_txt 'SKIP (%s)\n' "exists" && continue + + curl --silent --show-error --output "${out_path}" "${get_link}" && \ + print_txt 'DONE (%s)\n' "$(du -h "${out_path}" | cut -f1)" || \ + print_txt 'FAIL (%s)\n' "$(cat "${out_path}" | paste -sd " " -)" + + purge_file "${log_path}" + done + + return 0 +} + +function unlink_file() { + if [[ -f "${1}" ]] && ! rm "${1}" &>/dev/null; then + print_def_fail_n 'Could not unlink file: "%s"' "${1}" + print_nls + fi +} + +function create_file() { + print_txt '' +} + +# +# internal variables +# +readonly _SELF_PATH="$(dirname "$(readlink -m "${0}")")" + +# +# configuration +# +if [[ -z "${BRIGHT_LIBRARY_PATH}" ]]; then + BRIGHT_LIBRARY_PATH="${_SELF_PATH}/../lib/bright/bright.bash" +fi + +# +# check for required bright library dependency +# +if [[ ! -f "${BRIGHT_LIBRARY_PATH}" ]]; then + print_txt 'Failed to source required dependency: bright-library (%s)\n' \ + "${BRIGHT_LIBRARY_PATH}" + exit 255 +fi + +# +# source bright library dependency +# +source "${BRIGHT_LIBRARY_PATH}" + +#main "${@}" + +print_def_n crit 'this is %d %s of type "%s"...' 1 'message string' crit +print_def_n fail 'this is %d %s of type "%s"...' 1 'message string' fail +print_def_n warn 'this is %d %s of type "%s"...' 1 'message string' warn +print_def_n note 'this is %d %s of type "%s"...' 1 'message string' note +print_def_n info 'this is %d %s of type "%s"...' 1 'message string' info +print_def_n debg 'this is %d %s of type "%s"...' 1 'message string' debg +print_def_n unkn 'this is %d %s of type "%s"...' 1 'message string' unkn diff --git a/bin-available/start-glances.bash b/bin-available/start-glances.bash new file mode 100755 index 0000000..c937ebf --- /dev/null +++ b/bin-available/start-glances.bash @@ -0,0 +1,3 @@ +#!/bin/bash + +sudo glances 2> /dev/null diff --git a/bin-available/zfs-scrub-watch.zsh b/bin-available/zfs-scrub-watch.zsh new file mode 100755 index 0000000..26efd1b --- /dev/null +++ b/bin-available/zfs-scrub-watch.zsh @@ -0,0 +1,289 @@ +#!/usr/bin/env zsh + +function out_text() +{ + printf -- "${@}" +} + +function out_line() +{ + out_text "${1}\n" "${@:2}" +} + +function get_self_name() +{ + out_text '%s' "${$( + readlink -e -n -- "${(%):-%x}" + ):t:r}" +} + +function get_type_char() +{ + case "${1}" in + 'warn') out_text '%s' '##' ;; + 'fail') out_text '%s' '!!' ;; + 'info'|*) out_text '%s' '->' ;; + esac +} + +function out_type_pref() +{ + local type_name="${1}" + local unix_time="$(date +%s\.%N)" + + out_text '(%s @ %.02f) %s %s ' "$(get_self_name)" "${unix_time}" "${type_name:l}" "$(get_type_char "${type_name:l}")" +} + +function out_type_text() +{ + local type="${1}" + local text="${2}" + local -a args=("${@:3}") + + out_type_pref "${type}" + out_text "${text}" "${(@v)args}" +} + +function out_type_line() +{ + out_type_text "${1}" "${2}" "${@:3}" + out_line +} + +function resolve_log_file() +{ + local pool_ident="${1}" + local temp_tplts="zpool-scrub-status_${pool_ident}-XXXXXX.log" + + mktemp -u -t "${temp_tplts}" 2> /dev/null || \ + out_text '%s' "${temp_tplts}" +} + +function resolve_tic_time() +{ + local sleep_time="${SLEEP_TIME:-20}" + + out_text '%d' "${sleep_time}" +} + +function resolve_zfs_stat() +{ + local pool_ident="${1}" + + zpool status "${pool_ident}" 2>&1 +} + +function cleanup_time_string() +{ + sed -E 's/0 (days|hrs|mins), //g' <<< "${1:-$(</dev/stdin)}" \ + | sed -E 's/\b1 (day|hour|min|sec)s\b/1 \1/g' \ + | sed -E 's/\b0*([0-9]+\.[0-9]+)/\1/g' \ + | sed -E 's/\b([0-9]+\.[0-9][1-9])[0]{1}\b/\1/g' \ + | sed -E 's/\b([0-9]+\.[0-9])[0]{2}\b/\1/g' +} + +function cleanup_line_finals() +{ + sed -E 's/([^,]{1}.{1})\b[0]+\.[0]+[ ]+(hrs?)/\1unknown \2/g' <<< "${1:-$(</dev/stdin)}" \ + | sed -E 's/\b0[A-Z] repaired/no repairs/g' +} + +function is_scrub_in_progress() +{ + if ! grep 'scan: scrub in progress' <<< "$(resolve_zfs_stat "${1}")" &> /dev/null; then + return 1 + fi +} + +function resolve_scrub_size() +{ + grep -E '[0-9\.]+[A-Z] scanned at [0-9\.]+.{,3}' <<< "${1}" \ + | sed -E 's/[ \t]*([0-9\.]+[A-Z]) scanned at ([0-9\.]+[A-Z]\/[a-z]), ([0-9\.]+[A-Z]) [^0-9]+ ([0-9\.]+[A-Z]\/[a-z]), ([0-9\.]+[A-Z]).*/\3 of \5 @ \2/g' \ + | cleanup_time_string +} + +function resolve_scrub_repr() +{ + grep -oE '[0-9\.]+[A-Z] repaired' <<< "${1}" \ + | grep -oE '[0-9\.]+[A-Z]' +} + +function resolve_scrub_time() +{ + local hours=0 + local -a parts=("$( + grep -E '[0-9\.]+% done, .+' <<< "${1}" \ + | grep -oE '[0-9]+ days?' \ + | grep -oE '[0-9]+' + )" "${(@s/:/)$( + grep -E '[0-9\.]+% done, .+' <<< "${1}" \ + | grep -oE '[0-9]+:[0-9]+:[0-9]+' + )}") + + if [[ "${#parts[@]}" -ne 4 ]]; then + parts=(0 0 0 0) + fi + + out_text '%d days, %02d.%03d hrs' "${parts[1]}" "${parts[2]}" "${$( + bc <<< "scale=6; ${parts[3]} / 60" | grep -oE '[0-9]*$' + ):0:3}" | cleanup_time_string +} + +function resolve_scrub_elap() +{ + local now="$(date +%s)" + local beg="$( + date --date="$( + grep -oE 'in progress since .+' <<< "${1}" 2> /dev/null \ + | sed -E 's/in progress since //g' \ + | sed -E 's/[ ]+/ /g' + )" +%s 2> /dev/null || out_text '%d' "${now}" + )" + local len="$((${now} - ${beg}))" + local day="$((${len} / 86400))" + + if [[ "${day}" -gt 0 ]]; then + len="$((len - (day * 86400)))" + fi + + local -a hrs=("${(@s/./)$( + awk '{printf "%.03f", $1 / 3600}' <<< "${len}" + )}") + + out_text '%d days, %02d.%03d hrs' "${day}" "${hrs[1]}" "${hrs[2]:0:3}" | cleanup_time_string +} + +function resolve_scrub_perc() +{ + local -a percent_set=("${(@s/./)$( + grep -E '[0-9\.]+% done, .+' <<< "${1}" 2> /dev/null \ + | grep -E -o '[0-9\.]+%' \ + | sed -E 's/%//g' + )}") + + if [[ "${#percent_set[@]}" -ne 2 ]]; then + percent_set=("${(@s/./)0.00}") + fi + + out_text '%02d.%02d%%' "${percent_set[1]}" "${percent_set[2]}" +} + +function resolve_pool_names() +{ + local -a finals_named=() + local -a select_names=() + local -a passed_names=("${@}") + local -a online_names=("${(@f)$( + zpool list -H | awk '{print $1}' + )}") + + for p in "${(@v)passed_names}"; do + for o in "${(@v)online_names}"; do + [[ "${p}" == "${o}" ]] && select_names+=("${o}") + done + done + + if [[ "${#select_names[@]}" -eq 0 ]]; then + select_names=("${(@v)online_names}") + fi + + for p in "${(@v)select_names}"; do + is_scrub_in_progress "${p}" \ + && finals_named+=("${p}") + done + + out_line '%s' "${(@v)finals_named}" +} + +function resolve_pool_max_len() +{ + local max_len=0 + + for v in "${@}"; do + [[ "${#v}" -gt "${max_len}" ]] && max_len="${#v}" + done + + out_text '%d' "${max_len}" +} + +function do_sleep_time() +{ + local sleep_time="${1}" + + out_text ' ...' + + for i in {1..${sleep_time}}; do + sleep 1 + #[[ $((${i} % 2)) -eq 0 ]] && out_text '.' + done + + out_line +} + +function get_scrub_stats_for_pool() +{ + local pool_ident_name="${1}" + local pool_ident_mlen="${2}" + local pool_stats_text="$(resolve_zfs_stat "${pool_ident_name}")" + + if ! is_scrub_in_progress "${pool_ident_name}"; then + return 1 + fi + + local pool_scrub_size="$(resolve_scrub_size "${pool_stats_text}")" + local pool_scrub_time="$(resolve_scrub_time "${pool_stats_text}")" + local pool_scrub_elap="$(resolve_scrub_elap "${pool_stats_text}")" + local pool_scrub_perc="$(resolve_scrub_perc "${pool_stats_text}")" + local pool_scrub_repr="$(resolve_scrub_repr "${pool_stats_text}")" + + out_type_text 'info' '[ %'${pool_ident_mlen}'s: %s ] scanned %s (%s repaired); %s remaining (%s elapsed)' \ + "${pool_ident_name}" \ + "${pool_scrub_perc}" \ + "${pool_scrub_size}" \ + "${pool_scrub_repr}" \ + "${pool_scrub_time}" \ + "${pool_scrub_elap}" \ + | cleanup_line_finals + + return 0 +} + +function get_scrub_stats_all_asked() +{ + local -a pool_names=("${(@f)$(resolve_pool_names "${@}")}") + local temp_stats + + for p in "${(@v)pool_names}"; do + if temp_stats="$(get_scrub_stats_for_pool "${p}" "$( + resolve_pool_max_len "${(@v)pool_names}" + )")"; then out_line '%s' "${temp_stats}"; fi + done +} + +function out_scrub_stats() +{ + local -a pool_names=("${(@f)$(resolve_pool_names "${@}")}") + local -a call_lines=("${(@f)$(get_scrub_stats_all_asked "${@}")}") + + if [[ ${#call_lines[@]} -eq 0 ]]; then + out_type_text 'warn' 'no pools are activly scrubbing' + do_sleep_time "$(resolve_tic_time)" + return + fi + + for i in {1..${#call_lines[@]}}; do + out_text '%s' "${call_lines[${i}]}" + [[ "${i}" -lt "${#call_lines[@]}" ]] && out_line + done + + do_sleep_time "$(resolve_tic_time)" +} + +function main() +{ + while true; do + out_scrub_stats "${@}" + done +} + +main "${@}" diff --git a/bin-enabled/afc b/bin-enabled/afc new file mode 120000 index 0000000..19d2be5 --- /dev/null +++ b/bin-enabled/afc @@ -0,0 +1 @@ +../bin-available/afc.bash \ No newline at end of file diff --git a/bin-enabled/build-ffmpeg b/bin-enabled/build-ffmpeg new file mode 120000 index 0000000..f716460 --- /dev/null +++ b/bin-enabled/build-ffmpeg @@ -0,0 +1 @@ +../bin-available/build-ffmpeg.zsh \ No newline at end of file diff --git a/bin-enabled/deb-install b/bin-enabled/deb-install new file mode 120000 index 0000000..77c6aad --- /dev/null +++ b/bin-enabled/deb-install @@ -0,0 +1 @@ +../bin-available/deb-install.bash \ No newline at end of file diff --git a/bin-enabled/ffmpeg-verify-videos.backup-20230226-2.zsh b/bin-enabled/ffmpeg-verify-videos.backup-20230226-2.zsh new file mode 100644 index 0000000..e494349 --- /dev/null +++ b/bin-enabled/ffmpeg-verify-videos.backup-20230226-2.zsh @@ -0,0 +1,145 @@ +#!/usr/bin/env zsh + +FFMPEG_BIN='/opt/ffmpeg-sources/bin/ffmpeg' +FFPRBE_BIN='/opt/ffmpeg-sources/bin/ffprobe' +MDINFO_BIN="$(command -v mediainfo)" + +function pft() +{ + printf -- "${@}" 2> /dev/null +} + +function pfl() +{ + pft "${1}\n" "${@:2}" +} + +function get_audio_track() +{ + local video_file="${1}" + + "${FFPRBE_BIN}" "${video_file}" 2>&1 \ + | grep Stream 2> /dev/null \ + | grep Audio 2> /dev/null \ + | grep -oE '[0-9]:[0-9]' 2> /dev/null \ + | head -n1 2> /dev/null + + return "${?}" +} + +function get_log_file() +{ + local item_file="${1}" + local logs_path="${2}" + local find_path="${3}" + + local item_relt="${item_file/${find_path}\//}" + local logs_file="${logs_path}/$(sed -E 's/\//___/g' <<< "${item_relt}" 2> /dev/null).log" + + pft '%s' "${logs_file}" +} + +function check_video_logs() +{ + local check_file="${1}" + local -a goods_list=( + '^[0-9]+ frames successfully decoded, 0 decoding errors$' + ) + local -a error_list=( + '[eE]rror' + 'Invalid data' + 'does not contain any stream' + 'could not find sync byte' + 'Error while decoding stream' + 'non-existing PPS [0-9]+ referenced' + 'At least one output file must be specified' + ) + + for search in "${(@v)goods_list}"; do + if grep -E '('"${search}"')' "${check_file}" &> /dev/null; then + return 0 + fi + done + + for search in "${(@v)error_list}"; do + if grep -E '('"${search}"')' "${check_file}" &> /dev/null; then + return 1 + fi + done + + return 0 +} + +function check_video_file() +{ + local video_file="${1}" + local check_file="$(get_log_file "${1}" "${2}" "${3}")" + local audio_track='' + local -a ffmpeg_opts=( + '-v' 'error' + '-i' "${video_file}" + '-f' 'null' + ) + + if audio_track="$(get_audio_track "${video_file}")"; then + ffmpeg_opts+=('-map' "${audio_track}") + fi + + if [[ -e "${check_file}" ]] && [[ ! -f "${check_file}" ]]; then + pfl '[FAIL:SETUP(A)]' + return 1 + fi + + if ! rm -f "${check_file}" &> /dev/null || ! touch "${check_file}"; then + pfl '[FAIL:SETUP(B)]' + return 1 + fi + + #"${FFMPEG_BIN}" ${(v)ffmpeg_opts} - 2>&1 | tee "${check_file}" &> /dev/null + #echo "CALL[ ( \"${FFMPEG_BIN}\" ""${(@v)ffmpeg_opts}"" '-' 2>&1 ) > \"${check_file}\" ]" + + if ! ( "${FFMPEG_BIN}" "${(@v)ffmpeg_opts}" '-' 2>&1 ) > "${check_file}"; then + pfl '[FAIL]' + return 1 + fi + + if ! check_video_logs "${check_file}"; then + pfl '[FAIL]' + return 1 + fi + + if ! rm -f "${check_file}" 2> /dev/null; then + pfl '[OKAY:ERROR(RM)]' + return 1 + fi + + pfl '[OKAY]' +} + +function main() +{ + local find_path="${1}" + local logs_path="$( + pft '%s/.checks' "${find_path}" + )" + + if ! [[ -d "${find_path}" ]]; then + pfl 'ERROR: Invalid input path of "%s"' "${find_path}" + return 1 + fi + + if ! mkdir -p "${logs_path}"; then + pfl 'ERROR: Unable to create results path of "%s"' "${logs_path}" + return 1 + fi + + find "${find_path}" -type f | while read -r file; do + if mediainfo "${file}" | grep '^Video$' &> /dev/null; then + pft 'Processing video: "%s" ... ' "${file/${find_path}\//}" + check_video_file "${file}" "${logs_path}" ${find_path} + fi + done +} + +main "${@}" + diff --git a/bin-enabled/ffmpeg-verify-videos.backup-20230226.zsh b/bin-enabled/ffmpeg-verify-videos.backup-20230226.zsh new file mode 100644 index 0000000..dfc0581 --- /dev/null +++ b/bin-enabled/ffmpeg-verify-videos.backup-20230226.zsh @@ -0,0 +1,103 @@ +#!/usr/bin/env zsh + +FFMPEG_BIN='/opt/ffmpeg-sources/bin/ffmpeg' +FFPRBE_BIN='/opt/ffmpeg-sources/bin/ffprobe' +MDINFO_BIN="$(command -v mediainfo)" + +function get_audio_track() +{ + local video_file="${1}" + + "${FFPRBE_BIN}" "${video_file}" 2>&1 \ + | grep Stream \ + | grep Audio \ + | grep -oE '[0-9]:[0-9]' \ + | head -n1 + + return "${?}" +} + +function get_log_file() +{ + local item_file="${1}" + local logs_path="${2}" + local find_path="${3}" + local item_relt="${item_file/${find_path}\//}" + local logs_file="${logs_path}/$(sed -E 's/\//___/g' <<< "${item_relt}").log" + + printf -- '%s' "${logs_file}" +} + +function check_video_logs() +{ + local check_file="${1}" + local -a check_list=( + '[eE]rror' + 'Invalid data' + 'does not contain any stream' + 'could not find sync byte' + 'Error while decoding stream' + 'non-existing PPS [0-9]+ referenced' + 'At least one output file must be specified' + ) + + for c in "${(@v)check_list}"; do + if grep -E '('"${c}"')' "${check_file}" &> /dev/null; then + return 1 + fi + done + + return 0 +} + +function check_video_file() +{ + local video_file="${1}" + local check_file="$(get_log_file "${1}" "${2}" "${3}")" + local audio_track='' + local -a ffmpeg_opts=( + '-v' 'error' + '-i' "${video_file}" + '-f' 'null' + ) + + if audio_track="$(get_audio_track "${video_file}")"; then + ffmpeg_opts+=('-map' "${audio_track}") + fi + + sudo rm "${check_file}" &> /dev/null + touch "${check_file}" + + "${FFMPEG_BIN}" "${(@v)ffmpeg_opts}" - > "${check_file}" 2>&1 + + if ! check_video_logs "${check_file}"; then + printf -- '[FAIL]\n' + else + printf -- '[OKAY]\n' + rm "${check_file}" + fi +} + +function main() +{ + local find_path="${1}" + local logs_path="$(printf -- '%s/.checks' "${find_path}")" + + if ! [[ -d "${find_path}" ]]; then + printf -- 'ERROR: Invalid input path of "%s"\n' "${find_path}" + exit 1 + fi + + if ! mkdir -p "${logs_path}"; then + printf -- 'ERROR: Unable to create results path of "%s"\n' "${logs_path}" + fi + + find "${find_path}" -type f | while read -r file; do + if mediainfo "${file}" | grep '^Video$' &> /dev/null; then + printf 'Processing video: "%s" ... ' "${file/${find_path}\//}" + check_video_file "${file}" "${logs_path}" ${find_path} + fi + done +} + +main "${@}" diff --git a/bin-enabled/ffmpeg-verify-videos.zsh b/bin-enabled/ffmpeg-verify-videos.zsh new file mode 100644 index 0000000..e4c0f48 --- /dev/null +++ b/bin-enabled/ffmpeg-verify-videos.zsh @@ -0,0 +1,186 @@ +#!/usr/bin/env zsh + +FFMPEG_BIN='/opt/ffmpeg-sources/bin/ffmpeg' +FFPRBE_BIN='/opt/ffmpeg-sources/bin/ffprobe' +MDINFO_BIN="$(command -v mediainfo)" + +function pft() +{ + printf -- "${@}" 2> /dev/null +} + +function pfl() +{ + pft "${1}\n" "${@:2}" +} + +function get_audio_track() +{ + local video_file="${1}" + + export NO_COLOR=1 + export AV_LOG_FORCE_NOCOLOR=1 + + "${FFPRBE_BIN}" "${video_file}" 2>&1 \ + | grep 'Stream' 2> /dev/null \ + | grep 'Audio' 2> /dev/null \ + | grep -oE '[0-9]:[0-9]' 2> /dev/null \ + | head -n1 2> /dev/null + + return "${?}" +} + +function get_log_file() +{ + local item_file="${1}" + local logs_path="${2}" + local find_path="${3}" + + local item_relt="${item_file/${find_path}\//}" + local logs_file="${logs_path}/$( + sed -E 's/\//___/g' <<< "${item_relt:-.checks.log}" 2> /dev/null + ).log" + + pft '%s' "${logs_file}" +} + +function check_video_logs() +{ + local check_file="${1}" + local -a goods_list=( + '\b0 decoding errors' + ) + local -a error_list=( + 'error number -?[0-9]+ occurred' + 'invalid data' + 'does not contain any stream' + 'could not find sync byte' + 'error while decoding stream' + 'non-existing PPS [0-9]+ referenced' + 'at least one output file must be specified' + 'error' + ) + + for search in "${(@v)goods_list}"; do + if grep -i -E '('"${search}"')' "${check_file}" &> /dev/null; then + return 0 + fi + done + + for search in "${(@v)error_list}"; do + if grep -i -E '('"${search}"')' "${check_file}" &> /dev/null; then + return 1 + fi + done + + return 0 +} + +function get_ffmpeg_opts() +{ + local video_file_path="${1}" + local video_audio_map='' + local -a ffmpeg_opts_beg=( + '-nostdin' + '-v' 'error' + '-i' "${video_file_path}" + ) + local -a ffmpeg_opts_end=( + '-f' 'null' + ) + + if video_audio_map="$(get_audio_track "${video_file_path}")"; then + ffmpeg_opts_beg+=( + '-map' "${video_audio_map}" + ) + fi + + for v in "${(@v)ffmpeg_opts_beg}" "${(@v)ffmpeg_opts_end}"; do + pfl '%s' "${v}" + done +} + +function check_video_file() +{ + local video_file="${1}" + local check_file="$(get_log_file "${1}" "${2}" "${3}")" + local -a ffmpeg_opts=("${(@f)$( + get_ffmpeg_opts "${video_file}" + )}") + + for v in "${(@v)ffmpeg_opts}"; do + pfl 'ARG[%s]' "${v}" + done + + return + + if [[ -e "${check_file}" ]] && [[ ! -f "${check_file}" ]]; then + pfl '[FAIL:INIT(FILE)]' + return 1 + fi + + if ! rm --interactive=never -f "${check_file}" &> /dev/null || ! touch "${check_file}"; then + pfl '[FAIL:INIT(MAKE)]' + return 1 + fi + + #"${FFMPEG_BIN}" ${(v)ffmpeg_opts} - 2>&1 | tee "${check_file}" &> /dev/null + #echo "CALL[ ( \"${FFMPEG_BIN}\" ""${(@v)ffmpeg_opts}"" '-' 2>&1 ) > \"${check_file}\" ]" + + export NO_COLOR=1 + export AV_LOG_FORCE_NOCOLOR=1 + + echo -n "[CALL:\"${FFMPEG_BIN}\" ""${(@v)ffmpeg_opts}"" '-' &> \"${check_file}\"]" + + if ! "${FFMPEG_BIN}" "${(@v)ffmpeg_opts}" '-' &> "${check_file}"; then + pfl '[FAIL:CALL]' + return 1 + fi + + if ! sync "${check_file}" &> /dev/null; then + pfl '[FAIL:LOGS(SYNC)]' + return 1 + fi + + sleep 0.5 + + if ! check_video_logs "${check_file}"; then + pfl '[FAIL:LOGS(TEXT)]' + return 1 + fi + + #if ! rm --interactive=never -f "${check_file}" 2> /dev/null; then + # pfl '[OKAY:WARN(RM)]' + # return 1 + #fi + + pfl '[OKAY]' +} + +function main() +{ + local find_path="${1}" + local logs_path="$( + pft '%s/.checks' "${find_path}" + )" + + if ! [[ -d "${find_path}" ]]; then + pfl 'ERROR: Invalid input path of "%s"' "${find_path}" + return 1 + fi + + if ! mkdir -p "${logs_path}"; then + pfl 'ERROR: Unable to create results path of "%s"' "${logs_path}" + return 1 + fi + + find "${find_path}" -type f | while read -r file; do + if mediainfo "${file}" | grep '^Video$' &> /dev/null; then + pft 'Processing video: "%s" ... ' "${file/${find_path}\//}" + check_video_file "${file}" "${logs_path}" ${find_path} + fi + done +} + +main "${@}" + diff --git a/bin-enabled/ffmpeg-verify-videos.zsh~ b/bin-enabled/ffmpeg-verify-videos.zsh~ new file mode 100644 index 0000000..0291fd4 --- /dev/null +++ b/bin-enabled/ffmpeg-verify-videos.zsh~ @@ -0,0 +1,103 @@ +#!/usr/bin/env zsh + +FFMPEG_BIN='/opt/ffmpeg-sources/bin/ffmpeg' +FFPRBE_BIN='/opt/ffmpeg-sources/bin/ffprobe' +MDINFO_BIN="$(command -v mediainfo)" + +function get_audio_track() +{ + local video_file="${1}" + + "${FFPRBE_BIN}" "${video_file}" 2>&1 \ + | grep Stream \ + | grep Audio \ + | grep -oE '[0-9]:[0-9]' \ + | head -n1 + + return "${?}" +} + +function get_log_file() +{ + local item_file="${1}" + local logs_path="${2}" + local find_path="${3}" + local item_relt="${item_file/${find_path}\//}" + local logs_file="${logs_path}/$(sed -E 's/\//___/g' <<< "${item_relt}").log" + + printf -- '%s' "${logs_file}" +} + +function check_video_logs() +{ + local check_file="${1}" + local -a check_list=( + '[eE]rror' + 'Invalid data' + 'does not contain any stream' + 'could not find sync byte' + 'Error while decoding stream' + 'non-existing PPS [0-9]+ referenced' + 'At least one output file must be specified' + ) + + for c in ${(v)check_list}; do + if grep -E '('"${c}"')' "${check_file}" &> /dev/null; then + return 1 + fi + done + + return 0 +} + +function check_video_file() +{ + local video_file="${1}" + local check_file="$(get_log_file "${1}" "${2}" "${3}")" + local audio_track='' + local -a ffmpeg_opts=( + '-v' 'error' + '-i' "${video_file}" + '-f' 'null' + ) + + if audio_track="$(get_audio_track "${video_file}")"; then + ffmpeg_opts+=('-map' "${audio_track}") + fi + + sudo rm "${check_file}" &> /dev/null + touch "${check_file}" + + "${FFMPEG_BIN}" "${(@v)ffmpeg_opts}" - > "${check_file}" 2>&1 + + if ! check_video_logs "${check_file}"; then + printf -- '[FAIL]\n' + else + printf -- '[OKAY]\n' + rm "${check_file}" + fi +} + +function main() +{ + local find_path="${1}" + local logs_path="$(printf -- '%s/.checks' "${find_path}")" + + if ! [[ -d "${find_path}" ]]; then + printf -- 'ERROR: Invalid input path of "%s"\n' "${find_path}" + exit 1 + fi + + if ! mkdir -p "${logs_path}"; then + printf -- 'ERROR: Unable to create results path of "%s"\n' "${logs_path}" + fi + + find "${find_path}" -type f | while read -r file; do + if mediainfo "${file}" | grep '^Video$' &> /dev/null; then + printf 'Processing video: "%s" ... ' "${file/${find_path}\//}" + check_video_file "${file}" "${logs_path}" ${find_path} + fi + done +} + +main "${@}" diff --git a/bin-enabled/find-duplicate-files-in-path b/bin-enabled/find-duplicate-files-in-path new file mode 120000 index 0000000..e7ccbb2 --- /dev/null +++ b/bin-enabled/find-duplicate-files-in-path @@ -0,0 +1 @@ +../bin-available/find-duplicates.zsh \ No newline at end of file diff --git a/bin-enabled/glances b/bin-enabled/glances new file mode 120000 index 0000000..b9cad2c --- /dev/null +++ b/bin-enabled/glances @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/glances \ No newline at end of file diff --git a/bin-enabled/glances-cpuinfo b/bin-enabled/glances-cpuinfo new file mode 120000 index 0000000..1e1207c --- /dev/null +++ b/bin-enabled/glances-cpuinfo @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/glances-cpuinfo \ No newline at end of file diff --git a/bin-enabled/glances-defaults b/bin-enabled/glances-defaults new file mode 120000 index 0000000..05427a5 --- /dev/null +++ b/bin-enabled/glances-defaults @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/glances-defaults \ No newline at end of file diff --git a/bin-enabled/glances-install b/bin-enabled/glances-install new file mode 120000 index 0000000..1606299 --- /dev/null +++ b/bin-enabled/glances-install @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/glances-install \ No newline at end of file diff --git a/bin-enabled/glances-remove b/bin-enabled/glances-remove new file mode 120000 index 0000000..97a2b14 --- /dev/null +++ b/bin-enabled/glances-remove @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/glances-remove \ No newline at end of file diff --git a/bin-enabled/glances-wifi b/bin-enabled/glances-wifi new file mode 120000 index 0000000..9c71fa5 --- /dev/null +++ b/bin-enabled/glances-wifi @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/glances-wifi \ No newline at end of file diff --git a/bin-enabled/ip-info~ b/bin-enabled/ip-info~ new file mode 100755 index 0000000..348dcba --- /dev/null +++ b/bin-enabled/ip-info~ @@ -0,0 +1,384 @@ +#!/bin/bash + +## +## This file is part of the `src-run/user-scripts-server` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +# +# do not suppress errors by default +# +IP_INFO_OUTPUT_ERROR_SUPPRESS=0 + +# +# resolve the script name +# +function get_script_name() +{ + basename "${BASH_SOURCE}" +} + +# +# output new line +# +function write_newline() +{ + printf '\n' +} + +# +# output error message to stderr +# +function write_error() +{ + local message="${1}" + local do_exit="${2:--1}" + + if [[ ${IP_INFO_OUTPUT_ERROR_SUPPRESS} -ne 1 ]]; then + printf '[ERROR] %s\n' "${message}" >&2 + fi + + if [[ ${do_exit} -ne -1 ]]; then + exit ${do_exit} + fi +} + +# +# output script usage information +# +function write_usage() +{ + printf 'Usage:\n ./%s ARGUMENTS [INTERFACE_NAME]\n\nArguments:\n' "$(get_script_name)" + printf ' -i --interface=NAME specify one or more interface names\n' + printf ' -l --list list information for all resolvable interfaces\n' + printf ' -6 --ipv6 resolve the IP version 6 address\n' + printf ' -r --remote resolve the remote IP address (only supports IPv4)\n' + printf ' -c --no-remote-cache disable caching of remote IP address\n' + printf ' -m --minimal output minimal information (IP only)\n' + printf ' -q --minimal-quiet output minimal information (IP only) and ignore any errors\n' + printf ' -V --verbose output verbose information (IP, scope, level, and interface)\n' + printf ' -h --help output this help information\n' + printf ' -v --version output the version information\n' +} + +# +# resolve the local ipv4 address +# +function get_address_local_v6() +{ + local interface="${1}" + local address=$(ip -6 -br addr show ${interface} 2> /dev/null | grep -E -o '[a-f0-9]+::([a-f0-9]+:?)+/[0-9]+' 2> /dev/null) + + if [[ ${PIPESTATUS[0]} -eq 0 ]]; + then + echo "${address}" + fi +} + +# +# resolve the local ipv6 address +# +function get_address_local_v4() +{ + local interface="${1}" + local address=$(ip -4 -br addr show $interface 2> /dev/null | grep -E -o '(UNKNOWN|UP|DOWN)\s+[0-9]+\.([0-9]+\.?)+' 2> /dev/null | awk '{print $2}' 2> /dev/null) + + if [[ ${PIPESTATUS[0]} -eq 0 ]]; + then + echo "${address}" + fi +} + +# +# checks if a cache file is written to disk +# +function is_cache_file_written() +{ + local file="${1}" + + [[ -f "${file}" ]] && echo 1 || echo 0 +} + +# +# checks if a cache file is "fresh" (not expired) +# +function is_cache_file_fresh() +{ + local file="${1}" + local time=$(date +%s) + + [[ $(is_cache_file_written "${file}") -eq 1 ]] && \ + [[ $((${time} - $(stat -c %Y "${file}" 2> /dev/null || echo 300))) -lt 300 ]] && \ + echo 1 || \ + echo 0 +} + +# +# prune stale cache files by removing them +# +function prune_stale_cache_files() +{ + local path="${1}" + + find "${path}" -name "*.cache" -print0 2> /dev/null | while read -d $'\0' file + do + if [[ $(is_cache_file_fresh "${file}") -eq 0 ]]; then + rm "${file}" 2> /dev/null + fi + done +} + +# +# resolve the remote address from cache +# +function get_cached_remote_address() +{ + local full="${1}" + local path="$(dirname "${full}")" + local file="$(basename "${full}")" + + if [[ ! -d "${path}" ]]; then + mkdir -p "${path}" + + if [[ $? -ne 0 ]]; then + return + fi + fi + + prune_stale_cache_files "${path}" + + if [[ $(is_cache_file_fresh "${full}") -eq 1 ]]; then + cat "${full}" 2> /dev/null + fi +} + +# +# assign the remote address from cache +# +function set_cached_remote_address() +{ + local file="${1}" + local address_r="${2}" + + echo "${address_r}" > "${file}" 2> /dev/null +} + +# +# resolve the remote address +# +function get_address_remote() +{ + local bind="${1}" + local cache_file="/tmp/ip-info/${bind}.cache" + local use_cache="${2}" + local address_r="" + + if [[ "${use_cache}" -eq 1 ]]; then + address_r="$(get_cached_remote_address "${cache_file}")" + fi + + if [[ "${address_r}" != "" ]]; then + printf 'cache:%s' "${address_r}" + else + address_r=$(wget http://ipecho.net/plain -O - -q --bind-address="${bind}" 2> /dev/null) + + if [[ ${PIPESTATUS[0]} -ne 0 ]]; + then + return + fi + + if [[ "${use_cache}" -eq 1 ]]; then + set_cached_remote_address "${cache_file}" "${address_r}" + fi + + printf 'fresh:%s' "${address_r}" + fi + + if [[ "${use_cache}" -eq 0 ]] && [[ $(is_cache_file_written "${cache_file}") -eq 1 ]]; then + rm "${cache_file}" + fi +} + +function write_address() +{ + local scope="${1}" + local interface="${2}" + local address="${3}" + local ip_scope="${4}" + local output_level="${5}" + local address_type="${6:-fresh}" + + if [[ ${output_level} -eq 0 ]]; + then + printf '%s\n' "${address}" + return + fi + + if [[ ${output_level} -eq 1 ]]; + then + printf '[%s] %s\n' "${interface}" "${address}" + return + fi + + printf '[%s] %s (%s IPv%d) ' "${interface}" "${address}" "${scope}" "${ip_scope}" + + if [[ "${address_type}" == "cache" ]]; then + printf '[cached] ' + fi + + printf '\n' + +} + +function write_address_local() +{ + local interface="${1}" + local address_l="${2}" + local ip_scope="${3}" + local output_level="${4}" + + write_address local "${interface}" "${address_l}" "${ip_scope}" "${output_level}" +} + +function write_address_remote() +{ + local interface="${1}" + local address_l="${2}" + local ip_scope="${3}" + local output_level="${4}" + local use_cache="${5}" + local address_raw=$(get_address_remote "${address_l}" "${use_cache}") + local address_type="${address_raw:0:5}" + local address_r="${address_raw:6}" + + if [[ "${address_r}" == "" ]]; then + write_error "$(printf 'Failed to resolve remote address for "%s" interface.' "${interface}")" + return + fi + + write_address remote "${interface}" "${address_r}" "${ip_scope}" "${output_level}" "${address_type}" +} + +function write_interface_information() +{ + local interface="${1}" + local ip_scope="${2}" + local ip_level="${3}" + local output_level="${4}" + local use_cache="${5}" + local address_l="$([[ ${ip_level} -eq 6 ]] && get_address_local_v6 "${interface}" || get_address_local_v4 "${interface}")" + + if [[ "${address_l}" == "" ]]; then + write_error "$(printf 'Failed to resolve local address for "%s" interface.' "${interface}")" + return + fi + + if [[ "${ip_scope}" == "local" ]]; + then + write_address_local "${interface}" "${address_l}" "${ip_level}" "${output_level}" + else + write_address_remote "${interface}" "${address_l}" "${ip_level}" "${output_level}" "${use_cache}" + fi +} + +function main() +{ + local interfaces=() + local do_list_interfaces=0 + local ip_scope="local" + local ip_level=4 + local output_level=1 + local use_cache=1 + + while [[ $# -gt 0 ]] && [[ ."-${1}" = .--* ]]; + do + opt="${1}" + shift + + case "$opt" in + "--" ) + break 2 + ;; + -l | --list ) + do_list_interfaces=1 + ;; + -i=* | --interface=* ) + interfaces+=("${opt#*=}") + do_list_interfaces=0 + ;; + -6 | --ipv6 ) + ip_level=6 + ;; + -r | --remote ) + ip_scope=remote + ;; + -c | --no-remote-cache ) + use_cache=0 + ;; + -q | --minimal-quiet ) + IP_INFO_OUTPUT_ERROR_SUPPRESS=1 + ;; + -m | --minimal ) + output_level=0 + ;; + -V | --verbose ) + output_level=2 + ;; + -v | --version ) + printf '%s version 1.0.0\n' "$(get_script_name)" + exit + ;; + -h | --help ) + write_usage + exit + ;; + * ) + write_usage + write_newline + write_error "$(printf 'Invalid option provided: "%s"' "${opt}")" 255 + ;; + esac + + if [[ ${s} -eq 1 ]]; + then + shift + fi + done + + if [[ "${do_list_interfaces}" -eq 1 ]]; then + IP_INFO_OUTPUT_ERROR_SUPPRESS=1 + fi + + while [[ $# -gt 0 ]]; + do + interfaces+=("${1}") + do_list_interfaces_act=0 + do_list_interfaces_all=0 + shift + done + + if [[ ${do_list_interfaces} -eq 1 ]]; then + for interface in $(ip -br link | grep -E -o '^[a-z0-9]+\s+(UP|UNKNOWN)' | awk '{print $1}') + do + interfaces+=("${interface}") + done + fi + + if [[ ${#interfaces[@]} -eq 0 ]]; + then + write_usage + write_newline + write_error 'An interface name (directly or using arguments), or a list argument must be provided.' + fi + + for name in "${interfaces[@]}" + do + write_interface_information "${name}" "${ip_scope}" "${ip_level}" "${output_level}" "${use_cache}" + done +} + +main "$@" diff --git a/bin-enabled/net-list-hostnames b/bin-enabled/net-list-hostnames new file mode 120000 index 0000000..9a8e9f8 --- /dev/null +++ b/bin-enabled/net-list-hostnames @@ -0,0 +1 @@ +../bin-available/net-list-hostnames.bash \ No newline at end of file diff --git a/bin-enabled/pixztar b/bin-enabled/pixztar new file mode 120000 index 0000000..4eddeaa --- /dev/null +++ b/bin-enabled/pixztar @@ -0,0 +1 @@ +../bin-available/pixztar.bash \ No newline at end of file diff --git a/bin-enabled/plex-commercial-skipper b/bin-enabled/plex-commercial-skipper new file mode 120000 index 0000000..0ca8548 --- /dev/null +++ b/bin-enabled/plex-commercial-skipper @@ -0,0 +1 @@ +../bin-available/plex-commercial-skipper.zsh \ No newline at end of file diff --git a/bin-enabled/plex-media-fingerprinter b/bin-enabled/plex-media-fingerprinter new file mode 120000 index 0000000..caff88f --- /dev/null +++ b/bin-enabled/plex-media-fingerprinter @@ -0,0 +1 @@ +../bin-available/plex-media-fingerprinter.zsh \ No newline at end of file diff --git a/bin-enabled/plex-media-scanner b/bin-enabled/plex-media-scanner new file mode 120000 index 0000000..8b6559e --- /dev/null +++ b/bin-enabled/plex-media-scanner @@ -0,0 +1 @@ +../bin-available/plex-media-scanner.zsh \ No newline at end of file diff --git a/bin-enabled/plex-sqlite b/bin-enabled/plex-sqlite new file mode 120000 index 0000000..122c57e --- /dev/null +++ b/bin-enabled/plex-sqlite @@ -0,0 +1 @@ +../bin-available/plex-sqlite.zsh \ No newline at end of file diff --git a/bin-enabled/plex-transcoder b/bin-enabled/plex-transcoder new file mode 120000 index 0000000..37947c5 --- /dev/null +++ b/bin-enabled/plex-transcoder @@ -0,0 +1 @@ +../bin-available/plex-transcoder.zsh \ No newline at end of file diff --git a/bin-enabled/query-kraken b/bin-enabled/query-kraken new file mode 120000 index 0000000..a34162d --- /dev/null +++ b/bin-enabled/query-kraken @@ -0,0 +1 @@ +../bin-available/query-kraken.bash \ No newline at end of file diff --git a/bin-enabled/shellcheck b/bin-enabled/shellcheck new file mode 120000 index 0000000..6d768f1 --- /dev/null +++ b/bin-enabled/shellcheck @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/shellcheck \ No newline at end of file diff --git a/bin-enabled/shellcheck-install b/bin-enabled/shellcheck-install new file mode 120000 index 0000000..ec57a0a --- /dev/null +++ b/bin-enabled/shellcheck-install @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/shellcheck-install \ No newline at end of file diff --git a/bin-enabled/shellcheck-remove b/bin-enabled/shellcheck-remove new file mode 120000 index 0000000..9b5feb4 --- /dev/null +++ b/bin-enabled/shellcheck-remove @@ -0,0 +1 @@ +../lib/raspberry-scripts-bash/bin/shellcheck-remove \ No newline at end of file diff --git a/bin-enabled/start-glances b/bin-enabled/start-glances new file mode 120000 index 0000000..f83ec8d --- /dev/null +++ b/bin-enabled/start-glances @@ -0,0 +1 @@ +../bin-available/start-glances.bash \ No newline at end of file diff --git a/bin-enabled/youtube-dl b/bin-enabled/youtube-dl deleted file mode 120000 index 57e83eb..0000000 --- a/bin-enabled/youtube-dl +++ /dev/null @@ -1 +0,0 @@ -../bin-available/youtube-dl.bash \ No newline at end of file diff --git a/bin-enabled/zfs-mounts-reset.zsh b/bin-enabled/zfs-mounts-reset.zsh new file mode 100755 index 0000000..cc25b03 --- /dev/null +++ b/bin-enabled/zfs-mounts-reset.zsh @@ -0,0 +1,17 @@ +#!/usr/bin/env zsh + +DATASETS=('pool/backup-twoface/bpool' 'pool/backup-twoface/bpool/BOOT' 'pool/backup-twoface/bpool/BOOT/ubuntu' 'pool/backup-twoface/rpool' 'pool/backup-twoface/rpool/ROOT' 'pool/backup-twoface/rpool/ROOT/ubuntu' 'pool/backup-twoface/rpool/home' 'pool/backup-twoface/rpool/home/rmf' 'pool/backup-twoface/rpool/home/root' 'pool/backup-twoface/rpool/opt' 'pool/backup-twoface/rpool/srv' 'pool/backup-twoface/rpool/usr' 'pool/backup-twoface/rpool/usr/local' 'pool/backup-twoface/rpool/var' 'pool/backup-twoface/rpool/var/cache' 'pool/backup-twoface/rpool/var/lib' 'pool/backup-twoface/rpool/var/lib/docker' 'pool/backup-twoface/rpool/var/lib/nfs' 'pool/backup-twoface/rpool/var/lib/pms' 'pool/backup-twoface/rpool/var/log' 'pool/backup-twoface/rpool/var/spool' 'pool/backup-twoface/rpool/var/tmp') +DATAROOT='' +DATASETS=('tank/sends/bpool' 'tank/sends/bpool/BOOT' 'tank/sends/bpool/BOOT/ubuntu' 'tank/sends/rpool' 'tank/sends/rpool/ROOT' 'tank/sends/rpool/ROOT/ubuntu' 'tank/sends/rpool/home' 'tank/sends/rpool/home/rmf' +'tank/sends/rpool/home/root' 'tank/sends/rpool/opt' 'tank/sends/rpool/srv' 'tank/sends/rpool/usr' 'tank/sends/rpool/usr/local' 'tank/sends/rpool/var' 'tank/sends/rpool/var/cache' 'tank/sends/rpool/var/lib' +'tank/sends/rpool/var/lib/docker' 'tank/sends/rpool/var/lib/nfs' 'tank/sends/rpool/var/lib/pms' 'tank/sends/rpool/var/log' 'tank/sends/rpool/var/spool' 'tank/sends/rpool/var/tmp') +DATAROOT='' + +for d in ${(v)DATASETS};do + sudo zfs get all "${d}" | grep mount + sudo zfs set canmount=on "${d}" + sudo zfs set mountpoint="/${DATAROOT}${d}" "${d}" + sudo zfs get all "${d}" | grep mount + printf '=======================\n' + read +done diff --git a/bin-enabled/zfs-mounts-reset.zsh.b b/bin-enabled/zfs-mounts-reset.zsh.b new file mode 100644 index 0000000..86ce003 --- /dev/null +++ b/bin-enabled/zfs-mounts-reset.zsh.b @@ -0,0 +1,16 @@ +#!/usr/bin/env zsh + +DATASETS=('pool/backup-twoface/bpool' 'pool/backup-twoface/bpool/BOOT' 'pool/backup-twoface/bpool/BOOT/ubuntu' 'pool/backup-twoface/rpool' 'pool/backup-twoface/rpool/ROOT' 'pool/backup-twoface/rpool/ROOT/ubuntu' 'pool/backup-twoface/rpool/home' 'pool/backup-twoface/rpool/home/rmf' 'pool/backup-twoface/rpool/home/root' 'pool/backup-twoface/rpool/opt' 'pool/backup-twoface/rpool/srv' 'pool/backup-twoface/rpool/usr' 'pool/backup-twoface/rpool/usr/local' 'pool/backup-twoface/rpool/var' 'pool/backup-twoface/rpool/var/cache' 'pool/backup-twoface/rpool/var/lib' 'pool/backup-twoface/rpool/var/lib/docker' 'pool/backup-twoface/rpool/var/lib/nfs' 'pool/backup-twoface/rpool/var/lib/pms' 'pool/backup-twoface/rpool/var/log' 'pool/backup-twoface/rpool/var/spool' 'pool/backup-twoface/rpool/var/tmp') +DATAROOT='pool/backup-twoface/' +#DATASETS=('tank/sends/bpool' 'tank/sends/bpool/BOOT' 'tank/sends/bpool/BOOT/ubuntu' 'tank/sends/rpool' 'tank/sends/rpool/ROOT' 'tank/sends/rpool/ROOT/ubuntu' 'tank/sends/rpool/home' 'tank/sends/rpool/home/rmf' +#'tank/sends/rpool/home/root' 'tank/sends/rpool/opt' 'tank/sends/rpool/srv' 'tank/sends/rpool/usr' 'tank/sends/rpool/usr/local' 'tank/sends/rpool/var' 'tank/sends/rpool/var/cache' 'tank/sends/rpool/var/lib' 'tank/sends/rpool/var/lib/docker' 'tank/sends/rpool/var/lib/nfs' 'tank/sends/rpool/var/lib/pms' 'tank/sends/rpool/var/log' 'tank/sends/rpool/var/spool' 'tank/sends/rpool/var/tmp') +#tDATAROOT='' + +for d in ${(v)DATASETS};do + sudo zfs get all "${d}" | grep mount + sudo zfs set canmount=off "${d}" +# sudo zfs set mountpoint="/${DATAROOT}${d}" "${d}" + sudo zfs get all "${d}" | grep mount + printf '=======================\n' + read +done diff --git a/bin-enabled/zfs-mounts-reset.zsh.b~ b/bin-enabled/zfs-mounts-reset.zsh.b~ new file mode 100644 index 0000000..f074b4e --- /dev/null +++ b/bin-enabled/zfs-mounts-reset.zsh.b~ @@ -0,0 +1,16 @@ +#!/usr/bin/env zsh + +DATASETS=('pool/backup-twoface/bpool' 'pool/backup-twoface/bpool/BOOT' 'pool/backup-twoface/bpool/BOOT/ubuntu' 'pool/backup-twoface/rpool' 'pool/backup-twoface/rpool/ROOT' 'pool/backup-twoface/rpool/ROOT/ubuntu' 'pool/backup-twoface/rpool/home' 'pool/backup-twoface/rpool/home/rmf' 'pool/backup-twoface/rpool/home/root' 'pool/backup-twoface/rpool/opt' 'pool/backup-twoface/rpool/srv' 'pool/backup-twoface/rpool/usr' 'pool/backup-twoface/rpool/usr/local' 'pool/backup-twoface/rpool/var' 'pool/backup-twoface/rpool/var/cache' 'pool/backup-twoface/rpool/var/lib' 'pool/backup-twoface/rpool/var/lib/docker' 'pool/backup-twoface/rpool/var/lib/nfs' 'pool/backup-twoface/rpool/var/lib/pms' 'pool/backup-twoface/rpool/var/log' 'pool/backup-twoface/rpool/var/spool' 'pool/backup-twoface/rpool/var/tmp') +DATAROOT='pool/backup-twoface/' +#DATASETS=('tank/sends/bpool' 'tank/sends/bpool/BOOT' 'tank/sends/bpool/BOOT/ubuntu' 'tank/sends/rpool' 'tank/sends/rpool/ROOT' 'tank/sends/rpool/ROOT/ubuntu' 'tank/sends/rpool/home' 'tank/sends/rpool/home/rmf' +#'tank/sends/rpool/home/root' 'tank/sends/rpool/opt' 'tank/sends/rpool/srv' 'tank/sends/rpool/usr' 'tank/sends/rpool/usr/local' 'tank/sends/rpool/var' 'tank/sends/rpool/var/cache' 'tank/sends/rpool/var/lib' 'tank/sends/rpool/var/lib/docker' 'tank/sends/rpool/var/lib/nfs' 'tank/sends/rpool/var/lib/pms' 'tank/sends/rpool/var/log' 'tank/sends/rpool/var/spool' 'tank/sends/rpool/var/tmp') +#DATAROOT='' + +for d in ${(v)DATASETS};do + sudo zfs get all "${d}" | grep mount + sudo zfs set canmount=off "${d}" +# sudo zfs set mountpoint="/${DATAROOT}${d}" "${d}" + sudo zfs get all "${d}" | grep mount + printf '=======================\n' + read +done diff --git a/bin-enabled/zfs-mounts-reset.zsh~ b/bin-enabled/zfs-mounts-reset.zsh~ new file mode 100755 index 0000000..af50ebc --- /dev/null +++ b/bin-enabled/zfs-mounts-reset.zsh~ @@ -0,0 +1,17 @@ +#!/usr/bin/env zsh + +DATASETS=('pool/backup-twoface/bpool' 'pool/backup-twoface/bpool/BOOT' 'pool/backup-twoface/bpool/BOOT/ubuntu' 'pool/backup-twoface/rpool' 'pool/backup-twoface/rpool/ROOT' 'pool/backup-twoface/rpool/ROOT/ubuntu' 'pool/backup-twoface/rpool/home' 'pool/backup-twoface/rpool/home/rmf' 'pool/backup-twoface/rpool/home/root' 'pool/backup-twoface/rpool/opt' 'pool/backup-twoface/rpool/srv' 'pool/backup-twoface/rpool/usr' 'pool/backup-twoface/rpool/usr/local' 'pool/backup-twoface/rpool/var' 'pool/backup-twoface/rpool/var/cache' 'pool/backup-twoface/rpool/var/lib' 'pool/backup-twoface/rpool/var/lib/docker' 'pool/backup-twoface/rpool/var/lib/nfs' 'pool/backup-twoface/rpool/var/lib/pms' 'pool/backup-twoface/rpool/var/log' 'pool/backup-twoface/rpool/var/spool' 'pool/backup-twoface/rpool/var/tmp') +DATAROOT='' +#DATASETS=('tank/sends/bpool' 'tank/sends/bpool/BOOT' 'tank/sends/bpool/BOOT/ubuntu' 'tank/sends/rpool' 'tank/sends/rpool/ROOT' 'tank/sends/rpool/ROOT/ubuntu' 'tank/sends/rpool/home' 'tank/sends/rpool/home/rmf' +#'tank/sends/rpool/home/root' 'tank/sends/rpool/opt' 'tank/sends/rpool/srv' 'tank/sends/rpool/usr' 'tank/sends/rpool/usr/local' 'tank/sends/rpool/var' 'tank/sends/rpool/var/cache' 'tank/sends/rpool/var/lib' +#'tank/sends/rpool/var/lib/docker' 'tank/sends/rpool/var/lib/nfs' 'tank/sends/rpool/var/lib/pms' 'tank/sends/rpool/var/log' 'tank/sends/rpool/var/spool' 'tank/sends/rpool/var/tmp') +#DATAROOT='' + +for d in ${(v)DATASETS};do + sudo zfs get all "${d}" | grep mount + sudo zfs set canmount=on "${d}" + sudo zfs set mountpoint="/${DATAROOT}${d}" "${d}" + sudo zfs get all "${d}" | grep mount + printf '=======================\n' + read +done diff --git a/bin-enabled/zfs-scrub-watch b/bin-enabled/zfs-scrub-watch new file mode 120000 index 0000000..b083b41 --- /dev/null +++ b/bin-enabled/zfs-scrub-watch @@ -0,0 +1 @@ +../bin-available/zfs-scrub-watch.zsh \ No newline at end of file diff --git a/lib/bright b/lib/bright new file mode 160000 index 0000000..ade02a2 --- /dev/null +++ b/lib/bright @@ -0,0 +1 @@ +Subproject commit ade02a28b01155b9c02016d4229a2487bcc7a599 diff --git a/lib/bright-library b/lib/bright-library index 5e91878..ade02a2 160000 --- a/lib/bright-library +++ b/lib/bright-library @@ -1 +1 @@ -Subproject commit 5e91878d303317be3e474c37cee2aa215825c7d4 +Subproject commit ade02a28b01155b9c02016d4229a2487bcc7a599 diff --git a/lib/krakenx b/lib/krakenx new file mode 160000 index 0000000..1d27fa9 --- /dev/null +++ b/lib/krakenx @@ -0,0 +1 @@ +Subproject commit 1d27fa93230e6f8fb6eb3476347a55e822acc3d3 diff --git a/lib/raspberry-scripts-bash b/lib/raspberry-scripts-bash new file mode 160000 index 0000000..ca8b8cc --- /dev/null +++ b/lib/raspberry-scripts-bash @@ -0,0 +1 @@ +Subproject commit ca8b8ccd5c229dac852e76af4dfbdd45c8fa828e