Compare commits
6 Commits
ed73b90ef0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d53788e2c6 | ||
|
|
e63cb83370 | ||
|
|
ad203a093c | ||
|
|
5cd803b90c | ||
|
|
72fefab22d | ||
|
|
ee752d4988 |
@@ -127,7 +127,7 @@ if [ -z "$REPO_FILE" ]; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mirror=''
|
mirror='nyist'
|
||||||
DRY_RUN=${DRY_RUN:-}
|
DRY_RUN=${DRY_RUN:-}
|
||||||
REPO_ONLY=${REPO_ONLY:-0}
|
REPO_ONLY=${REPO_ONLY:-0}
|
||||||
NO_AUTOSTART=${NO_AUTOSTART:-0}
|
NO_AUTOSTART=${NO_AUTOSTART:-0}
|
||||||
|
|||||||
100
linux-managements/menu.sh
Normal file
100
linux-managements/menu.sh
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
|
||||||
|
|
||||||
|
_NAMES=(); _DESCS=(); _URLS=()
|
||||||
|
add() { _NAMES+=("$1"); _DESCS+=("$2"); _URLS+=("$3"); }
|
||||||
|
|
||||||
|
# Read from terminal even when script is run via `curl ... | bash`.
|
||||||
|
prompt_read() {
|
||||||
|
local __var_name="$1"
|
||||||
|
local __prompt="$2"
|
||||||
|
local __input=""
|
||||||
|
if [ -r /dev/tty ]; then
|
||||||
|
read -r -p "$__prompt" __input < /dev/tty
|
||||||
|
else
|
||||||
|
read -r -p "$__prompt" __input
|
||||||
|
fi
|
||||||
|
printf -v "$__var_name" '%s' "$__input"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ════════════════════════════════════════════════════════════════════════════════
|
||||||
|
# CONFIGURATION — 在此处添加或修改脚本条目
|
||||||
|
# 用法: add "<显示名称>" "<脚本说明>" "<脚本 URL>"
|
||||||
|
# ════════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
add "Linux 初始化配置" \
|
||||||
|
"配置 HTTP 代理、SSH 密钥、安装 Homebrew 及常用软件、配置 Fish Shell、同步 Dotfiles" \
|
||||||
|
"https://git.mitsea.com/FlintyLemming/scripts-public/raw/branch/main/linux-managements/setup.sh"
|
||||||
|
|
||||||
|
add "安装 Docker Engine(中国大陆服务器)" \
|
||||||
|
"自动检测发行版,经由南洋理工镜像源安装 Docker Engine、Compose、Buildx 等组件" \
|
||||||
|
"https://git.mitsea.com/FlintyLemming/scripts-public/raw/branch/main/linux-managements/install-docker.sh"
|
||||||
|
|
||||||
|
add "配置 Snapper 快照" \
|
||||||
|
"为 Btrfs 子卷配置 Snapper 自动快照,按天/周/月/年策略保留快照并启用 systemd 定时器" \
|
||||||
|
"https://git.mitsea.com/FlintyLemming/scripts-public/raw/branch/main/linux-managements/setup-snapper.sh"
|
||||||
|
|
||||||
|
# ════════════════════════════════════════════════════════════════════════════════
|
||||||
|
# 以下为脚本逻辑,无需修改
|
||||||
|
# ════════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
draw_menu() {
|
||||||
|
echo -e "\n${BOLD}${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BOLD}${BLUE}║ Linux Management Scripts ║${NC}"
|
||||||
|
echo -e "${BOLD}${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}\n"
|
||||||
|
|
||||||
|
local total="${#_NAMES[@]}"
|
||||||
|
for (( i=0; i<total; i++ )); do
|
||||||
|
echo -e " ${BOLD}${CYAN}[$((i+1))]${NC} ${BOLD}${_NAMES[$i]}${NC}"
|
||||||
|
echo -e " ${YELLOW}${_DESCS[$i]}${NC}"
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e " ${BOLD}${RED}[0]${NC} 退出\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_script() {
|
||||||
|
local idx=$1
|
||||||
|
local name="${_NAMES[$idx]}"
|
||||||
|
local url="${_URLS[$idx]}"
|
||||||
|
|
||||||
|
echo -e "\n${GREEN}[OK]${NC} 正在执行: ${BOLD}$name${NC}"
|
||||||
|
echo -e "${CYAN}[INFO]${NC} 来源: $url\n"
|
||||||
|
echo -e "${BLUE}──────────────────────────────────────────────────────────────${NC}\n"
|
||||||
|
|
||||||
|
if command -v curl &>/dev/null; then
|
||||||
|
bash <(curl -fsSL "$url")
|
||||||
|
elif command -v wget &>/dev/null; then
|
||||||
|
bash <(wget -qO- "$url")
|
||||||
|
else
|
||||||
|
echo -e "${RED}[ERR]${NC} 未找到 curl 或 wget,无法下载脚本。" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local total="${#_NAMES[@]}"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
draw_menu
|
||||||
|
prompt_read choice "请选择要执行的脚本 [0-$total]: "
|
||||||
|
|
||||||
|
if [[ "$choice" == "0" ]]; then
|
||||||
|
echo -e "\n${CYAN}[INFO]${NC} 已退出。\n"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > total )); then
|
||||||
|
echo -e "\n${RED}[ERR]${NC} 无效选项,请输入 0 到 $total 之间的数字。\n"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_script $(( choice - 1 ))
|
||||||
|
break
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
@@ -11,6 +11,19 @@ warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|||||||
error() { echo -e "${RED}[ERR]${NC} $*" >&2; }
|
error() { echo -e "${RED}[ERR]${NC} $*" >&2; }
|
||||||
step() { echo -e "\n${BOLD}${BLUE}══ $* ${NC}"; }
|
step() { echo -e "\n${BOLD}${BLUE}══ $* ${NC}"; }
|
||||||
|
|
||||||
|
# Read from terminal even when script is run via `curl ... | bash`.
|
||||||
|
prompt_read() {
|
||||||
|
local __var_name="$1"
|
||||||
|
local __prompt="$2"
|
||||||
|
local __input=""
|
||||||
|
if [ -r /dev/tty ]; then
|
||||||
|
read -r -p "$__prompt" __input < /dev/tty
|
||||||
|
else
|
||||||
|
read -r -p "$__prompt" __input
|
||||||
|
fi
|
||||||
|
printf -v "$__var_name" '%s' "$__input"
|
||||||
|
}
|
||||||
|
|
||||||
# ─── OS Detection ─────────────────────────────────────────────────────────────
|
# ─── OS Detection ─────────────────────────────────────────────────────────────
|
||||||
detect_os() {
|
detect_os() {
|
||||||
if [ -f /etc/os-release ]; then
|
if [ -f /etc/os-release ]; then
|
||||||
@@ -43,11 +56,11 @@ detect_os() {
|
|||||||
setup_proxy() {
|
setup_proxy() {
|
||||||
step "HTTP Proxy"
|
step "HTTP Proxy"
|
||||||
echo -e "Do you want to configure an HTTP proxy for this session? ${YELLOW}(helps with Homebrew downloads)${NC}"
|
echo -e "Do you want to configure an HTTP proxy for this session? ${YELLOW}(helps with Homebrew downloads)${NC}"
|
||||||
read -rp "Configure proxy? [y/N] " ans
|
prompt_read ans "Configure proxy? [y/N] "
|
||||||
case "$ans" in
|
case "$ans" in
|
||||||
[Yy]*)
|
[Yy]*)
|
||||||
while true; do
|
while true; do
|
||||||
read -rp "Enter proxy URL (e.g. http://192.168.1.1:7890): " proxy_url
|
prompt_read proxy_url "Enter proxy URL (e.g. http://192.168.1.1:7890): "
|
||||||
if [[ "$proxy_url" =~ ^https?://[^:]+:[0-9]+$ ]]; then
|
if [[ "$proxy_url" =~ ^https?://[^:]+:[0-9]+$ ]]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -65,6 +78,26 @@ setup_proxy() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ─── Proxy-aware sudo ─────────────────────────────────────────────────────────
|
||||||
|
# sudo's default env_reset policy strips proxy variables.
|
||||||
|
# This wrapper forwards them so that package managers / curl under sudo
|
||||||
|
# can reach the network through the configured proxy.
|
||||||
|
psudo() {
|
||||||
|
local -a env_args=()
|
||||||
|
[ -n "${http_proxy:-}" ] && env_args+=("http_proxy=$http_proxy")
|
||||||
|
[ -n "${https_proxy:-}" ] && env_args+=("https_proxy=$https_proxy")
|
||||||
|
[ -n "${HTTP_PROXY:-}" ] && env_args+=("HTTP_PROXY=$HTTP_PROXY")
|
||||||
|
[ -n "${HTTPS_PROXY:-}" ] && env_args+=("HTTPS_PROXY=$HTTPS_PROXY")
|
||||||
|
[ -n "${no_proxy:-}" ] && env_args+=("no_proxy=$no_proxy")
|
||||||
|
[ -n "${NO_PROXY:-}" ] && env_args+=("NO_PROXY=$NO_PROXY")
|
||||||
|
|
||||||
|
if [ ${#env_args[@]} -gt 0 ]; then
|
||||||
|
sudo env "${env_args[@]}" "$@"
|
||||||
|
else
|
||||||
|
sudo "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ─── SSH Key Setup ────────────────────────────────────────────────────────────
|
# ─── SSH Key Setup ────────────────────────────────────────────────────────────
|
||||||
setup_ssh_key() {
|
setup_ssh_key() {
|
||||||
step "SSH Key Configuration"
|
step "SSH Key Configuration"
|
||||||
@@ -91,7 +124,7 @@ setup_ssh_key() {
|
|||||||
|
|
||||||
local added=0
|
local added=0
|
||||||
while true; do
|
while true; do
|
||||||
read -rp "Public key (or blank to finish): " pubkey
|
prompt_read pubkey "Public key (or blank to finish): "
|
||||||
[[ -z "$pubkey" ]] && break
|
[[ -z "$pubkey" ]] && break
|
||||||
if [[ "$pubkey" =~ ^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|sk-ssh-ed25519) ]]; then
|
if [[ "$pubkey" =~ ^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp256|sk-ssh-ed25519) ]]; then
|
||||||
if grep -qF "$pubkey" ~/.ssh/authorized_keys 2>/dev/null; then
|
if grep -qF "$pubkey" ~/.ssh/authorized_keys 2>/dev/null; then
|
||||||
@@ -119,10 +152,10 @@ setup_ssh_key() {
|
|||||||
sudo_set_sshd() {
|
sudo_set_sshd() {
|
||||||
local key="$1" val="$2"
|
local key="$1" val="$2"
|
||||||
# Uncomment or add the line
|
# Uncomment or add the line
|
||||||
if sudo grep -qE "^\s*#?\s*${key}\s" "$SSHD_CONF"; then
|
if psudo grep -qE "^\s*#?\s*${key}\s" "$SSHD_CONF"; then
|
||||||
sudo sed -i -E "s|^\s*#?\s*(${key})\s+.*|\1 ${val}|" "$SSHD_CONF"
|
psudo sed -i -E "s|^\s*#?\s*(${key})\s+.*|\1 ${val}|" "$SSHD_CONF"
|
||||||
else
|
else
|
||||||
echo "${key} ${val}" | sudo tee -a "$SSHD_CONF" > /dev/null
|
echo "${key} ${val}" | psudo tee -a "$SSHD_CONF" > /dev/null
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +171,7 @@ setup_ssh_key() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Restart SSH
|
# Restart SSH
|
||||||
if sudo systemctl restart ssh 2>/dev/null || sudo systemctl restart sshd 2>/dev/null; then
|
if psudo systemctl restart ssh 2>/dev/null || psudo systemctl restart sshd 2>/dev/null; then
|
||||||
success "SSH service restarted"
|
success "SSH service restarted"
|
||||||
else
|
else
|
||||||
warn "Could not restart SSH service automatically — please restart it manually"
|
warn "Could not restart SSH service automatically — please restart it manually"
|
||||||
@@ -153,9 +186,9 @@ install_git() {
|
|||||||
fi
|
fi
|
||||||
info "Installing git via system package manager ..."
|
info "Installing git via system package manager ..."
|
||||||
case "$DISTRO" in
|
case "$DISTRO" in
|
||||||
aosc) sudo oma install -y git ;;
|
aosc) psudo oma install -y git ;;
|
||||||
debian|ubuntu) sudo apt-get update -qq && sudo apt-get install -y git ;;
|
debian|ubuntu) psudo apt-get update -qq && psudo apt-get install -y git ;;
|
||||||
fedora) sudo dnf install -y git ;;
|
fedora) psudo dnf install -y git ;;
|
||||||
esac
|
esac
|
||||||
success "git installed"
|
success "git installed"
|
||||||
}
|
}
|
||||||
@@ -227,7 +260,7 @@ install_packages() {
|
|||||||
case "$DISTRO" in
|
case "$DISTRO" in
|
||||||
aosc)
|
aosc)
|
||||||
info "Installing packages via oma ..."
|
info "Installing packages via oma ..."
|
||||||
sudo oma install -y git fish eza fastfetch btop docker docker-compose-plugin docker-buildx-plugin
|
psudo oma install -y git fish eza fastfetch btop docker docker-compose docker-buildx
|
||||||
success "All packages installed via oma"
|
success "All packages installed via oma"
|
||||||
;;
|
;;
|
||||||
debian|ubuntu)
|
debian|ubuntu)
|
||||||
@@ -255,7 +288,7 @@ setup_fish() {
|
|||||||
|
|
||||||
# Add fish to /etc/shells if not already present
|
# Add fish to /etc/shells if not already present
|
||||||
if ! grep -qF "$FISH_PATH" /etc/shells; then
|
if ! grep -qF "$FISH_PATH" /etc/shells; then
|
||||||
echo "$FISH_PATH" | sudo tee -a /etc/shells > /dev/null
|
echo "$FISH_PATH" | psudo tee -a /etc/shells > /dev/null
|
||||||
success "Added $FISH_PATH to /etc/shells"
|
success "Added $FISH_PATH to /etc/shells"
|
||||||
else
|
else
|
||||||
info "$FISH_PATH already in /etc/shells"
|
info "$FISH_PATH already in /etc/shells"
|
||||||
@@ -266,7 +299,7 @@ setup_fish() {
|
|||||||
if [ "$current_shell" = "$FISH_PATH" ]; then
|
if [ "$current_shell" = "$FISH_PATH" ]; then
|
||||||
info "fish is already the default shell"
|
info "fish is already the default shell"
|
||||||
else
|
else
|
||||||
sudo chsh -s "$FISH_PATH" "$USER"
|
psudo chsh -s "$FISH_PATH" "$USER"
|
||||||
success "Default shell changed to fish ($FISH_PATH)"
|
success "Default shell changed to fish ($FISH_PATH)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -296,20 +329,9 @@ install_docker() {
|
|||||||
if command -v docker &>/dev/null; then
|
if command -v docker &>/dev/null; then
|
||||||
info "Docker already installed ($(docker --version)), skipping"
|
info "Docker already installed ($(docker --version)), skipping"
|
||||||
else
|
else
|
||||||
echo ""
|
curl -fsSL https://git.mitsea.com/FlintyLemming/scripts-public/raw/branch/main/linux-managements/install-docker.sh \
|
||||||
echo -e "Use a ${BOLD}domestic mirror${NC} for Docker installation? ${YELLOW}(recommended in China)${NC}"
|
-o /tmp/install-docker.sh
|
||||||
read -rp "Use mirror? [y/N] " use_mirror
|
psudo sh /tmp/install-docker.sh
|
||||||
case "$use_mirror" in
|
|
||||||
[Yy]*)
|
|
||||||
curl -fsSL https://git.mitsea.com/FlintyLemming/scripts-public/raw/branch/main/linux-managements/install-docker.sh \
|
|
||||||
-o /tmp/install-docker.sh
|
|
||||||
sudo sh /tmp/install-docker.sh --mirror nyist
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
|
|
||||||
sudo sh /tmp/get-docker.sh
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
success "Docker installed"
|
success "Docker installed"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
@@ -318,9 +340,9 @@ install_docker() {
|
|||||||
info "Docker already installed ($(docker --version)), skipping"
|
info "Docker already installed ($(docker --version)), skipping"
|
||||||
else
|
else
|
||||||
info "Setting up Docker CE repository ..."
|
info "Setting up Docker CE repository ..."
|
||||||
sudo curl -fsSL https://download.docker.com/linux/fedora/docker-ce.repo \
|
psudo curl -fsSL https://download.docker.com/linux/fedora/docker-ce.repo \
|
||||||
-o /etc/yum.repos.d/docker-ce.repo
|
-o /etc/yum.repos.d/docker-ce.repo
|
||||||
sudo dnf install -y docker-ce docker-ce-cli containerd.io \
|
psudo dnf install -y docker-ce docker-ce-cli containerd.io \
|
||||||
docker-compose-plugin docker-buildx-plugin
|
docker-compose-plugin docker-buildx-plugin
|
||||||
success "Docker installed"
|
success "Docker installed"
|
||||||
fi
|
fi
|
||||||
@@ -335,21 +357,21 @@ docker_no_root() {
|
|||||||
info "Configuring Docker for non-root usage ..."
|
info "Configuring Docker for non-root usage ..."
|
||||||
|
|
||||||
if ! getent group docker > /dev/null 2>&1; then
|
if ! getent group docker > /dev/null 2>&1; then
|
||||||
sudo groupadd docker
|
psudo groupadd docker
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if id -nG "$USER" | grep -qw docker; then
|
if id -nG "$USER" | grep -qw docker; then
|
||||||
info "User '$USER' is already in the docker group"
|
info "User '$USER' is already in the docker group"
|
||||||
else
|
else
|
||||||
sudo usermod -aG docker "$USER"
|
psudo usermod -aG docker "$USER"
|
||||||
success "User '$USER' added to the docker group"
|
success "User '$USER' added to the docker group"
|
||||||
warn "Log out and back in for the group change to take effect"
|
warn "Log out and back in for the group change to take effect"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! sudo systemctl is-enabled --quiet docker 2>/dev/null; then
|
if ! psudo systemctl is-enabled --quiet docker 2>/dev/null; then
|
||||||
sudo systemctl enable docker
|
psudo systemctl enable docker
|
||||||
fi
|
fi
|
||||||
sudo systemctl start docker
|
psudo systemctl start docker
|
||||||
success "Docker service running"
|
success "Docker service running"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,6 +434,7 @@ ensure_sudo() {
|
|||||||
# Keep sudo ticket alive in the background for the duration of the script
|
# Keep sudo ticket alive in the background for the duration of the script
|
||||||
( while true; do sudo -n true 2>/dev/null; sleep 50; done ) &
|
( while true; do sudo -n true 2>/dev/null; sleep 50; done ) &
|
||||||
SUDO_KEEPALIVE_PID=$!
|
SUDO_KEEPALIVE_PID=$!
|
||||||
|
# Note: ensure_sudo uses raw sudo intentionally — psudo is not defined yet
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -456,7 +479,7 @@ main() {
|
|||||||
configure_ssh_config
|
configure_ssh_config
|
||||||
|
|
||||||
step "Starting Docker"
|
step "Starting Docker"
|
||||||
if sudo systemctl start docker; then
|
if psudo systemctl start docker; then
|
||||||
success "Docker started"
|
success "Docker started"
|
||||||
else
|
else
|
||||||
warn "Could not start Docker — please start it manually"
|
warn "Could not start Docker — please start it manually"
|
||||||
|
|||||||
Reference in New Issue
Block a user