Skip to content

Instantly share code, notes, and snippets.

@RichardBronosky
Last active March 19, 2024 01:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RichardBronosky/5db39c943ae13697df4070316f0227ec to your computer and use it in GitHub Desktop.
Save RichardBronosky/5db39c943ae13697df4070316f0227ec to your computer and use it in GitHub Desktop.
tools-rpi is a bash script full Raspberry Pi tools
#! /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 "$@"
)
#! /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