VM NOTES
Small commands I reuse when setting up or maintaining a VM.
UPDATE THE VM
Refresh the package list and install available updates.
sudo apt update
sudo apt full-upgrade -y
VIRTUALBOX GUEST TOOLS
Install the VirtualBox guest packages, then restart the VM.
sudo apt install -y virtualbox-guest-utils virtualbox-guest-x11
sudo reboot
INSTALL ZSH
Install Zsh and make it the current user's default shell.
sudo apt install -y zsh
chsh -s "$(command -v zsh)" "$USER"
exec zsh
Check the configured login shell.
getent passwd "$USER" | cut -d: -f7
SHOW USER@HOST
Show User@Host in the prompt.
PROMPT='┌─[%n@%m]─[%~]
└──╼ %# '
Reload the configuration.
source "$HOME/.zshrc"
CLEAN DAILY COMMAND/OUTPUT LOGGER
Add this block to $HOME/.zshrc. It records commands, output, exit status, and duration in one daily log.
# ── Clean daily command/output logger ──────────────────────────
DAILY_LOG_DIR="$HOME/daily"
mkdir -p "$DAILY_LOG_DIR"
chmod 700 "$DAILY_LOG_DIR"
autoload -Uz add-zsh-hook
zmodload zsh/datetime
# Save the real terminal FDs once only.
# Re-sourcing .zshrc must NOT save an already-redirected tee pipe.
if [[ -z "${DAILY_LOGGER_FDS_READY:-}" ]]; then
typeset -g DAILY_LOGGER_FDS_READY=1
exec {DAILY_TTY_OUT}>&1
exec {DAILY_TTY_ERR}>&2
fi
_daily_preexec() {
local cmd="$1"
local logfile="$DAILY_LOG_DIR/$(date '+%Y-%m-%d').log"
local firstcmd="${${(z)cmd}[1]}"
typeset -g DAILY_COMMAND_ACTIVE=1
typeset -g DAILY_COMMAND_CAPTURE=0
typeset -g DAILY_CURRENT_LOG="$logfile"
typeset -g DAILY_START_TIME="${EPOCHREALTIME:-$(date '+%s.%N')}"
printf '\n[%s] COMMAND: %s\n' \
"$(date '+%Y-%m-%d %H:%M:%S')" \
"$cmd" >> "$logfile"
# Don't capture programs that redraw the terminal, or shell
# reload/replacement commands that can mutate logger state.
case "$firstcmd" in
less|more|vim|nvim|nano|top|htop|watch|man|tmux|screen|source|.|exec)
printf '[interactive/shell output not captured]\n' >> "$logfile"
;;
*)
typeset -g DAILY_COMMAND_CAPTURE=1
exec > >(tee -a "$logfile" >&$DAILY_TTY_OUT) \
2> >(tee -a "$logfile" >&$DAILY_TTY_ERR)
;;
esac
}
_daily_precmd() {
local exit_code=$?
local end_time
local -F 3 duration
[[ "${DAILY_COMMAND_ACTIVE:-0}" == "1" ]] || return
# Restore the real terminal BEFORE the next prompt/ZLE redraw.
if [[ "${DAILY_COMMAND_CAPTURE:-0}" == "1" ]]; then
exec 1>&$DAILY_TTY_OUT 2>&$DAILY_TTY_ERR
fi
end_time="${EPOCHREALTIME:-$(date '+%s.%N')}"
duration=$(( end_time - DAILY_START_TIME ))
printf '[%s] exit=%d duration=%.1fs\n' \
"$(date '+%Y-%m-%d %H:%M:%S')" \
"$exit_code" \
"$duration" >> "$DAILY_CURRENT_LOG"
unset DAILY_COMMAND_ACTIVE
unset DAILY_COMMAND_CAPTURE
unset DAILY_CURRENT_LOG
unset DAILY_START_TIME
}
# Make re-sourcing .zshrc idempotent: replace, don't stack, hooks.
add-zsh-hook -d preexec _daily_preexec 2>/dev/null
add-zsh-hook -d precmd _daily_precmd 2>/dev/null
add-zsh-hook preexec _daily_preexec
add-zsh-hook precmd _daily_precmd
Reload Zsh after saving the file.
exec zsh
NOTE: If you are hacking the logger SHOULD contain passwords, tokens, hashes, cookies, client data, and command output. Treat the output as sensitive.
QUICK HEALTH CHECKS
Check the host, network, disk, memory, and failed services.
hostnamectl
ip addr
df -h
free -h
systemctl --failed
CLEAN UP PACKAGES
Remove packages that are no longer needed and clear downloaded package files.
sudo apt autoremove --purge -y
sudo apt clean