Breaking it down
This commit is contained in:
46
scripts/go.sh
Normal file
46
scripts/go.sh
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Go (GVM)...${NC}"
|
||||
|
||||
# 1. Install GVM dependencies
|
||||
unalias cd 2>/dev/null || true
|
||||
|
||||
# 2. Install GVM if missing
|
||||
if [ ! -d "$HOME/.gvm" ]; then
|
||||
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
|
||||
fi
|
||||
|
||||
# 3. Load GVM
|
||||
[[ -s "$HOME/.gvm/scripts/gvm" ]] && source "$HOME/.gvm/scripts/gvm"
|
||||
|
||||
# 4. Install Go
|
||||
# Use a known stable version that exists. 1.24.11 is speculative. 1.24.0 is real.
|
||||
TARGET_GO="go1.24.0"
|
||||
|
||||
if command -v gvm &> /dev/null; then
|
||||
if [[ $(gvm list) != *"$TARGET_GO"* ]]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing $TARGET_GO...${NC}"
|
||||
|
||||
# Try Binary install first (Fastest/Safest)
|
||||
gvm install "$TARGET_GO" -B || {
|
||||
echo -e "${RED} LOG: Binary failed. Bootstrapping via go1.22.9...${NC}"
|
||||
gvm install go1.22.9 -B
|
||||
gvm use go1.22.9
|
||||
gvm install "$TARGET_GO"
|
||||
}
|
||||
|
||||
gvm use "$TARGET_GO" --default
|
||||
echo -e "${GREEN} LOG: Go setup complete.$(go version)${NC}"
|
||||
else
|
||||
echo -e "${GREEN} LOG: $TARGET_GO already installed.${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED} ERROR: GVM failed to load.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
33
scripts/node.sh
Normal file
33
scripts/node.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
set -e # Exit on error
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Node.js (NVM)...${NC}"
|
||||
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
|
||||
# 1. Install NVM
|
||||
if [ ! -d "$NVM_DIR" ]; then
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
|
||||
fi
|
||||
|
||||
# 2. Load NVM
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
|
||||
# 3. Install Node
|
||||
if command -v nvm &> /dev/null; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing LTS...${NC}"
|
||||
nvm install --lts
|
||||
nvm use --lts
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Global Tools...${NC}"
|
||||
# set +e is safer for npm global installs which can be noisy
|
||||
set +e
|
||||
npm install -g pnpm yarn
|
||||
set -e
|
||||
|
||||
echo -e "${GREEN} LOG: Node setup complete.$(node -v)${NC}"
|
||||
fi
|
||||
115
scripts/provision.sh
Executable file
115
scripts/provision.sh
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
GREEN='\033[1;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
DEFAULT_USER="mangopig"
|
||||
DEFAULT_UID="1000"
|
||||
DEFAULT_GID="1000"
|
||||
|
||||
# Root Check
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Please run this script as root.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# OS Detection
|
||||
echo -e "${YELLOW}LOG: Detecting OS...${NC}"
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
fi
|
||||
|
||||
# IP Address Retrieval
|
||||
echo -e "${YELLOW}LOG: Determining primary IPv4 address...${NC}"
|
||||
if command -v hostname >/dev/null 2>&1 && hostname -I >/dev/null 2>&1; then
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
elif command -v ip >/dev/null 2>&1; then
|
||||
IP=$(ip route get 1.1.1.1 2>/dev/null | awk '/src/ {print $NF; exit}')
|
||||
elif command -v ifconfig >/dev/null 2>&1; then
|
||||
IP=$(ifconfig | awk '/inet /{print $2}' | grep -v '^127' | head -n1)
|
||||
else
|
||||
IP="127.0.0.1"
|
||||
fi
|
||||
|
||||
# Install Prerequisites (Git, Make, Zsh, Sudo)
|
||||
echo -e "${YELLOW}LOG: Updating system and installing base tools...${NC}"
|
||||
|
||||
if [ "$OS" == "arch" ] || [ "$OS" == "manjaro" ]; then
|
||||
pacman -Sy --noconfirm git make curl zsh sudo
|
||||
SUDO_GROUP="wheel"
|
||||
elif [ "$OS" == "ubuntu" ] || [ "$OS" == "debian" ]; then
|
||||
apt-get update
|
||||
apt-get install -y git make curl sudo
|
||||
SUDO_GROUP="sudo"
|
||||
else
|
||||
echo -e "${RED}Unsupported OS: $OS${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Interactive Prompts
|
||||
if [ -t 0 ]; then
|
||||
echo -e "${GREEN}---------------------------------------${NC}"
|
||||
echo -e "${GREEN} USER PROVISIONING WIZARD ${NC}"
|
||||
echo -e "${GREEN}---------------------------------------${NC}"
|
||||
|
||||
read -p "Enter Username (default: $DEFAULT_USER): " INPUT_USER
|
||||
USERNAME=${INPUT_USER:-$DEFAULT_USER}
|
||||
|
||||
read -p "Enter UID (default: $DEFAULT_UID): " INPUT_UID
|
||||
USER_UID=${INPUT_UID:-$DEFAULT_UID}
|
||||
|
||||
read -p "Enter GID (default: $DEFAULT_GID): " INPUT_GID
|
||||
USER_GID=${INPUT_GID:-$DEFAULT_GID}
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Non-interactive session detected. Using defaults.${NC}"
|
||||
# Allow Environment Variables to override defaults in Docker/Headless
|
||||
USERNAME=${USERNAME:-$DEFAULT_USER}
|
||||
USER_UID=${USER_UID:-$DEFAULT_UID}
|
||||
USER_GID=${USER_GID:-$DEFAULT_GID}
|
||||
fi
|
||||
|
||||
# Group Creation
|
||||
if getent group "$USER_GID" >/dev/null; then
|
||||
echo -e "${YELLOW}LOG: Group with GID $USER_GID already exists. Using it.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Creating group $USERNAME with GID $USER_GID...${NC}"
|
||||
groupadd -g "$USER_GID" "$USERNAME"
|
||||
fi
|
||||
|
||||
# User Creation
|
||||
if id "$USERNAME" &>/dev/null; then
|
||||
echo -e "${YELLOW}LOG: User $USERNAME already exists. Skipping creation.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Creating user $USERNAME...${NC}"
|
||||
|
||||
# Create user with specific UID, GID, Groups, and Shell
|
||||
useradd -m -u "$USER_UID" -g "$USER_GID" -G "$SUDO_GROUP" -s "$ZSH_PATH" "$USERNAME"
|
||||
|
||||
echo -e "${GREEN}LOG: Setting password for $USERNAME...${NC}"
|
||||
passwd "$USERNAME"
|
||||
fi
|
||||
|
||||
# Sudo Configuration (Passwordless)
|
||||
echo -e "${YELLOW}LOG: Configuring passwordless sudo...${NC}"
|
||||
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/90-$USERNAME"
|
||||
chmod 0440 "/etc/sudoers.d/90-$USERNAME"
|
||||
|
||||
# Arch Specific: Uncomment wheel in sudoers if not already active
|
||||
if [ "$OS" == "arch" ]; then
|
||||
# Ensure the 'wheel' group is actually enabled in the main config if drop-in fails
|
||||
sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
|
||||
fi
|
||||
|
||||
# Cloning Dotfiles
|
||||
echo -e "${YELLOW}LOG: Cloning dotfiles for $USERNAME...${NC}"
|
||||
sudo -u "$USERNAME" git clone https://git.mangopig.tech/MangoPig/Dot-Zsh.git "/home/$USERNAME/Config/Dot-Zsh"
|
||||
|
||||
|
||||
echo -e "${GREEN}✅ Server Provisioned!"
|
||||
echo -e "${GREEN} sudo su - $USERNAME${NC} OR logout and SSH back in as $USERNAME@$IP.${NC}"
|
||||
echo -e "${GREEN} Then run cd ~/Config/Dot-Zsh && make setup ${NC}"
|
||||
15
scripts/python.sh
Normal file
15
scripts/python.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Bold Colors
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
RED='\033[1;31m'
|
||||
GREEN='\033[1;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Python Setup
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Python environment...${NC}"
|
||||
|
||||
# MiniConda Installation
|
||||
23
scripts/rust.sh
Normal file
23
scripts/rust.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Rust (Rustup)...${NC}"
|
||||
|
||||
# 1. Install Rustup
|
||||
if ! command -v rustup &> /dev/null; then
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
fi
|
||||
|
||||
# 2. Source Environment
|
||||
[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env"
|
||||
|
||||
# 3. Update to Stable
|
||||
if command -v cargo &> /dev/null; then
|
||||
rustup default stable
|
||||
rustup update
|
||||
echo -e "${GREEN} LOG: Rust setup complete.$(cargo --version)${NC}"
|
||||
fi
|
||||
116
scripts/setup.sh
Executable file
116
scripts/setup.sh
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Initializing Base System Layer...${NC}"
|
||||
|
||||
# OS Detection
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
fi
|
||||
|
||||
# Confirm Architecture
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ]; then
|
||||
echo -e "${RED} ERROR: Unsupported architecture: $ARCH${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Package Installation (OS Dependencies)
|
||||
# Note: Removed 'go', 'npm', 'cargo' - these are handled by specific scripts
|
||||
PACKAGES=(
|
||||
curl wget git sudo zsh tmux unzip tar gzip
|
||||
build-essential openssl python bison mercurial
|
||||
ripgrep fd bat fzf jq btop httpie gnupg zoxide stow
|
||||
bind nmap socat tcpdump net-tools strace gdb hexyl
|
||||
rclone
|
||||
# 'eza' is REMOVED from here for Ubuntu logic below
|
||||
)
|
||||
|
||||
if [ "$OS" == "arch" ] || [ "$OS" == "manjaro" ]; then
|
||||
# Arch has eza in the community repo
|
||||
sudo pacman -Sy --noconfirm --needed "${PACKAGES[@]}" eza base-devel
|
||||
elif [ "$OS" == "ubuntu" ] || [ "$OS" == "debian" ]; then
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${PACKAGES[@]}" bsdmainutils pkg-config cmake
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# EZA BINARY INSTALL (Ubuntu/Debian)
|
||||
# -----------------------------------------------------------------
|
||||
if ! command -v eza &> /dev/null; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Fetching eza binary (skipping compilation)...${NC}"
|
||||
|
||||
# 1. Define Version (Check releases page for latest)
|
||||
EZA_VER="v0.18.11"
|
||||
EZA_URL="https://github.com/eza-community/eza/releases/download/${EZA_VER}/eza_x86_64-unknown-linux-gnu.tar.gz"
|
||||
|
||||
# 2. Download and Extract directly to a temp location
|
||||
wget -qO- "$EZA_URL" | tar xz -C /tmp
|
||||
|
||||
# 3. Move to local bin (No sudo needed if ~/.local/bin is in PATH)
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
mv /tmp/eza "$HOME/.local/bin/"
|
||||
chmod +x "$HOME/.local/bin/eza"
|
||||
|
||||
echo -e "${GREEN} LOG: eza installed to ~/.local/bin${NC}"
|
||||
fi
|
||||
fi
|
||||
# 3. Docker Installation
|
||||
if command -v docker &> /dev/null; then
|
||||
echo -e "${GREEN} LOG: Docker is already installed.${NC}"
|
||||
else
|
||||
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
|
||||
echo -e "${RED} LOG: WSL Detected! Skipping Native Docker.${NC}"
|
||||
echo -e "${RED} >>> Please install Docker Desktop on Windows.${NC}"
|
||||
else
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Native Docker...${NC}"
|
||||
if [ "$OS" == "arch" ]; then
|
||||
sudo pacman -S --noconfirm --needed docker docker-compose
|
||||
sudo systemctl enable --now docker
|
||||
elif [ "$OS" == "ubuntu" ]; then
|
||||
# (Simplified for brevity - standard Docker install logic)
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
fi
|
||||
|
||||
# Add user to group
|
||||
sudo usermod -aG docker $(whoami)
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. Zsh & Configuration
|
||||
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Oh My Zsh...${NC}"
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
||||
fi
|
||||
|
||||
# Plugins
|
||||
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
||||
mkdir -p "$ZSH_CUSTOM/plugins"
|
||||
[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ] && git clone https://github.com/zsh-users/zsh-syntax-highlighting.git "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
|
||||
[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ] && git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
|
||||
|
||||
# 5. Git Credentials (WSL Bridge)
|
||||
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
|
||||
GCM_WIN="/mnt/c/Program Files/Git/mingw64/bin/git-credential-manager.exe"
|
||||
[ -f "$GCM_WIN" ] && git config --global credential.helper "! \"$GCM_WIN\""
|
||||
else
|
||||
git config --global credential.helper 'cache --timeout=43200'
|
||||
fi
|
||||
|
||||
# 6. Cleanup & Secrets
|
||||
rm -f "$HOME/.zshrc" "$HOME/.zsh_aliases"
|
||||
touch "$HOME/.zsh_secrets"
|
||||
|
||||
# 7. Set Shell
|
||||
if [ "$SHELL" != "$(which zsh)" ]; then
|
||||
sudo chsh -s "$(which zsh)" $(whoami)
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} LOG: Base System Setup Complete.${NC}"
|
||||
116
scripts/storagebox.sh
Normal file
116
scripts/storagebox.sh
Normal file
@@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
SECRETS_FILE="$HOME/.zsh_secrets"
|
||||
REMOTE_NAME="hetzner-box"
|
||||
|
||||
# Dependency Check
|
||||
if ! command -v rclone &> /dev/null; then
|
||||
echo -e "${RED}Error: rclone is not installed.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Load Secrets
|
||||
if [ -f "$SECRETS_FILE" ]; then
|
||||
source "$SECRETS_FILE"
|
||||
fi
|
||||
|
||||
# Configure Remote (If missing)
|
||||
if ! rclone listremotes | grep -q "^${REMOTE_NAME}:$"; then
|
||||
echo -e "${BLUE}Configuration missing. Starting setup...${NC}"
|
||||
|
||||
if [ -z "$HETZNER_USER" ]; then
|
||||
DEFAULT_USER="u513875"
|
||||
read -p "Enter Username [$DEFAULT_USER]: " INPUT_USER
|
||||
HETZNER_USER="${INPUT_USER:-$DEFAULT_USER}"
|
||||
fi
|
||||
|
||||
if [ -z "$HETZNER_HOST" ]; then
|
||||
DEFAULT_HOST="${HETZNER_USER}.your-storagebox.de"
|
||||
read -p "Enter Host [$DEFAULT_HOST]: " INPUT_HOST
|
||||
HETZNER_HOST="${INPUT_HOST:-$DEFAULT_HOST}"
|
||||
fi
|
||||
|
||||
if [ -z "$HETZNER_PASS" ]; then
|
||||
echo -e "${YELLOW}Note: Passwords are obscured in config, but saving to secrets file uses plain text.${NC}"
|
||||
read -s -p "Enter Password: " HETZNER_PASS
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Save to secrets
|
||||
if ! grep -q "HETZNER_USER" "$SECRETS_FILE" 2>/dev/null; then
|
||||
echo -e "${BLUE}Saving credentials to $SECRETS_FILE...${NC}"
|
||||
{
|
||||
echo ""
|
||||
echo "# Hetzner Storage Box"
|
||||
echo "export HETZNER_USER=\"$HETZNER_USER\""
|
||||
echo "export HETZNER_HOST=\"$HETZNER_HOST\""
|
||||
echo "export HETZNER_PASS=\"$HETZNER_PASS\""
|
||||
} >> "$SECRETS_FILE"
|
||||
fi
|
||||
|
||||
OBSCURED_PASS=$(rclone obscure "$HETZNER_PASS")
|
||||
rclone config create "$REMOTE_NAME" sftp \
|
||||
host "$HETZNER_HOST" \
|
||||
user "$HETZNER_USER" \
|
||||
pass "$OBSCURED_PASS" \
|
||||
port 23 \
|
||||
--non-interactive
|
||||
|
||||
echo -e "${GREEN}Configuration created!${NC}"
|
||||
fi
|
||||
|
||||
# Interactive Menu
|
||||
echo -e "${BLUE}--- Hetzner Storage Box Manager ---${NC}"
|
||||
echo "1) List files (ls)"
|
||||
echo "2) Upload (Copy LOCAL -> REMOTE)"
|
||||
echo "3) Download (Copy REMOTE -> LOCAL)"
|
||||
echo "q) Quit"
|
||||
|
||||
read -p "Select option: " OPTION
|
||||
|
||||
case $OPTION in
|
||||
1)
|
||||
read -p "Enter depth [1]: " INPUT_DEPTH
|
||||
DEPTH="${INPUT_DEPTH:-1}"
|
||||
echo -e "${BLUE}Listing files on Hetzner...${NC}"
|
||||
rclone ls "${REMOTE_NAME}:" --max-depth "$DEPTH"
|
||||
;;
|
||||
2)
|
||||
read -p "Enter local folder/file to upload: " LOCAL_PATH
|
||||
LOCAL_PATH=${LOCAL_PATH%/}
|
||||
|
||||
read -p "Enter remote destination folder (e.g. Backup): " REMOTE_FOLDER
|
||||
REMOTE_FOLDER=${REMOTE_FOLDER#/}
|
||||
REMOTE_FOLDER=${REMOTE_FOLDER%/}
|
||||
|
||||
echo -e "${YELLOW}Uploading '$LOCAL_PATH' to '${REMOTE_NAME}:$REMOTE_FOLDER'...${NC}"
|
||||
rclone copy "$LOCAL_PATH" "${REMOTE_NAME}:$REMOTE_FOLDER" -P
|
||||
;;
|
||||
3)
|
||||
echo -e "${BLUE}Contents of Root:${NC}"
|
||||
rclone lsd "${REMOTE_NAME}:"
|
||||
|
||||
read -p "Enter remote path to download (e.g. models/Test): " REMOTE_PATH
|
||||
REMOTE_PATH=${REMOTE_PATH#/}
|
||||
|
||||
read -p "Enter local destination folder: " LOCAL_DEST
|
||||
mkdir -p "$LOCAL_DEST"
|
||||
|
||||
echo -e "${YELLOW}Downloading '${REMOTE_NAME}:$REMOTE_PATH' to '$LOCAL_DEST'...${NC}"
|
||||
rclone copy "${REMOTE_NAME}:$REMOTE_PATH" "$LOCAL_DEST" -P
|
||||
;;
|
||||
q)
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option"
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user