mirror of
https://github.com/buildplan/du_setup.git
synced 2025-12-17 17:55:35 +00:00
Add optional dtop - Docker container monitoring TUI
This commit is contained in:
parent
103abb8d1d
commit
ff6bcc97ec
282
du_setup.sh
282
du_setup.sh
@ -1,8 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Debian and Ubuntu Server Hardening Interactive Script
|
||||
# Version: 0.73 | 2025-10-22
|
||||
# Version: 0.74 | 2025-11-06
|
||||
# Changelog:
|
||||
# - v0.74: Add optional dtop (https://github.com/amir20/dtop) after docker installation.
|
||||
#. Update .bashrc
|
||||
# - v0.73: Revised/improved logic in .bashrc for memory and system updates.
|
||||
# - v0.72: Added configure_custom_bashrc() function that creates and installs a feature-rich .bashrc file during user creation.
|
||||
# - v0.71: Simplify test backup function to work reliably with Hetzner storagebox
|
||||
@ -77,7 +79,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
# --- Update Configuration ---
|
||||
CURRENT_VERSION="0.73"
|
||||
CURRENT_VERSION="0.74"
|
||||
SCRIPT_URL="https://raw.githubusercontent.com/buildplan/du_setup/refs/heads/main/du_setup.sh"
|
||||
CHECKSUM_URL="${SCRIPT_URL}.sha256"
|
||||
|
||||
@ -228,7 +230,7 @@ print_header() {
|
||||
printf '%s\n' "${CYAN}╔═════════════════════════════════════════════════════════════════╗${NC}"
|
||||
printf '%s\n' "${CYAN}║ ║${NC}"
|
||||
printf '%s\n' "${CYAN}║ DEBIAN/UBUNTU SERVER SETUP AND HARDENING SCRIPT ║${NC}"
|
||||
printf '%s\n' "${CYAN}║ v0.73 | 2025-10-22 ║${NC}"
|
||||
printf '%s\n' "${CYAN}║ v0.74 | 2025-11-06 ║${NC}"
|
||||
printf '%s\n' "${CYAN}║ ║${NC}"
|
||||
printf '%s\n' "${CYAN}╚═════════════════════════════════════════════════════════════════╝${NC}"
|
||||
printf '\n'
|
||||
@ -1238,16 +1240,15 @@ __bash_prompt_command() {
|
||||
PROMPT_COMMAND=__bash_prompt_command
|
||||
|
||||
# --- Editor Configuration ---
|
||||
# Set default editor with fallback chain.
|
||||
if command -v vim &>/dev/null; then
|
||||
export EDITOR=vim
|
||||
export VISUAL=vim
|
||||
elif command -v vi &>/dev/null; then
|
||||
export EDITOR=vi
|
||||
export VISUAL=vi
|
||||
else
|
||||
elif command -v nano &>/dev/null; then
|
||||
export EDITOR=nano
|
||||
export VISUAL=nano
|
||||
else
|
||||
export EDITOR=vi
|
||||
export VISUAL=vi
|
||||
fi
|
||||
|
||||
# --- Additional Environment Variables ---
|
||||
@ -1265,7 +1266,7 @@ mkcd() {
|
||||
# Create a backup of a file with timestamp.
|
||||
backup() {
|
||||
if [ -f "$1" ]; then
|
||||
local backup_file="$1.backup-$(date +%Y%m%d-%H%M%S)"
|
||||
local backup_file; backup_file="$1.backup-$(date +%Y%m%d-%H%M%S)"
|
||||
cp "$1" "$backup_file"
|
||||
echo "Backup created: $backup_file"
|
||||
else
|
||||
@ -1300,7 +1301,7 @@ extract() {
|
||||
;;
|
||||
*)
|
||||
echo "'$1' cannot be extracted via extract()" >&2
|
||||
return 1
|
||||
return 1 # Add return 1 for consistency
|
||||
;;
|
||||
esac
|
||||
else
|
||||
@ -1334,6 +1335,9 @@ ftext() {
|
||||
grep -rnw . -e "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
# Search history easily
|
||||
hgrep() { history | grep -i --color=auto "$@"; }
|
||||
|
||||
# Create a tarball of a directory.
|
||||
targz() {
|
||||
if [ -d "$1" ]; then
|
||||
@ -1357,7 +1361,36 @@ sizeof() {
|
||||
|
||||
# Show most used commands from history.
|
||||
histop() {
|
||||
history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n20
|
||||
history | awk -v ig="$HISTIGNORE" 'BEGIN{OFS="\t";gsub(/:/,"|",ig);ir="^("ig")($| )";sr="(^|\\s)\\./"}
|
||||
{cmd=$4;for(i=5;i<=NF;i++)cmd=cmd" "$i}
|
||||
(cmd==""||cmd~ir||cmd~sr){next}
|
||||
{C[cmd]++;t++}
|
||||
END{if(t>0)for(a in C)printf"%d\t%.2f%%\t%s\n",C[a],(C[a]/t*100),a}' |
|
||||
sort -nr | head -n20 |
|
||||
awk 'BEGIN{
|
||||
FS="\t";
|
||||
maxc=length("COUNT");
|
||||
maxp=length("PERCENT");
|
||||
}
|
||||
{
|
||||
data[NR]=$0;
|
||||
len1=length($1);
|
||||
len2=length($2);
|
||||
if(len1>maxc)maxc=len1;
|
||||
if(len2>maxp)maxp=len2;
|
||||
}
|
||||
END{
|
||||
fmt=" %-4s %-*s %-*s %s\n";
|
||||
printf fmt,"RANK",maxc,"COUNT",maxp,"PERCENT","COMMAND";
|
||||
sep_c=sep_p="";
|
||||
for(i=1;i<=maxc;i++)sep_c=sep_c"-";
|
||||
for(i=1;i<=maxp;i++)sep_p=sep_p"-";
|
||||
printf fmt,"----",maxc,sep_c,maxp,sep_p,"-------";
|
||||
for(i=1;i<=NR;i++){
|
||||
split(data[i],f,"\t");
|
||||
printf fmt,i".",maxc,f[1],maxp,f[2],f[3]
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
||||
# Quick server info display
|
||||
@ -1392,18 +1425,45 @@ sysinfo() {
|
||||
cpu_info=$(lscpu | awk -F: '/Model name/ {print $2; exit}' | xargs || grep -m1 'model name' /proc/cpuinfo | cut -d ':' -f2 | xargs)
|
||||
[ -z "$cpu_info" ] && cpu_info="Unknown"
|
||||
|
||||
# --- IP Detection (preferred interfaces first) ---
|
||||
local ip_addr
|
||||
for iface in eth0 wlan0 ens33 eno1 enp0s3 enp3s0; do
|
||||
# --- IP Detection ---
|
||||
local ip_addr public_ipv4 public_ipv6
|
||||
|
||||
# Try to get public IPv4 first
|
||||
public_ipv4=$(curl -4 -s -m 2 --connect-timeout 1 https://checkip.amazonaws.com 2>/dev/null || \
|
||||
curl -4 -s -m 2 --connect-timeout 1 https://ipconfig.io 2>/dev/null || \
|
||||
curl -4 -s -m 2 --connect-timeout 1 https://api.ipify.org 2>/dev/null)
|
||||
# If no IPv4, try IPv6
|
||||
if [ -z "$public_ipv4" ]; then
|
||||
public_ipv6=$(curl -6 -s -m 2 --connect-timeout 1 https://ipconfig.io 2>/dev/null || \
|
||||
curl -6 -s -m 2 --connect-timeout 1 https://icanhazip.co 2>/dev/null || \
|
||||
curl -6 -s -m 2 --connect-timeout 1 https://api64.ipify.org 2>/dev/null)
|
||||
fi
|
||||
# Get local/internal IP as fallback
|
||||
for iface in eth0 ens3 enp0s3 enp0s6 wlan0 ens33 eno1; do
|
||||
ip_addr=$(ip -4 addr show "$iface" 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1)
|
||||
[ -n "$ip_addr" ] && break
|
||||
done
|
||||
[ -z "$ip_addr" ] && ip_addr=$(ip -4 addr show scope global | awk '/inet/ {print $2}' | cut -d/ -f1 | head -n1)
|
||||
[ -z "$ip_addr" ] && ip_addr=$(ip -4 addr show scope global 2>/dev/null | awk '/inet/ {print $2}' | cut -d/ -f1 | head -n1)
|
||||
|
||||
# --- System Info ---
|
||||
if [ -n "$ip_addr" ]; then
|
||||
if [ -n "$public_ipv4" ]; then
|
||||
# Show public IPv4 (preferred)
|
||||
printf "${CYAN}%-15s${RESET} %s ${YELLOW}[%s]${RESET}" "Hostname:" "$(hostname)" "$public_ipv4"
|
||||
# Show local IP if different from public
|
||||
if [ -n "$ip_addr" ] && [ "$ip_addr" != "$public_ipv4" ]; then
|
||||
printf " ${DIM}(local: %s)${RESET}\n" "$ip_addr"
|
||||
else
|
||||
printf "\n"
|
||||
fi
|
||||
elif [ -n "$public_ipv6" ]; then
|
||||
# Show public IPv6 if no IPv4
|
||||
printf "${CYAN}%-15s${RESET} %s ${YELLOW}[%s]${RESET}" "Hostname:" "$(hostname)" "$public_ipv6"
|
||||
[ -n "$ip_addr" ] && printf " ${DIM}(local: %s)${RESET}\n" "$ip_addr" || printf "\n"
|
||||
elif [ -n "$ip_addr" ]; then
|
||||
# Show local IP only
|
||||
printf "${CYAN}%-15s${RESET} %s ${YELLOW}[%s]${RESET}\n" "Hostname:" "$(hostname)" "$ip_addr"
|
||||
else
|
||||
# No IP detected
|
||||
printf "${CYAN}%-15s${RESET} %s\n" "Hostname:" "$(hostname)"
|
||||
fi
|
||||
printf "${CYAN}%-15s${RESET} %s\n" "OS:" "$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d'"' -f2 || echo 'Unknown')"
|
||||
@ -1439,19 +1499,23 @@ sysinfo() {
|
||||
security="${apt_check_output##*;}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fallback if apt-check didn't provide values
|
||||
if [ -z "$total" ] && [ -r /var/lib/update-notifier/updates-available ]; then
|
||||
total=$(awk '/[0-9]+ (update|package)s? can be (updated|applied|installed)/ {print $1; exit}' /var/lib/update-notifier/updates-available 2>/dev/null)
|
||||
security=$(awk '/[0-9]+ (update|package)s? .*security/ {print $1; exit}' /var/lib/update-notifier/updates-available 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Final fallback
|
||||
if [ -z "$total" ]; then
|
||||
total=$(apt list --upgradable 2>/dev/null | grep -c upgradable)
|
||||
security=$(apt list --upgradable 2>/dev/null | grep -ci security)
|
||||
fi
|
||||
|
||||
total="${total:-0}"
|
||||
security="${security:-0}"
|
||||
|
||||
# Display updates if available
|
||||
if [ -n "$total" ] && [ "$total" -gt 0 ] 2>/dev/null; then
|
||||
printf "${CYAN}%-15s${RESET} " "Updates:"
|
||||
if [ -n "$security" ] && [ "$security" -gt 0 ] 2>/dev/null; then
|
||||
@ -1485,6 +1549,28 @@ sysinfo() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Tailscale Info (if installed and connected) ---
|
||||
if command -v tailscale &>/dev/null; then
|
||||
local ts_ipv4 ts_ipv6 ts_hostname
|
||||
# Get Tailscale IPs
|
||||
ts_ipv4=$(tailscale ip -4 2>/dev/null)
|
||||
ts_ipv6=$(tailscale ip -6 2>/dev/null)
|
||||
# Only show if connected
|
||||
if [ -n "$ts_ipv4" ] || [ -n "$ts_ipv6" ]; then
|
||||
# Get hostname from status (FIXED: use head -n1 to get only first line)
|
||||
ts_hostname=$(tailscale status --self --peers=false 2>/dev/null | head -n1 | awk '{print $2}')
|
||||
printf "${CYAN}%-15s${RESET} " "Tailscale:"
|
||||
printf "${GREEN}Connected${RESET}"
|
||||
[ -n "$ts_ipv4" ] && printf " - %s" "$ts_ipv4"
|
||||
[ -n "$ts_hostname" ] && printf " ${DIM}(%s)${RESET}" "$ts_hostname"
|
||||
printf "\n"
|
||||
# Optional: Show IPv6 on second line if available
|
||||
if [ -n "$ts_ipv6" ]; then
|
||||
printf " ${DIM}IPv6: %s${RESET}\n" "$ts_ipv6"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
@ -1501,6 +1587,47 @@ checkupdates() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Disk space alert (warns if any partition > 80%)
|
||||
diskcheck() {
|
||||
df -h | awk '
|
||||
NR > 1 {
|
||||
usage = $5
|
||||
gsub(/%/, "", usage)
|
||||
if (usage > 80) {
|
||||
printf "⚠️ %s\n", $0
|
||||
found = 1
|
||||
}
|
||||
}
|
||||
END {
|
||||
if (!found) print "✓ All disks below 80%"
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
# Directory bookmarks
|
||||
export MARKPATH=$HOME/.marks
|
||||
[ -d "$MARKPATH" ] || mkdir -p "$MARKPATH"
|
||||
mark() { ln -sfn "$(pwd)" "$MARKPATH/${1:-$(basename "$PWD")}"; }
|
||||
jump() { cd -P "$MARKPATH/$1" 2>/dev/null || ls -l "$MARKPATH"; }
|
||||
|
||||
# Service status shortcut (cleaner output)
|
||||
svc() { sudo systemctl status "$1" --no-pager -l | head -20; }
|
||||
alias failed='systemctl --failed --no-pager'
|
||||
|
||||
# Show top 10 processes by CPU
|
||||
topcpu() { ps aux --sort=-%cpu | head -11; }
|
||||
|
||||
# Show top 10 processes by memory
|
||||
topmem() { ps aux --sort=-%mem | head -11; }
|
||||
|
||||
# Network connections summary
|
||||
netsum() {
|
||||
echo "=== Active Connections ==="
|
||||
ss -s
|
||||
echo -e "\n=== Listening Ports ==="
|
||||
sudo ss -tulnp | grep LISTEN | awk '{print $5, $7}' | sort -u
|
||||
}
|
||||
|
||||
# --- Aliases ---
|
||||
# Enable color support for common commands.
|
||||
if [ -x /usr/bin/dircolors ]; then
|
||||
@ -1523,6 +1650,9 @@ alias lt='ls -alFht' # Sort by modification time, newest first
|
||||
alias ltr='ls -alFhtr' # Sort by modification time, oldest first
|
||||
alias lS='ls -alFhS' # Sort by size, largest first
|
||||
|
||||
# Last command with sudo
|
||||
alias please='sudo $(history -p !!)'
|
||||
|
||||
# Safety aliases to prompt before overwriting.
|
||||
alias rm='rm -i'
|
||||
alias cp='cp -i'
|
||||
@ -1582,6 +1712,7 @@ alias myip='curl -s ifconfig.me || curl -s icanhazip.com' # Alternatives: api.ip
|
||||
localip() {
|
||||
ip -4 addr | awk '/inet/ {print $2}' | cut -d/ -f1 | grep -v '127.0.0.1'
|
||||
}
|
||||
|
||||
alias netstat='ss'
|
||||
alias ping='ping -c 5'
|
||||
alias fastping='ping -c 100 -i 0.2'
|
||||
@ -1635,12 +1766,14 @@ if command -v docker &>/dev/null; then
|
||||
# Docker stats
|
||||
alias dstats='docker stats --no-stream'
|
||||
alias dstatsa='docker stats'
|
||||
dtop() {
|
||||
dst() {
|
||||
docker stats --format 'table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}'
|
||||
}
|
||||
|
||||
# Safe stop all (shows command instead of executing)
|
||||
alias dstopall='echo "To stop all containers, run: docker stop \$(docker ps -q)"'
|
||||
alias dstopa='echo "To stop all containers, run: docker stop \$(docker ps -q)"'
|
||||
# Start all stopped containers
|
||||
alias dstarta='docker start $(docker ps -aq)'
|
||||
|
||||
# Docker Compose v2 aliases (check if the compose plugin exists)
|
||||
if docker compose version &>/dev/null; then
|
||||
@ -1880,6 +2013,8 @@ Categories: navigation, files, system, docker, git, network
|
||||
mkcd <dir> Create directory and cd into it
|
||||
up <n> Go up N directories (e.g., up 3)
|
||||
path Display PATH variable (one per line)
|
||||
mark <name> Bookmark current directory
|
||||
jump <name> Jump to a bookmarked directory
|
||||
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
📄 FILE OPERATIONS
|
||||
@ -1911,18 +2046,22 @@ Categories: navigation, files, system, docker, git, network
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
sysinfo Display comprehensive system information
|
||||
checkupdates Check for available system updates
|
||||
diskcheck Check for disk partitions over 80%
|
||||
|
||||
psgrep <pat> Search for process by name
|
||||
psmem Show top 10 processes by memory usage
|
||||
pscpu Show top 10 processes by CPU usage
|
||||
top10 Show top 10 memory-consuming processes
|
||||
topcpu Show top 10 processes by CPU
|
||||
topmem Show top 10 processes by Memory
|
||||
pscpu Show top 10 processes by CPU (tree view)
|
||||
psmem Show top 10 processes by Memory (tree view)
|
||||
|
||||
ports Show all listening ports (TCP/UDP)
|
||||
listening Show listening ports with process info
|
||||
meminfo Display detailed memory information
|
||||
|
||||
h Show command history
|
||||
hgrep <pat> Search command history
|
||||
histop Show most used commands
|
||||
c, cls Clear the screen
|
||||
reload Reload bashrc configuration
|
||||
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
@ -1947,7 +2086,7 @@ Docker Commands:
|
||||
|
||||
dstats Container stats snapshot
|
||||
dstatsa Container stats live
|
||||
dtop Container stats formatted table
|
||||
dst Container stats formatted table
|
||||
|
||||
dprune Prune system (remove unused data)
|
||||
dprunea Prune all (including images)
|
||||
@ -1996,6 +2135,8 @@ Docker Compose:
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
myip Show external IP address
|
||||
localip Show local IP address(es)
|
||||
netsum Network connections summary
|
||||
kssh SSH wrapper for kitty terminal
|
||||
ping Ping with 5 packets (default)
|
||||
fastping Fast ping (100 packets, 0.2s interval)
|
||||
netstat Show network connections (ss)
|
||||
@ -2004,6 +2145,8 @@ Docker Compose:
|
||||
⚙️ SYSTEM ADMINISTRATION
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
Systemd:
|
||||
svc <srv> Show service status (brief)
|
||||
failed List failed systemd services
|
||||
sysstart <srv> Start service
|
||||
sysstop <srv> Stop service
|
||||
sysrestart <srv> Restart service
|
||||
@ -2021,6 +2164,9 @@ APT (Debian/Ubuntu):
|
||||
aptclean Remove unused packages
|
||||
aptlist List installed packages
|
||||
|
||||
Sudo:
|
||||
please Run last command with sudo
|
||||
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
🕒 DATE & TIME
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
@ -2032,6 +2178,8 @@ APT (Debian/Ubuntu):
|
||||
ℹ️ HELP & INFORMATION
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
bashhelp Show this help (all categories)
|
||||
bh Alias for bashhelp
|
||||
commands List all custom functions and aliases
|
||||
bashhelp navigation Show navigation commands only
|
||||
bashhelp files Show file operation commands
|
||||
bashhelp system Show system monitoring commands
|
||||
@ -2042,7 +2190,7 @@ APT (Debian/Ubuntu):
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
💡 TIP: Most commands support --help or -h for more information
|
||||
The prompt shows: ✗ for failed commands, git branch when in repo
|
||||
The prompt shows: ✗ for failed commands, (git branch) when in repo
|
||||
|
||||
HELPTEXT
|
||||
;;
|
||||
@ -2062,11 +2210,14 @@ HELPTEXT
|
||||
mkcd <dir> Create directory and cd into it
|
||||
up <n> Go up N directories
|
||||
path Display PATH variable
|
||||
mark <name> Bookmark current directory
|
||||
jump <name> Jump to a bookmarked directory
|
||||
|
||||
Examples:
|
||||
mkcd ~/projects/newapp # Create and enter directory
|
||||
up 3 # Go up 3 levels
|
||||
cd - # Return to previous directory
|
||||
mark proj1 # Bookmark current dir as 'proj1'
|
||||
jump proj1 # Jump back to 'proj1'
|
||||
|
||||
HELPTEXT
|
||||
;;
|
||||
@ -2111,12 +2262,14 @@ HELPTEXT
|
||||
Overview:
|
||||
sysinfo Comprehensive system info
|
||||
checkupdates Check for package updates
|
||||
diskcheck Check for disks > 80%
|
||||
|
||||
Processes:
|
||||
psgrep <pat> Search processes
|
||||
psmem Top 10 by memory
|
||||
pscpu Top 10 by CPU
|
||||
top10 Top memory consumers
|
||||
topcpu Top 10 by CPU
|
||||
topmem Top 10 by Memory
|
||||
pscpu Top 10 by CPU (tree view)
|
||||
psmem Top 10 by Memory (tree view)
|
||||
|
||||
Network:
|
||||
ports Listening ports
|
||||
@ -2126,9 +2279,11 @@ Memory:
|
||||
meminfo Detailed memory info
|
||||
free Free memory (human-readable)
|
||||
|
||||
History:
|
||||
Shell:
|
||||
h Show history
|
||||
hgrep <pat> Search history
|
||||
histop Most used commands
|
||||
c, cls Clear screen
|
||||
reload Reload bashrc
|
||||
|
||||
Examples:
|
||||
@ -2155,7 +2310,7 @@ Management:
|
||||
dfollow <id> Follow logs
|
||||
|
||||
Stats & Cleanup:
|
||||
dstats, dstatsa, dtop
|
||||
dstats, dstatsa, dst
|
||||
dprune, dprunea, dvprune, diprune
|
||||
drmall Remove stopped containers
|
||||
|
||||
@ -2165,7 +2320,7 @@ Docker Compose:
|
||||
dcstatus Status & resource usage
|
||||
dcreload <srv> Restart & follow logs
|
||||
dcupdate <srv> Pull & update service
|
||||
dcgrep <srv> <p> Filter logs
|
||||
dcgrep <s> <p> Filter logs
|
||||
dcvalidate Validate compose file
|
||||
|
||||
Examples:
|
||||
@ -2207,11 +2362,13 @@ HELPTEXT
|
||||
|
||||
myip Show external IP
|
||||
localip Show local IP(s)
|
||||
netsum Network connection summary
|
||||
kssh SSH wrapper for kitty
|
||||
ports Show listening ports
|
||||
listening Ports with process info
|
||||
ping Ping (5 packets)
|
||||
fastping Fast ping (100 packets)
|
||||
netstat Network connections
|
||||
netstat Network connections (ss)
|
||||
|
||||
Examples:
|
||||
myip # Get public IP
|
||||
@ -2231,6 +2388,7 @@ HELPTEXT
|
||||
}
|
||||
|
||||
# Preserve Bash's builtin `help` while integrating bashhelp
|
||||
# This wrapper routes custom help to bashhelp, bash builtins to builtin help
|
||||
help() {
|
||||
case "${1:-}" in
|
||||
""|all|navigation|files|system|docker|git|network)
|
||||
@ -3680,6 +3838,68 @@ EOF
|
||||
fi
|
||||
print_warning "NOTE: '$USERNAME' must log out and back in to use Docker without sudo."
|
||||
log "Docker installation completed."
|
||||
# Offer dtop installation
|
||||
install_dtop_optional
|
||||
}
|
||||
|
||||
install_dtop_optional() {
|
||||
if sudo sh -c 'command -v dtop' >/dev/null 2>&1 || command -v dtop >/dev/null 2>&1; then
|
||||
print_info "dtop is already installed."
|
||||
return 0
|
||||
fi
|
||||
if ! confirm "Install 'dtop' (Docker container monitoring TUI)?"; then
|
||||
print_info "Skipping dtop installation."
|
||||
return 0
|
||||
fi
|
||||
print_info "Installing dtop for user '$USERNAME'..."
|
||||
local DTOP_INSTALLER="/tmp/dtop-installer.sh"
|
||||
if ! curl -fsSL "https://github.com/amir20/dtop/releases/latest/download/dtop-installer.sh" -o "$DTOP_INSTALLER"; then
|
||||
print_warning "Failed to download dtop installer. Continuing setup..."
|
||||
log "Failed to download dtop installer."
|
||||
return 0
|
||||
fi
|
||||
chmod +x "$DTOP_INSTALLER"
|
||||
trap 'rm -f "$DTOP_INSTALLER"' RETURN
|
||||
local USER_HOME
|
||||
USER_HOME=$(getent passwd "$USERNAME" | cut -d: -f6)
|
||||
local USER_LOCAL_BIN="$USER_HOME/.local/bin"
|
||||
if [[ ! -d "$USER_LOCAL_BIN" ]]; then
|
||||
print_info "Creating $USER_LOCAL_BIN..."
|
||||
if ! sudo -u "$USERNAME" mkdir -p "$USER_LOCAL_BIN"; then
|
||||
print_warning "Failed to create $USER_LOCAL_BIN. Skipping dtop."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if sudo -u "$USERNAME" bash "$DTOP_INSTALLER" < /dev/null >> "$LOG_FILE" 2>&1; then
|
||||
# Verify installation
|
||||
if [[ -f "$USER_LOCAL_BIN/dtop" ]]; then
|
||||
sudo -u "$USERNAME" chmod +x "$USER_LOCAL_BIN/dtop"
|
||||
local BASHRC="$USER_HOME/.bashrc"
|
||||
if [[ -f "$BASHRC" ]] && ! grep -q "\.local/bin" "$BASHRC"; then
|
||||
print_info "Adding ~/.local/bin to PATH in $BASHRC..."
|
||||
{
|
||||
echo ''
|
||||
echo '# Add local bin to PATH'
|
||||
# shellcheck disable=SC2016
|
||||
echo 'if [ -d "$HOME/.local/bin" ]; then PATH="$HOME/.local/bin:$PATH"; fi'
|
||||
} >> "$BASHRC"
|
||||
chown "$USERNAME:$USERNAME" "$BASHRC"
|
||||
if grep -q "\.local/bin" "$BASHRC"; then
|
||||
print_info "PATH configuration updated successfully."
|
||||
else
|
||||
print_warning "Failed to update PATH, but dtop is still installed."
|
||||
fi
|
||||
fi
|
||||
print_success "dtop installed successfully to $USER_LOCAL_BIN."
|
||||
log "dtop installed to $USER_LOCAL_BIN for user $USERNAME"
|
||||
else
|
||||
print_warning "dtop installer finished, but binary not found at $USER_LOCAL_BIN/dtop"
|
||||
log "dtop binary missing after user installation attempt."
|
||||
fi
|
||||
else
|
||||
print_warning "dtop installation script failed. Continuing setup..."
|
||||
log "dtop installation script failed."
|
||||
fi
|
||||
}
|
||||
|
||||
install_tailscale() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user