Last active
March 19, 2024 01:22
-
-
Save RichardBronosky/5db39c943ae13697df4070316f0227ec to your computer and use it in GitHub Desktop.
tools-rpi is a bash script full Raspberry Pi tools
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
_setup_env() { | |
_env_blrplate | |
# Perform env setup by defining an _env function in calling script | |
if _is_function _env; then _env; fi | |
} | |
_env_blrplate() { | |
# ctrl chars for terminal colorizing | |
_text_plain="$(tput sgr0)" | |
_text_bold="$(tput bold)" | |
_text_red="$(tput setaf 1)" | |
_text_green="$(tput setaf 2)" | |
_text_yellow="$(tput setaf 3)" | |
_text_blue="$(tput setaf 4)" | |
_text_purple="$(tput setaf 5)" | |
_text_cyan="$(tput setaf 6)" | |
_text_grey="$(tput setaf 7)" | |
_text_white="$(tput setaf 15)" | |
DEBUG_TRAP="${DEBUG_TRAP:-0}" | |
DEBUG_XTRACE="${DEBUG_XTRACE:-0}" | |
DEBUG_SETUP="${DEBUG_SETUP:-}" | |
# shellcheck disable=SC2015 # shorthand use confirmed | |
[[ ${DEBUG_TRAP} -gt 0 ]] && _trap_set || : | |
# shellcheck disable=SC2015 # shorthand use confirmed | |
[[ ${DEBUG_XTRACE} -gt 0 ]] && _xtrace_set || : | |
# shellcheck disable=SC2015 # shorthand use confirmed | |
[[ -n ${DEBUG_SETUP} ]] && "${DEBUG_SETUP[@]}" || : | |
SCRIPT_PATH="$(_path_to_this_script)" | |
# shellcheck disable=SC2034 | |
SCRIPT_DIR="$(dirname "${SCRIPT_PATH}")" | |
SCRIPT_NAME="$(basename "${SCRIPT_PATH}")" | |
FORCE_SOURCE='' \ | |
_is_sourced || default_function=("_source_blrplate") | |
} | |
_text_demo() { | |
for v in $( | |
declare -p | awk '{sub("=.*","")} $2~/--/ && $3~/^_text/ && $3!~/(_plain|_bold)$/ {print $3}' | |
); do | |
echo "${v}:" \ | |
"${!v}${_text_bold}${v##*_}${_text_plain}" \ | |
"${!v}text${_text_plain}" | |
done | |
} | |
# In the event that tput is missing, noop | |
tput() { | |
command tput "$@" 2>/dev/null || : | |
} | |
# Use an array so that arguments can be included ("ls" "-l") | |
#default_function=("help") | |
unset default_function_takes_file | |
_has_main_function() { | |
declare -F | grep -qE '\<main$' | |
} | |
if [[ -z ${default_function:-} ]]; then | |
if _has_main_function; then | |
default_function=("main") | |
else | |
default_function=("help") | |
fi | |
fi | |
_source_blrplate() { | |
local src | |
if [[ $((${FULL_PATH:-0} + ${ABSOLUTE_PATH:-0})) -lt 1 ]]; then | |
src="$(basename "${BASH_SOURCE[0]}")" | |
echo 'source "$''(PATH="$''PWD:$''PATH" which '"$src"')"' | |
else | |
local pth | |
local arg | |
if [[ ${ABSOLUTE_PATH:-0} -gt 0 ]]; then arg="-P"; else arg="-L"; fi | |
src="${BASH_SOURCE[0]}" | |
pth="$(dirname "$src")" | |
pth="${pth:-.}" | |
pth="$( | |
cd "$pth" | |
pwd $arg | |
)" | |
src="$pth/$(basename "${BASH_SOURCE[0]}")" | |
echo 'source "'"$src"'"' | |
fi | |
} | |
_usage() { | |
/usr/bin/less -EXS <<USAGE | |
$SCRIPT_NAME | |
Usage: | |
$SCRIPT_NAME [-h | help] SUBCOMMAND [ ARGUMENT [ | ARGUMENT ] ... ] | |
$( | |
if [[ -n "${default_function:-}" ]]; then | |
if [[ -z "${default_function_takes_file:-}" ]]; then | |
cat <<NON_FILE_ARG | |
$SCRIPT_NAME [$default_function] ARGUMENT | |
NON_FILE_ARG | |
else | |
cat <<FILE_ARG | |
$SCRIPT_NAME [$default_function] FILE | |
$SCRIPT_NAME [$default_function] < FILE | |
FILE_ARG | |
fi | |
fi | |
) | |
Subcommands: | |
$( | |
_funcs | _pad | |
) | |
Note: | |
The help subcommand accepts a subcommand as a argument and will show | |
the the source code for the subcommand to help you understand what it | |
does and how it may be useful. | |
Example: | |
$( | |
{ | |
echo "$ $0 help help" | |
help help | |
} | _pad | |
) | |
USAGE | |
} | |
_pad() { | |
sed 's/^/ /' | |
} | |
_section() { | |
echo -e "\n""## $* ##" | |
} | |
_tee_stderr() { | |
tee >(cat >&2) | |
} | |
_is_function() { | |
[[ "$(type -t "$1" 2>/dev/null)" == *function* ]] | |
} | |
_funcs() { | |
if [[ ${1:-} == "--all" ]]; then | |
filter="^$" | |
else | |
local ignore | |
ignore=(help tput) | |
filter="$(IFS="|"; echo "^_|^(${ignore[*]})$";)" | |
echo help | |
fi | |
declare -F | awk '$2=="-f" && $3!~/'"$filter"'/{print $3}' | |
} | |
# shellcheck disable=SC2120 | |
_path_to_this_script() { | |
local src | |
local dir | |
local arg | |
src="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}" | |
if [[ ${1:-} =~ "^abs" ]]; then arg="-P"; else arg="-L"; fi | |
dir="$(cd "$(dirname "$src")" && pwd $arg)" | |
echo "$dir/$(basename "$src")" | |
} | |
_fd() { ( | |
check_what="$1" | |
check_for="$2" | |
case $check_what in | |
stdin | in | 0) | |
case $check_for in | |
tty) | |
[[ -t 0 ]] | |
;; | |
pipe) | |
[[ -p /dev/stdin ]] | |
;; | |
redirect | pipelike) | |
_fd 0 pipe || ! _fd 0 tty | |
;; | |
*) | |
echo "Checking '$check_what' fd for '$check_for' is not implemented" | |
return 255 | |
;; | |
esac | |
;; | |
stdout | out | 1) | |
case $check_for in | |
tty) | |
[[ -t 1 ]] | |
;; | |
pipe) | |
echo -e \ | |
"Checking 'stdout' fd for 'pipe' is not implemented because bash cannot""\n" \ | |
"distinguish between piping to another command and redirecting output to a""\n" \ | |
"file. Consider checking for 'pipelike'""\n" | |
return 255 | |
;; | |
redirect | pipelike) | |
! _fd 1 tty | |
;; | |
*) | |
echo "Checking '$check_what' fd for '$check_for' is not implemented" | |
return 255 | |
;; | |
esac | |
;; | |
*) | |
echo "Checking '$check_what' fd is not implemented" | |
return 255 | |
;; | |
esac | |
) } | |
_main() { | |
_setup_env | |
( | |
cmd=("help") | |
if [[ -n "${default_function:-}" ]]; then | |
if [[ -z "${default_function_takes_file:-}" && -n "${1:-}" ]] && ! _is_function "$1"; then | |
cmd=("${default_function[@]}") | |
else | |
if [[ -f "${1:-}" ]]; then | |
cmd=("${default_function[@]}" "$@") | |
elif _fd stdin pipelike; then | |
## TODO: Fix this!!! | |
#cmd=("${default_function[@]}" "/dev/stdin") | |
: | |
cmd=("${default_function[@]}") | |
else | |
cmd=("${default_function[@]}") | |
fi | |
fi | |
fi | |
if [[ "${cmd[0]}" == "help" && -n "${1:-}" ]]; then | |
# Use and array so that arguments can be included ("ls" "-l") | |
cmd=("$1") | |
# Map alternate subcommands | |
[[ ${cmd[0]} == -h ]] && cmd=("help") | |
[[ ${cmd[0]} == -help ]] && cmd=("help") | |
[[ ${cmd[0]} == --help ]] && cmd=("help") | |
# Do not shift the arguments until last | |
shift | |
fi | |
"${cmd[@]}" "$@" | |
) | |
} | |
_is_sourced() { | |
local stack_depth=${1:-0} | |
[[ -z ${FORCE_SOURCE:-} ]] || return | |
[[ "X${BASH_SOURCE:-}X" != "XX" ]] && [[ "${BASH_SOURCE[$stack_depth]}" != "$0" ]] && return | |
[[ "X${ZSH_EVAL_CONTEXT:-}X" != "XX" ]] && [[ $ZSH_EVAL_CONTEXT == *file:shfunc* ]] && return | |
return | |
} | |
_vars() { | |
set | | |
awk ' | |
/^[a-zA-Z_]+ \(\)/{exit} | |
/^(ALAC|CSF_|DBUS|DEBUGINFOD_URLS|DOCKER_HOST|DRAW|GPG|GTK|HOST|INVO|KUBE|M[AMO])/{next} | |
/^(OLD|_?P9|PY|SS|TERM|TMUX|WIN|XAUTH|XDG)/{next} | |
{print}' | |
} | |
_trap_fn() { | |
[[ ${DEBUG_TRAP_SKIP:-} ]] && unset DEBUG_TRAP_SKIP && return 0 | |
if [[ ${DEBUG_TRAP:-0} -gt 0 && $BASH_COMMAND != "unset DEBUG_TRAP" && "${FUNCNAME[1]}" != *_is_function* ]]; then | |
printf "${_text_yellow:-}[%s:%5s %-${length_longest_func}s${_text_plain:-} %s\n" \ | |
"${BASH_SOURCE[1]}" \ | |
"${BASH_LINENO[0]}" \ | |
"${FUNCNAME[1]}()]" \ | |
"${BASH_COMMAND}" >&2 | |
#"$({ sed -n l | sed 's,\\,\\\\\\\\,g' }<<<"XX${BASH_COMMAND}XX")" >&2 | |
fi | |
if _is_function "${BASH_COMMAND%% *}"; then DEBUG_TRAP_SKIP=1; fi | |
return 0 # do not block execution in extdebug mode | |
} | |
_trap_set() { | |
length_longest_func="$(_funcs --all | sed 's/././g' | sort | tail -n1 | wc -c)" | |
set -o functrace | |
trap _trap_fn DEBUG | |
} | |
_xtrace_set() { | |
length_longest_func="$(_funcs --all | sed 's/././g' | sort | tail -n1 | wc -c)" | |
PS4='$(_ps4)' | |
set -x | |
} | |
_ps4() { | |
printf "${_text_yellow:-}[%s:%5s %-${length_longest_func}s ${_text_plain:-}" \ | |
"${BASH_SOURCE[1]}" \ | |
"${BASH_LINENO[0]}" \ | |
"${FUNCNAME[1]}()]" | |
} | |
_entrypoint() { | |
if _is_sourced -1; then | |
_setup_env | |
else | |
_main "$@" | |
fi | |
} | |
# Explicitly use the (implied) function keyword to prevent conflict with common aliases | |
function help() { | |
local funcs=("$@") | |
if [[ -z "${funcs[*]}" ]]; then | |
for func in usage _usage _funcs; do _is_function $func && { | |
$func | |
return | |
}; done | |
else | |
for func in "${funcs[@]}"; do | |
declare -f "$func" | |
done | |
fi | |
} | |
# Avoids having your interactive shell close if you source this script | |
# and get an error caught by set -eu | |
( | |
# EVERY SHELL SCRIPT SHOULD HAVE: set -eu | |
# Use ||true after commands that should be fault tolerant | |
# -e aka -o errexit: Exit immediately if a command exits with a non-zero status | |
# -u aka -o nounset: Unset variables treated as an error when substituting | |
set -eu | |
_entrypoint "$@" | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
stdu="$(id -un 1000)" | |
stdh="$(sudo -u "${stdu}" bash -c 'echo $HOME')" | |
function keyboard_setup(){ | |
locale=en_US.UTF-8 | |
layout=us | |
sudo raspi-config nonint do_change_locale $locale | |
sudo raspi-config nonint do_configure_keyboard $layout | |
} | |
function wifi_setup(){ | |
country=US | |
sudo raspi-config nonint do_wifi_country $country | |
wifi_powersave_setup | |
} | |
function wifi_powersave_setup(){ | |
sudo tee -a /etc/NetworkManager/conf.d/wifi-powersave.conf << EOF | |
# See: https://github.com/NetworkManager/NetworkManager/blob/main/src/libnm-core-public/nm-setting-wireless.h#L128-L146 | |
[connection] | |
wifi.powersave = 2 | |
EOF | |
sudo systemctl restart NetworkManager | |
} | |
# This includes some apparent redundant calls to sudo. | |
# They are there to make sure that no mater which user executes these commands, | |
# both root and standard users get files with the right permissions. | |
# Fix bash | |
function bash_setup(){ | |
sudo -u "$stdu" touch "$stdh/.bashrc" | |
( | |
sudo tee -a "$stdh/.bashrc" \ | |
| sudo tee -a /root/.bashrc > /dev/null | |
) << 'EOF_BASHRC' | |
set -o vi | |
export EDITOR=vim | |
alias ll='ls -la' | |
ptree(){ ps auxf | awk -v cmd="$1" 'BEGIN{"ps -o ppid= $$" | getline pid} $0 !~ "\_" {p=0} $0 ~ cmd && $2 != pid {p=1} p==1{print}' | less -SEX; } | |
EOF_BASHRC | |
} | |
function sshd_fix(){ | |
sudo tee -a /etc/ssh/sshd_config.d/fix_freeze.conf <<EOF_SSHD_CONF | |
#IPQoS 0x00 | |
IPQoS cs0 cs0 | |
TCPKeepAlive yes | |
ClientAliveInterval 60 | |
ClientAliveCountMax 10 | |
EOF_SSHD_CONF | |
} | |
# Fix vim | |
function vim_setup(){ | |
sudo mkdir -p ~root/.vim | |
sudo -u "$stdu" mkdir -p "$stdh/.vim" | |
sudo touch ~root/.vim/vimrc | |
sudo -u "$stdu" touch "$stdh/.vim/vimrc" | |
( | |
sudo tee -a $stdh/.vim/vimrc \ | |
| sudo tee -a ~root/.vim/vimrc > /dev/null | |
) << 'EOF_VIMRC' | |
" use the pretty good defaults | |
if filereadable("/usr/share/vim/vim80/defaults.vim") | |
source /usr/share/vim/vim80/defaults.vim | |
elseif filereadable("/usr/share/vim/vim90/defaults.vim") | |
source /usr/share/vim/vim90/defaults.vim | |
endif | |
" don't interpret mouse clicks | |
set mouse= | |
EOF_VIMRC | |
} | |
source "$(PATH="$PWD:$PATH" which BOILERPLATE.sh)" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment