first commit

This commit is contained in:
root
2026-02-17 17:28:37 +08:00
commit 192078dc3b
52 changed files with 18158 additions and 0 deletions

64
.gitignore vendored Normal file
View File

@@ -0,0 +1,64 @@
# Node/React
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
build/
dist/
coverage/
.env.local
.env.development.local
.env.test.local
.env.production.local
# Go
*.exe
*.exe~
*.test
*.out
*.dll
*.so
*.dylib
vendor/
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
ENV/
*.egg-info/
dist/
build/
# 数据文件
data/data.json
*.db
*.sqlite
# 日志文件
*.log
logs/
# 操作系统
.DS_Store
Thumbs.db
desktop.ini
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
.project
.classpath
.settings/
# 其他
*.bak
*.tmp
*.temp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

179
docker-info/AGENTS.md Normal file
View File

@@ -0,0 +1,179 @@
# AGENTS.md - Agentic Coding Guidelines
## Project Overview
This is a Bash shell script project for collecting Docker and server information on Debian/Ubuntu systems.
**Primary Language**: Bash
**Main File**: `docker-info.sh`
---
## Build/Lint/Test Commands
Since this is a Bash script project without a formal build system, use these commands:
### Linting
```bash
# ShellCheck (static analysis for bash scripts)
shellcheck docker-info.sh
# Check for syntax errors
bash -n docker-info.sh
```
### Testing
```bash
# Run the script (requires Docker to be installed for full functionality)
bash docker-info.sh
# Or make executable and run directly
chmod +x docker-info.sh
./docker-info.sh
```
### Single Test Pattern
```bash
# Test specific functions by sourcing and calling them
source docker-info.sh && command_exists docker
source docker-info.sh && print_success "test message"
```
---
## Code Style Guidelines
### General Bash Style
- **Shebang**: Always use `#!/usr/bin/env bash`
- **Set options**: Use `set -euo pipefail` at the start of scripts
- `-e`: Exit on error
- `-u`: Exit on undefined variables
- `-o pipefail`: Pipeline fails if any command fails
### Formatting
- **Indentation**: 4 spaces (no tabs)
- **Line length**: Keep lines under 100 characters
- **Quotes**: Always quote variables: `"$variable"` not `$variable`
- **Functions**: Use `snake_case` for function names
- **Constants**: Use `UPPER_CASE` for constants and color codes
### Naming Conventions
```bash
# Functions - snake_case
print_header() { }
get_server_info() { }
check_root() { }
# Variables - descriptive names
local container_output
local cpu_count
local total_mem
# Constants - UPPER_CASE
readonly RED='\033[0;31m'
readonly HEADER_COLOR="${BRIGHT_CYAN}"
```
### Error Handling
```bash
# Always check command existence before use
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Use proper exit codes
if ! command_exists docker; then
print_error "Docker未安装"
return 1
fi
# Redirect errors appropriately
docker ps 2>/dev/null || print_warning "无法列出容器"
```
### Function Structure
```bash
# Document functions with comments
# 获取服务器信息
get_server_info() {
print_header "服务器信息"
# Use local for function-scoped variables
local cpu_count=$(grep -c '^processor' /proc/cpuinfo)
local cpu_model=$(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)
# Call other functions for output
print_key_value "CPU核心数" "$cpu_count"
}
```
### Color/Styling Code
- Define color codes as constants at the top of the file
- Group related colors together (basic, bright, background, styles)
- Use descriptive names: `HEADER_COLOR`, `SUCCESS_COLOR`, `ERROR_COLOR`
- Always reset colors with `${NC}` after colored output
### Output Patterns
```bash
# Use helper functions for consistent output
print_header() # Boxed titles
print_section() # Section headers with arrows
print_key_value() # Key: Value pairs
print_success() # Green checkmark
print_warning() # Yellow warning
print_error() # Red X
```
### Comments
- Use Chinese comments to match existing codebase style
- Keep comments concise and meaningful
- Comment complex logic or non-obvious behavior
---
## Testing Checklist
Before submitting changes:
- [ ] Run `shellcheck docker-info.sh` with no warnings
- [ ] Run `bash -n docker-info.sh` for syntax check
- [ ] Test on a system with Docker installed
- [ ] Test on a system without Docker (should handle gracefully)
- [ ] Verify all color output displays correctly
- [ ] Check that tables align properly
---
## Dependencies
**Required**: None (uses standard POSIX utilities)
**Optional but recommended**:
- `jq` - For better JSON parsing of Docker info
- `shellcheck` - For linting
---
## File Structure
```
/shumengya/project/bash/docker-info/
└── docker-info.sh # Main script file
```
---
## Security Notes
- This script may require root access for some Docker operations
- Always validate user input if added in the future
- Use proper quoting to prevent word splitting and globbing
- Sanitize any data passed to eval or similar dangerous operations

253
docker-info/docker-info.sh Executable file
View File

@@ -0,0 +1,253 @@
#!/usr/bin/env bash
# =============================================================================
# Docker Info Collector - Single Column Edition
# =============================================================================
set -euo pipefail
# =============================================================================
# Colors
# =============================================================================
readonly NC='\033[0m'
readonly GRAY='\033[0;90m'
readonly CYAN='\033[0;36m'
readonly GREEN='\033[1;32m'
readonly YELLOW='\033[1;33m'
readonly WHITE='\033[1;37m'
readonly DIM='\033[2m'
readonly C_HEADER="${CYAN}"
readonly C_SECTION="${YELLOW}"
readonly C_KEY="${WHITE}"
readonly C_VALUE="${CYAN}"
readonly C_OK="${GREEN}"
readonly C_WARN="${YELLOW}"
readonly C_ERR="\033[1;31m"
readonly C_DIM="${GRAY}"
# Separator line (thick line style)
SEP_LINE="${C_DIM}══════════════════════════════════════════════════════════════════════════════${NC}"
# =============================================================================
# Utils
# =============================================================================
has_cmd() { command -v "$1" &>/dev/null; }
print_header() {
local title="$1"
local len=${#title}
local pad=$(( (76 - len) / 2 ))
echo -e "\n${C_HEADER}╔══════════════════════════════════════════════════════════════════════════════╗"
printf "${C_HEADER}║%${pad}s${WHITE} %s %${pad}s║${NC}\n" "" "$title" ""
echo -e "${C_HEADER}╚══════════════════════════════════════════════════════════════════════════════╝${NC}"
}
print_section() {
echo -e "\n${C_SECTION}$1${NC}"
echo -e "$SEP_LINE"
}
print_kv() {
printf " ${C_KEY}%-14s${NC} ${C_VALUE}%s${NC}\n" "$1:" "$2"
}
print_ok() { echo -e " ${C_OK}${NC} $1"; }
print_warn() { echo -e " ${C_WARN}${NC} $1"; }
print_err() { echo -e " ${C_ERR}${NC} $1"; }
# =============================================================================
# System Info
# =============================================================================
collect_server() {
print_header "服务器信息"
# OS Information
print_section "操作系统"
local os_name kernel arch
os_name="$(. /etc/os-release 2>/dev/null && echo "$PRETTY_NAME" || uname -s)"
kernel="$(uname -r)"
arch="$(uname -m)"
print_kv "系统" "$os_name"
print_kv "内核版本" "$kernel"
print_kv "系统架构" "$arch"
# Host Info
print_section "主机信息"
local hostname uptime_str
hostname="$(hostname)"
uptime_str="$(uptime -p 2>/dev/null | sed 's/up //' || uptime | sed 's/.*up //; s/,.*//')"
print_kv "主机名" "$hostname"
print_kv "运行时长" "$uptime_str"
print_kv "当前时间" "$(date '+%Y-%m-%d %H:%M:%S')"
# CPU
if [[ -f /proc/cpuinfo ]]; then
print_section "处理器"
local cpus cpu_model
cpus=$(grep -c '^processor' /proc/cpuinfo)
cpu_model=$(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)
print_kv "核心数量" "${cpus}"
print_kv "型号" "$cpu_model"
fi
# Memory
if has_cmd free; then
print_section "内存"
local mem_total mem_used mem_free mem_pct
mem_total=$(free -h | awk '/^Mem:/ {print $2}')
mem_used=$(free -h | awk '/^Mem:/ {print $3}')
mem_free=$(free -h | awk '/^Mem:/ {print $7}')
mem_pct=$(free | awk '/^Mem:/ {printf "%.1f", $3/$2 * 100}')
print_kv "总容量" "$mem_total"
print_kv "已使用" "$mem_used (${mem_pct}%)"
print_kv "可用" "$mem_free"
fi
# Disk
if has_cmd df; then
print_section "磁盘使用"
df -h --output=source,fstype,size,used,pcent,target 2>/dev/null | tail -n +2 | while read -r fs type size used pct target; do
[[ "$fs" == "tmpfs" || "$fs" == "devtmpfs" || "$fs" == "overlay" ]] && continue
[[ -z "$fs" ]] && continue
# Escape % for printf
local pct_clean="${pct%%%}"
printf " ${C_DIM}[${NC}${C_VALUE}%-12s${NC}${C_DIM}]${NC} ${C_KEY}%-8s${NC} ${C_VALUE}%-7s${NC} ${C_DIM}used:${NC} ${C_VALUE}%-7s${NC} ${C_DIM}(%s%%)${NC}\n" \
"$target" "$type" "$size" "$used" "$pct_clean"
done
fi
# Network
if has_cmd ip; then
print_section "网络接口"
ip -o addr show 2>/dev/null | awk '{print $2, $4}' | while read -r iface addr; do
[[ "$iface" == "lo" ]] && continue
print_kv "$iface" "$addr"
done
fi
}
# =============================================================================
# Docker Info
# =============================================================================
collect_docker() {
print_header "Docker 信息"
if ! has_cmd docker; then
print_err "Docker 未安装"
return 1
fi
# Version
print_section "版本信息"
local client_ver server_ver
client_ver=$(docker version --format '{{.Client.Version}}' 2>/dev/null || echo "N/A")
server_ver=$(docker version --format '{{.Server.Version}}' 2>/dev/null || echo "N/A")
print_kv "客户端" "$client_ver"
print_kv "服务端" "$server_ver"
if has_cmd docker-compose; then
print_kv "Docker Compose" "$(docker-compose version --short 2>/dev/null)"
fi
# Status
if docker info &>/dev/null; then
print_ok "守护进程运行中"
else
print_warn "守护进程未运行"
return 1
fi
# Stats
print_section "资源统计"
local containers running images networks volumes
containers=$(docker ps -aq 2>/dev/null | wc -l)
running=$(docker ps -q 2>/dev/null | wc -l)
images=$(docker images -q 2>/dev/null | wc -l)
networks=$(docker network ls -q 2>/dev/null | wc -l)
volumes=$(docker volume ls -q 2>/dev/null | wc -l)
print_kv "容器" "${running} 运行 / ${containers} 总计"
print_kv "镜像" "$images"
print_kv "网络" "$networks"
print_kv "存储卷" "$volumes"
# Running containers
if [[ $running -gt 0 ]]; then
print_section "运行中的容器"
docker ps --format "{{.Names}}|{{.Image}}|{{.Status}}" 2>/dev/null | while IFS='|' read -r name image status; do
printf " ${C_OK}${NC} ${C_VALUE}%-20s${NC} ${C_DIM}%-30s${NC} %s\n" "$name" "${image:0:30}" "$status"
done
fi
# All containers
if [[ $containers -gt 0 ]]; then
print_section "所有容器"
docker ps -a --format "{{.Names}}|{{.Image}}|{{.Status}}" 2>/dev/null | head -20 | while IFS='|' read -r name image status; do
local icon="${C_DIM}${NC}"
local color="$C_VALUE"
[[ "$status" == Up* ]] && icon="${C_OK}${NC}" && color="$C_OK"
[[ "$status" == Exited* ]] && color="$C_DIM"
printf " ${icon} ${color}%-20s${NC} ${C_DIM}%-25s${NC} %s\n" "$name" "${image:0:25}" "$status"
done
[[ $containers -gt 20 ]] && echo -e " ${C_DIM}... 还有 $((containers - 20)) 个容器${NC}"
fi
# Images
if [[ $images -gt 0 ]]; then
print_section "镜像列表"
docker images --format "{{.Repository}}|{{.Tag}}|{{.Size}}|{{.CreatedAt}}" 2>/dev/null | grep -v "<none>" | head -25 | while IFS='|' read -r repo tag size created; do
printf " ${C_DIM}${NC} ${C_VALUE}%-35s${NC} ${C_DIM}%-10s %s${NC}\n" "${repo}:${tag}" "$size" "$created"
done
[[ $images -gt 25 ]] && echo -e " ${C_DIM}... 还有 $((images - 25)) 个镜像${NC}"
fi
# Networks
if [[ $networks -gt 0 ]]; then
print_section "网络"
docker network ls --format "{{.Name}}|{{.Driver}}|{{.Scope}}" 2>/dev/null | head -15 | while IFS='|' read -r name driver scope; do
printf " ${C_DIM}${NC} ${C_VALUE}%-20s${NC} ${C_DIM}[%s/%s]${NC}\n" "$name" "$driver" "$scope"
done
fi
# Volumes
if [[ $volumes -gt 0 ]]; then
print_section "存储卷"
docker volume ls --format "{{.Name}}|{{.Driver}}" 2>/dev/null | head -20 | while IFS='|' read -r name driver; do
printf " ${C_DIM}${NC} ${C_VALUE}%s${NC} ${C_DIM}(%s)${NC}\n" "$name" "$driver"
done
[[ $volumes -gt 20 ]] && echo -e " ${C_DIM}... 还有 $((volumes - 20)) 个存储卷${NC}"
fi
}
# =============================================================================
# Main
# =============================================================================
main() {
collect_server
collect_docker
echo -e "\n${C_HEADER}╔══════════════════════════════════════════════════════════════════════════════╗"
echo -e "${C_HEADER}${C_OK} ✓ 信息收集完成 ${C_HEADER}${NC}"
echo -e "${C_HEADER}╚══════════════════════════════════════════════════════════════════════════════╝${NC}\n"
}
main "$@"

View File

@@ -0,0 +1,145 @@
#!/usr/bin/env bash
set -euo pipefail
# Filebrowser 一键安装脚本
# 用法示例curl -fsSL "https://pan.shumengya.top/d/scripts/filebrowser/install_filebrowser.sh" | sudo bash
# 目录结构假设:
# BASE_URL/linux-amd64/filebrowser
# BASE_URL/linux-arm64/filebrowser
BASE_URL="https://pan.shumengya.top/d/scripts/filebrowser"
INSTALL_DIR="/shumengya/bin/filebrowser"
SERVICE_NAME="smy-filebrowser"
BINARY_NAME="filebrowser"
log() { printf '[Filebrowser-安装] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 进度条函数
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[Filebrowser-安装] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash install_filebrowser.sh)"
fi
}
detect_arch() {
local machine
machine=$(uname -m)
case "$machine" in
x86_64|amd64) echo "linux-amd64" ;;
aarch64|arm64) echo "linux-arm64" ;;
*) fail "不支持的架构: $machine" ;;
esac
}
download_and_install() {
local arch=$1
local tmp_dir
tmp_dir=$(mktemp -d)
trap 'if [ -n "${tmp_dir:-}" ] && [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi' EXIT
mkdir -p "$INSTALL_DIR"
local bin_url="${BASE_URL}/${arch}/${BINARY_NAME}"
log "正在处理 ${BINARY_NAME} ..."
# 停止旧服务
systemctl stop "${SERVICE_NAME}.service" 2>/dev/null || true
# 强制清理可能残留的进程 (避免 Text file busy)
pids=$(pgrep -f "$INSTALL_DIR/$BINARY_NAME" || true)
if [ -n "$pids" ]; then
log "清理残留进程..."
kill -9 $pids 2>/dev/null || true
fi
# 优先检测当前目录下是否有二进制文件(本地安装模式)
if [ -f "./${BINARY_NAME}" ]; then
log "发现本地文件 ./${BINARY_NAME},跳过下载..."
cp "./${BINARY_NAME}" "$tmp_dir/$BINARY_NAME"
else
# 下载二进制
curl -fsSL "$bin_url" -o "$tmp_dir/$BINARY_NAME" &
show_progress $! "下载二进制文件"
[ -f "$tmp_dir/$BINARY_NAME" ] || fail "下载失败"
fi
# 安装文件
cp "$tmp_dir/$BINARY_NAME" "$INSTALL_DIR/$BINARY_NAME"
chmod +x "$INSTALL_DIR/$BINARY_NAME"
# 配置服务
write_service
# 启动服务
systemctl daemon-reload
systemctl enable "${SERVICE_NAME}.service"
systemctl restart "${SERVICE_NAME}.service"
sleep 2
if systemctl is-active --quiet "${SERVICE_NAME}.service"; then
log "服务启动成功"
log "Filebrowser 监听端口: 2333"
log "配置文件和数据库将存储在: $INSTALL_DIR"
else
log "警告: 服务启动失败,查看日志:"
journalctl -u "${SERVICE_NAME}.service" --no-pager -n 10
fi
}
write_service() {
local service_file="/etc/systemd/system/${SERVICE_NAME}.service"
cat > "$service_file" <<EOF
[Unit]
Description=Filebrowser Service
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/$BINARY_NAME -r $INSTALL_DIR -d $INSTALL_DIR/filebrowser.db -l /var/log/filebrowser.log -p 2333 -a 0.0.0.0
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
}
main() {
require_root
local arch
arch=$(detect_arch)
log "检测到架构: $arch"
download_and_install "$arch"
log "=========================================="
log "安装任务完成!"
log "安装目录: $INSTALL_DIR"
log "服务名称: $SERVICE_NAME"
log "=========================================="
}
main "$@"

Binary file not shown.

Binary file not shown.

View File

View File

@@ -0,0 +1,109 @@
#!/usr/bin/env bash
set -euo pipefail
# Filebrowser 一键卸载脚本
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/filebrowser/uninstall_filebrowser.sh" | sudo bash
INSTALL_DIR="/shumengya/bin/filebrowser"
SERVICE_NAME="smy-filebrowser"
BINARY_NAME="filebrowser"
log() { printf '[Filebrowser-卸载] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[Filebrowser-卸载] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash uninstall_filebrowser.sh)"
fi
}
stop_and_disable_service() {
if systemctl is-active --quiet "${SERVICE_NAME}.service"; then
systemctl stop "${SERVICE_NAME}.service"
fi
if systemctl is-enabled --quiet "${SERVICE_NAME}.service" 2>/dev/null; then
systemctl disable "${SERVICE_NAME}.service"
fi
}
remove_service_file() {
local service_file="/etc/systemd/system/${SERVICE_NAME}.service"
if [ -f "$service_file" ]; then
rm -f "$service_file"
systemctl daemon-reload
fi
}
cleanup_process() {
# 查找并杀掉所有匹配的进程
local pids
pids=$(pgrep -f "$INSTALL_DIR/$BINARY_NAME" || true)
if [ -n "$pids" ]; then
kill -9 $pids 2>/dev/null || true
fi
}
uninstall_main() {
log "正在卸载 Filebrowser ..."
(stop_and_disable_service) &
show_progress $! "停止服务"
cleanup_process
(remove_service_file) &
show_progress $! "删除服务文件"
if [ -f "$INSTALL_DIR/$BINARY_NAME" ]; then
rm -f "$INSTALL_DIR/$BINARY_NAME"
fi
# 清理日志文件(可选)
if [ -f "/var/log/filebrowser.log" ]; then
rm -f "/var/log/filebrowser.log"
log "已删除日志文件"
fi
# 询问是否删除数据(数据库)
if [ -d "$INSTALL_DIR" ]; then
# 检查目录下是否有除了二进制文件以外的内容(主要是数据库)
if [ -n "$(ls -A "$INSTALL_DIR" 2>/dev/null)" ]; then
log "警告: 安装目录 $INSTALL_DIR 中可能包含用户数据 (如 filebrowser.db)"
# 默认不自动删除数据目录,防止误删,提示用户手动删除
log "为了安全起见,脚本仅删除了二进制文件。若要彻底清除数据,请手动运行: rm -rf $INSTALL_DIR"
else
rm -rf "$INSTALL_DIR"
log "已删除空安装目录"
fi
fi
log "=========================================="
log "卸载任务完成"
log "=========================================="
}
main() {
require_root
uninstall_main
}
main "$@"

37
frp/frp/frpc.toml Normal file
View File

@@ -0,0 +1,37 @@
#===========================================
#===================基础设置===================
#===========================================
serverAddr = "47.108.90.0"
serverPort = 7000
auth.method = "token"
auth.token = "smy"
webServer.addr = "0.0.0.0"
webServer.port = 7400
webServer.user = "shumengya"
webServer.password = "tyh@19900420"
webServer.pprofEnable = false
# 日志配置
log.to = "console"
log.level = "info"
#===========================================
#===================Http服务===================
#===========================================
#大萌芽frp客户端-frpc
[[proxies]]
name = "frpc"
type = "http"
localIP = "127.0.0.1"
localPort = 7400
customDomains = ["frpc.shumengya.top"]

26
frp/frp/frps.toml Normal file
View File

@@ -0,0 +1,26 @@
# frp服务端配置 - 作为nginx后端服务
# 与nginx配合使用提供HTTPS支持
bindAddr = "0.0.0.0"
bindPort = 7000
auth.method = "token"
auth.token = "smy"
# HTTP配置 - 作为后端服务nginx代理
vhostHTTPPort = 8080 # nginx代理到此端口
# 日志配置
log.to = "console"
log.level = "info"
# 管理界面
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "shumengya"
webServer.password = "tyh@19900420"

BIN
frp/frp/linux_amd64/frpc Normal file

Binary file not shown.

BIN
frp/frp/linux_amd64/frps Normal file

Binary file not shown.

BIN
frp/frp/linux_arm64/frpc Normal file

Binary file not shown.

BIN
frp/frp/linux_arm64/frps Normal file

Binary file not shown.

0
frp/frp/smy-frpc.serivce Normal file
View File

0
frp/frp/smy-frps.serivce Normal file
View File

192
frp/install_frp.sh Normal file
View File

@@ -0,0 +1,192 @@
#!/usr/bin/env bash
set -euo pipefail
# FRP 一键安装脚本
# 用法示例curl -fsSL "https://pan.shumengya.top/d/scripts/frp/install_frp.sh" | sudo bash
# 包含 frps (服务端) 和 frpc (客户端) 的安装
# 目录结构假设:
# BASE_URL/linux_amd64/frps
# BASE_URL/linux_amd64/frpc
# BASE_URL/frps.toml
# BASE_URL/frpc.toml
# BASE_URL/smy-frps.service (模板)
# BASE_URL/smy-frpc.service (模板)
BASE_URL="https://pan.shumengya.top/d/scripts/frp/frp"
INSTALL_DIR="/shumengya/bin/frp"
SERVICE_PREFIX="smy-frp"
log() { printf '[frp-安装] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 进度条函数
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[frp-安装] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash install_frp.sh)"
fi
}
detect_arch() {
local machine
machine=$(uname -m)
case "$machine" in
x86_64|amd64) echo "linux_amd64" ;;
aarch64|arm64) echo "linux_arm64" ;;
*) fail "不支持的架构: $machine" ;;
esac
}
select_mode() {
echo "请选择安装模式:" >&2
echo "1) 安装客户端 (frpc)" >&2
echo "2) 安装服务端 (frps)" >&2
echo "3) 同时安装" >&2
read -p "请输入选项 [1-3]: " choice < /dev/tty
case "$choice" in
1) echo "client" ;;
2) echo "server" ;;
3) echo "both" ;;
*) fail "无效选项" ;;
esac
}
download_and_install() {
local mode=$1
local arch=$2
local tmp_dir
tmp_dir=$(mktemp -d)
trap 'if [ -n "${tmp_dir:-}" ] && [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi' EXIT
mkdir -p "$INSTALL_DIR"
if [ "$mode" = "client" ] || [ "$mode" = "both" ]; then
install_component "frpc" "$arch" "$tmp_dir"
fi
if [ "$mode" = "server" ] || [ "$mode" = "both" ]; then
install_component "frps" "$arch" "$tmp_dir"
fi
}
install_component() {
local name=$1 # frpc or frps
local arch=$2
local tmp_dir=$3
local bin_url="${BASE_URL}/${arch}/${name}"
local conf_url="${BASE_URL}/${name}.toml"
local service_name="${SERVICE_PREFIX}${name:3}" # smy-frpc or smy-frps
log "正在处理 $name ..."
# 停止旧服务
systemctl stop "${service_name}.service" 2>/dev/null || true
# 强制清理可能残留的进程 (避免 Text file busy)
pids=$(pgrep -x "$name" || true)
if [ -n "$pids" ]; then
log "清理 $name 残留进程..."
kill -9 $pids 2>/dev/null || true
fi
# 下载二进制
curl -fsSL "$bin_url" -o "$tmp_dir/$name" &
show_progress $! "下载 $name 二进制文件"
[ -f "$tmp_dir/$name" ] || fail "下载 $name 失败"
# 下载配置
curl -fsSL "$conf_url" -o "$tmp_dir/${name}.toml" &
show_progress $! "下载 $name 配置文件"
[ -f "$tmp_dir/${name}.toml" ] || fail "下载配置文件失败"
# 安装文件
cp "$tmp_dir/$name" "$INSTALL_DIR/$name"
chmod +x "$INSTALL_DIR/$name"
if [ ! -f "$INSTALL_DIR/${name}.toml" ]; then
cp "$tmp_dir/${name}.toml" "$INSTALL_DIR/${name}.toml"
else
log "保留现有配置文件: $INSTALL_DIR/${name}.toml"
fi
# 配置服务
write_service "$name"
# 启动服务
systemctl daemon-reload
systemctl enable "${service_name}.service"
systemctl restart "${service_name}.service"
sleep 2
if systemctl is-active --quiet "${service_name}.service"; then
log "$name 服务启动成功"
else
log "警告: $name 服务启动失败,查看日志:"
journalctl -u "${service_name}.service" --no-pager -n 10
fi
}
write_service() {
local name=$1
local service_name="${SERVICE_PREFIX}${name:3}"
local service_file="/etc/systemd/system/${service_name}.service"
cat > "$service_file" <<EOF
[Unit]
Description=${service_name}
After=network.target
[Service]
Type=simple
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/$name -c $INSTALL_DIR/${name}.toml
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
}
main() {
require_root
local arch
arch=$(detect_arch)
log "检测到架构: $arch"
local mode
if [ $# -gt 0 ]; then
case "$1" in
client|frpc) mode="client" ;;
server|frps) mode="server" ;;
both) mode="both" ;;
*) fail "无效参数: $1 (可用: client, server, both)" ;;
esac
else
mode=$(select_mode)
fi
download_and_install "$mode" "$arch"
log "=========================================="
log "安装任务完成!"
log "安装目录: $INSTALL_DIR"
log "=========================================="
}
main "$@"

66
frp/start_frp.sh Normal file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/env bash
set -euo pipefail
# 恢复并启动 frp 服务
# 该脚本自动检测已安装的 frp 服务 (客户端/服务端) 并恢复其运行和开机自启
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/frp/start_frp.sh" | sudo bash
SERVICE_FRPC="smy-frpc"
SERVICE_FRPS="smy-frps"
log() { printf '[frp-启动] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 检查 root 权限
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行"
fi
start_service() {
local svc=$1
local service_file="/etc/systemd/system/${svc}.service"
if [ -f "$service_file" ]; then
log "检测到已安装服务: $svc"
# 重置失败状态
systemctl reset-failed "$svc" 2>/dev/null || true
log "正在启用并启动 $svc..."
systemctl enable --now "$svc"
sleep 1
if systemctl is-active --quiet "$svc"; then
log "$svc 启动成功 (状态: $(systemctl is-active "$svc"))"
else
log "$svc 启动失败"
systemctl status "$svc" --no-pager -n 5 || true
fi
else
# 仅在调试时显示,避免干扰普通用户
# log "未检测到 $svc跳过"
:
fi
}
log "正在扫描并恢复 frp 服务..."
found_any=false
if [ -f "/etc/systemd/system/${SERVICE_FRPC}.service" ]; then
start_service "$SERVICE_FRPC"
found_any=true
fi
if [ -f "/etc/systemd/system/${SERVICE_FRPS}.service" ]; then
start_service "$SERVICE_FRPS"
found_any=true
fi
if [ "$found_any" = false ]; then
log "未检测到任何已安装的 frp 服务 (smy-frpc 或 smy-frps)。"
log "请先运行安装脚本进行安装。"
exit 1
fi
log "操作完成。"

66
frp/stopkill_frp.sh Normal file
View File

@@ -0,0 +1,66 @@
#!/usr/bin/env bash
set -euo pipefail
# 强制停止 frp 服务并清理进程
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/frp/stopkill_frp.sh" | sudo bash
SERVICE_FRPC="smy-frpc"
SERVICE_FRPS="smy-frps"
log() { printf '[frp-停止] %s\n' "$*" >&2; }
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
log "请使用 root 权限运行"
exit 1
fi
stop_service() {
local svc=$1
if systemctl is-active --quiet "$svc"; then
log "正在停止服务 $svc..."
systemctl disable --now "$svc" 2>/dev/null || true
systemctl stop "$svc" 2>/dev/null || true
fi
# 即使服务不活跃,也要尝试 disable防止开机自启
systemctl disable "$svc" 2>/dev/null || true
# 重置失败状态
systemctl reset-failed "$svc" 2>/dev/null || true
}
kill_process() {
local name=$1
local pids
local current_pid=$$
# 尝试精确匹配
pids=$(pgrep -x "$name" || true)
# 如果没找到,尝试模糊匹配但排除当前脚本
if [ -z "$pids" ]; then
pids=$(pgrep -f "$name" | grep -v "$current_pid" || true)
fi
if [ -n "$pids" ]; then
log "发现 $name 残留进程 PID: $pids,正在强制终止..."
kill -9 $pids 2>/dev/null || true
fi
}
log "开始清理 frp 相关服务..."
# Stop Services
stop_service "$SERVICE_FRPC"
stop_service "$SERVICE_FRPS"
# Kill Processes
kill_process "frpc"
kill_process "frps"
log "正在验证服务状态..."
if pgrep -x "frpc" >/dev/null || pgrep -x "frps" >/dev/null; then
log "警告: 仍有 frp 进程在运行!"
ps -fp $(pgrep -x "frpc" "frps" 2>/dev/null) || true
else
log "frp 相关服务及进程已完全停止 (服务已禁用)。"
fi

145
frp/uninstall_frp.sh Normal file
View File

@@ -0,0 +1,145 @@
#!/usr/bin/env bash
set -euo pipefail
# FRP 一键卸载脚本
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/frp/uninstall_frp.sh" | sudo bash
INSTALL_DIR="/shumengya/bin/frp"
SERVICE_PREFIX="smy-frp"
log() { printf '[frp-卸载] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[frp-卸载] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash uninstall_frp.sh)"
fi
}
select_mode() {
echo "请选择卸载模式:" >&2
echo "1) 卸载客户端 (frpc)" >&2
echo "2) 卸载服务端 (frps)" >&2
echo "3) 全部卸载" >&2
read -p "请输入选项 [1-3]: " choice < /dev/tty
case "$choice" in
1) echo "client" ;;
2) echo "server" ;;
3) echo "both" ;;
*) fail "无效选项" ;;
esac
}
stop_and_disable_service() {
local name=$1
local service_name="${SERVICE_PREFIX}${name:3}"
if systemctl is-active --quiet "${service_name}.service"; then
systemctl stop "${service_name}.service"
fi
if systemctl is-enabled --quiet "${service_name}.service" 2>/dev/null; then
systemctl disable "${service_name}.service"
fi
}
remove_service_file() {
local name=$1
local service_name="${SERVICE_PREFIX}${name:3}"
local service_file="/etc/systemd/system/${service_name}.service"
if [ -f "$service_file" ]; then
rm -f "$service_file"
systemctl daemon-reload
fi
}
cleanup_process() {
local name=$1
# 查找并杀掉所有匹配的进程
local pids
pids=$(pgrep -f "$INSTALL_DIR/$name" || true)
if [ -n "$pids" ]; then
kill -9 $pids 2>/dev/null || true
fi
}
uninstall_component() {
local name=$1
log "正在卸载 $name ..."
(stop_and_disable_service "$name") &
show_progress $! "停止服务"
cleanup_process "$name"
(remove_service_file "$name") &
show_progress $! "删除服务文件"
if [ -f "$INSTALL_DIR/$name" ]; then
rm -f "$INSTALL_DIR/$name"
fi
# 注意:不自动删除配置文件,以免误删用户配置
# if [ -f "$INSTALL_DIR/${name}.toml" ]; then
# rm -f "$INSTALL_DIR/${name}.toml"
# fi
}
main() {
require_root
local mode
if [ $# -gt 0 ]; then
case "$1" in
client|frpc) mode="client" ;;
server|frps) mode="server" ;;
both) mode="both" ;;
*) fail "无效参数: $1 (可用: client, server, both)" ;;
esac
else
mode=$(select_mode)
fi
if [ "$mode" = "client" ] || [ "$mode" = "both" ]; then
uninstall_component "frpc"
fi
if [ "$mode" = "server" ] || [ "$mode" = "both" ]; then
uninstall_component "frps"
fi
# 如果目录为空,则删除目录
if [ -d "$INSTALL_DIR" ]; then
if [ -z "$(ls -A "$INSTALL_DIR")" ]; then
rm -rf "$INSTALL_DIR"
log "已删除空安装目录"
else
log "保留安装目录 (包含配置文件): $INSTALL_DIR"
fi
fi
log "=========================================="
log "卸载任务完成"
log "=========================================="
}
main "$@"

267
login-info/login-info.sh Executable file
View File

@@ -0,0 +1,267 @@
#!/bin/bash
# 用法示例curl -fsSL "https://pan.shumengya.top/d/scripts/login_info.sh" | bash
# --- 精心选择的颜色定义 ---
NONE='\033[00m'
BOLD='\033[1m'
# 主题色 (可根据喜好调整)
# 可以选择一个主色调,例如蓝色系或绿色系
# 这里我们尝试用青色作为标题,黄色作为关键信息,白色作为次要信息
TITLE_COLOR='\033[01;36m' # 亮青色 (Bold Cyan)
INFO_COLOR='\033[01;33m' # 亮黄色 (Bold Yellow)
VALUE_COLOR='\033[00;37m' # 白色 (White)
LABEL_COLOR='\033[00;32m' # 绿色 (Green) - 用于标签
SUBTLE_COLOR='\033[01;30m' # 深灰色/亮黑色 (Bold Black / Dark Gray) - 用于分隔符或不重要信息
BLUE_COLOR='\033[01;34m' # 亮蓝色 (Bold Blue)
ORANGE_COLOR='\033[01;33m' # 亮黄色 (在16色终端中常作为橙色) - 使用 INFO_COLOR 相同的代码
# --- 设备名称和欢迎 ---
HOSTNAME_TEXT=$(hostname) # 如果不再需要显示hostname可以注释掉或删除这行
# --- 系统概览 ---
OS_INFO=$(lsb_release -ds 2>/dev/null || echo "N/A")
KERNEL_VERSION=$(uname -sr 2>/dev/null || echo "N/A")
BOOT_TIME=$(uptime -s 2>/dev/null || who -b | awk '{print $3, $4}')
UPTIME=$(uptime -p 2>/dev/null | sed 's/up //')
LOAD_AVG=$(uptime 2>/dev/null | awk -F'load average: ' '{print $2}')
echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"
echo -e "${TITLE_COLOR}${BOLD}系统概览${NONE}"
echo -e " ${LABEL_COLOR}系统名称:${NONE} ${VALUE_COLOR}$(uname -a)${NONE}"
echo -e " ${LABEL_COLOR}操作系统:${NONE} ${VALUE_COLOR}$OS_INFO${NONE}"
echo -e " ${LABEL_COLOR}内核版本:${NONE} ${VALUE_COLOR}$KERNEL_VERSION${NONE}"
echo -e " ${LABEL_COLOR}启动时间:${NONE} ${VALUE_COLOR}$BOOT_TIME${NONE}"
echo -e " ${LABEL_COLOR}运行时间:${NONE} ${VALUE_COLOR}$UPTIME${NONE}"
echo -e " ${LABEL_COLOR}平均负载:${NONE} ${VALUE_COLOR}$LOAD_AVG${NONE}"
echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"
# --- 硬件资源 ---
# 获取 CPU 型号,处理可能的多行输出,只取第一行,并去除首尾空格
CPU_MODEL=$(grep "model name" /proc/cpuinfo | head -n 1 | awk -F ':' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' || echo "N/A")
CPU_CORES=$(grep -c "processor" /proc/cpuinfo 2>/dev/null || echo "N/A")
# CPU 温度 (尽可能兼容更多机型)
CPU_TEMP=""
# 定义获取CPU温度的函数
get_cpu_temp() {
local temp_c=""
# 1. 尝试使用 sensors 命令 (如果安装了 lm-sensors)
if command -v sensors &> /dev/null; then
# 尝试匹配常见的CPU温度标签
# Package id 0: Intel/AMD 多核封装温度
# Tctl/Tdie: AMD Ryzen
# Core 0: Intel Core
# cpu_thermal: 树莓派/通用
# Composite: 部分嵌入式设备
temp_c=$(sensors | grep -iE '^(package id 0|tctl|tdie|core 0|cpu_thermal|composite|temp1):' | head -n 1 | awk '{print $2}' | tr -d '+°C')
if [ -n "$temp_c" ]; then
echo "$temp_c"
return
fi
fi
# 2. 尝试读取 /sys/class/thermal/thermal_zone*
# 优先查找 x86_pkg_temp (Intel) 或 k10temp (AMD) 或 cpu-thermal (ARM) 或 acpitz
for zone in /sys/class/thermal/thermal_zone*; do
[ -e "$zone/type" ] || continue
type=$(cat "$zone/type")
if [[ "$type" == "x86_pkg_temp" || "$type" == "k10temp" || "$type" == "cpu-thermal" || "$type" == "acpitz" ]]; then
if [ -r "$zone/temp" ]; then
temp_raw=$(cat "$zone/temp")
# 转换为摄氏度 (除以1000)
if [ "$temp_raw" -gt 0 ] 2>/dev/null; then
awk "BEGIN {printf \"%.1f\", $temp_raw/1000}"
return
fi
fi
fi
done
# 3. 如果还没找到,尝试任何 thermal_zone0 (通常是主要的)
if [ -r "/sys/class/thermal/thermal_zone0/temp" ]; then
temp_raw=$(cat "/sys/class/thermal/thermal_zone0/temp")
if [ "$temp_raw" -gt 0 ] 2>/dev/null; then
awk "BEGIN {printf \"%.1f\", $temp_raw/1000}"
return
fi
fi
}
CPU_TEMP_VAL=$(get_cpu_temp)
if [ -n "$CPU_TEMP_VAL" ]; then
CPU_TEMP="(${INFO_COLOR}${CPU_TEMP_VAL}°C${VALUE_COLOR})"
fi
# 智能内存显示:小于 1GB 显示 MB否则显示 GB (保留1位小数)
MEM_TOTAL_MB=$(free -m | awk 'NR==2{print $2}')
if [ "$MEM_TOTAL_MB" -ge 1000 ]; then
MEM_TOTAL_DISPLAY=$(awk -v val="$MEM_TOTAL_MB" 'BEGIN {printf "%.1fGB", val/1024}')
else
MEM_TOTAL_DISPLAY="${MEM_TOTAL_MB}MB"
fi
MEM_USED_PERCENT=$(free -m | awk 'NR==2{printf "%.1f%%", $3*100/$2 }')
MEM_AVAILABLE_MB=$(free -m | awk 'NR==2{print $7"MB"}') # 'available' 通常比 'free' 更能代表实际可用内存
# --- GPU 检测 ---
# 优先使用 lspci 检测 VGA, 3D, Display 控制器
GPU_INFO=""
if command -v lspci &> /dev/null; then
# 获取设备列表,去除前面的地址信息,只保留设备名称
# 典型 lspci 输出: "00:02.0 VGA compatible controller: Intel Corporation ..."
# 我们需要截取 "Intel Corporation ..."
# 使用 sed 处理:匹配开头到第二个冒号之前的所有内容并删除
GPU_INFO=$(lspci | grep -iE 'vga|3d|display' | sed 's/^.*: .*[:] //')
fi
echo -e "${TITLE_COLOR}${BOLD}硬件资源${NONE}"
echo -e " ${LABEL_COLOR}中央处理器 (CPU):${NONE}"
echo -e " ${VALUE_COLOR}$CPU_MODEL - ${CPU_CORES} 核心 ${CPU_TEMP}${NONE}"
if [ -n "$GPU_INFO" ]; then
echo -e " ${LABEL_COLOR}图形处理器 (GPU):${NONE}"
# 处理多显卡情况,逐行显示
echo "$GPU_INFO" | while read -r line; do
echo -e " ${VALUE_COLOR}$line${NONE}"
done
fi
echo -e " ${LABEL_COLOR}内存 (RAM):${NONE}"
echo -e " ${VALUE_COLOR}总计: ${INFO_COLOR}$MEM_TOTAL_DISPLAY${VALUE_COLOR} | 已用: ${INFO_COLOR}$MEM_USED_PERCENT${VALUE_COLOR} | 可用: ${INFO_COLOR}$MEM_AVAILABLE_MB${NONE}"
echo -e " ${LABEL_COLOR}存储空间:${NONE}"
# --- 修改的存储部分 (删除进度条, 修改颜色) ---
# 使用 df -hT 获取信息,-x 排除不必要的类型 (保留 overlay)
# 使用 awk 跳过头部 (NR>1),并按列提取 (Filesystem, Type, Size, Used, Use%, Mounted on)
# 注意:已添加 -x overlay 以隐藏 Docker 挂载卷
df -hT -x tmpfs -x devtmpfs -x devpts -x proc -x sysfs -x cgroup -x fusectl -x securityfs -x pstore -x efivarfs -x autofs -x overlay 2>/dev/null | awk 'NR>1 {print $1, $2, $3, $4, $6, $7}' | while read -r DEVICE TYPE SIZE USED PERCENT MOUNTPOINT; do
# --- 已删除进度条的计算和绘制 ---
echo -e " ${INFO_COLOR}${MOUNTPOINT}${NONE} (${VALUE_COLOR}${DEVICE} - ${TYPE}${NONE})"
# --- 核心改动:将 总 和 已用 后面的数值改为蓝色 ---
# LABEL_COLOR 用于标签文字 "总:" 和 "已用:"
# BLUE_COLOR 用于数值 SIZE 和 USED
# VALUE_COLOR 用于百分比 PERCENT 以及括号和逗号
echo -e " ${LABEL_COLOR}总:${NONE} ${BLUE_COLOR}${SIZE}${NONE}, ${LABEL_COLOR}已用:${NONE} ${BLUE_COLOR}${USED}${NONE} (${VALUE_COLOR}${PERCENT}${NONE})"
done
echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"
# --- 网络连接 ---
echo -e "${TITLE_COLOR}${BOLD}网络连接${NONE}"
INTERFACES_UP=$(ip -o link show up | awk -F': ' '{print $2}' | cut -d '@' -f 1) # 使用 cut 移除 @ifname 后缀
HAS_IP=false
if [ -n "$INTERFACES_UP" ]; then
for IFACE in $INTERFACES_UP; do
if [[ "$IFACE" == "lo" ]]; then continue; fi # 跳过 lo 接口
# 跳过 Docker 相关接口
if [[ "$IFACE" == docker* || "$IFACE" == veth* || "$IFACE" == br-* ]]; then continue; fi
IP_ADDRS=$(ip -4 addr show dev "$IFACE" 2>/dev/null | grep -oP 'inet \K[\d.]+' | tr '\n' ' ')
IP_ADDRS_V6=$(ip -6 addr show dev "$IFACE" 2>/dev/null | grep -oP 'inet6 \K[0-9a-fA-F:]+' | grep -ivE '^fe80::' | head -n1 | tr '\n' ' ') # 只显示一个全局 IPv6
MAC_ADDR=$(ip link show dev "$IFACE" 2>/dev/null | awk '/ether/ {print $2}')
if [ -n "$IP_ADDRS" ] || [ -n "$IP_ADDRS_V6" ]; then
HAS_IP=true
IFACE_TYPE_LABEL=""
if [[ "$IFACE" == wlan* || "$IFACE" == wlp* || "$IFACE" == ath* || "$IFACE" == ra* ]]; then
IFACE_TYPE_LABEL="(${LABEL_COLOR}WiFi${NONE}) "
elif [[ "$IFACE" == eth* || "$IFACE" == enp* || "$IFACE" == eno* ]]; then
IFACE_TYPE_LABEL="(${LABEL_COLOR}有线${NONE}) "
# 添加对虚拟接口类型的更全面判断
elif [[ "$IFACE" == docker* || "$IFACE" == br-* || "$IFACE" == veth* || "$IFACE" == tun* || "$IFACE" == tap* || "$IFACE" == virbr* ]]; then
IFACE_TYPE_LABEL="(${LABEL_COLOR}虚拟${NONE}) "
# 考虑桥接接口
elif ip link show "$IFACE" | grep -q "bridge"; then
IFACE_TYPE_LABEL="(${LABEL_COLOR}桥接${NONE}) "
fi
echo -e " ${INFO_COLOR}${BOLD}${IFACE}${NONE} ${IFACE_TYPE_LABEL}"
[ -n "$IP_ADDRS" ] && echo -e " ${LABEL_COLOR}IPv4:${NONE} ${VALUE_COLOR}${IP_ADDRS% }${NONE}" # % 移除末尾空格
[ -n "$IP_ADDRS_V6" ] && echo -e " ${LABEL_COLOR}IPv6:${NONE} ${VALUE_COLOR}${IP_ADDRS_V6% }${NONE}"
[ -n "$MAC_ADDR" ] && echo -e " ${LABEL_COLOR}MAC:${NONE} ${VALUE_COLOR}${MAC_ADDR}${NONE}"
fi
done
fi
if ! $HAS_IP; then
echo -e " ${VALUE_COLOR}未检测到活动的网络连接或IP地址${NONE}"
fi
echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"
# --- Docker 容器 ---
# 检查 docker 命令是否存在且守护进程正在运行
if command -v docker &> /dev/null && docker ps &> /dev/null; then
DOCKER_RUNNING_COUNT=$(docker ps -q | wc -l)
DOCKER_TOTAL_COUNT=$(docker ps -aq | wc -l)
echo -e "${TITLE_COLOR}${BOLD}Docker 容器${NONE}"
echo -e " ${LABEL_COLOR}容器数量:${NONE} ${VALUE_COLOR}运行中: ${INFO_COLOR}${DOCKER_RUNNING_COUNT}${VALUE_COLOR} / 总计: ${INFO_COLOR}${DOCKER_TOTAL_COUNT}${NONE}"
if [ "$DOCKER_RUNNING_COUNT" -gt 0 ]; then
# 获取名称列表,用逗号分隔
DOCKER_NAMES=$(docker ps --format "{{.Names}}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g')
echo -e " ${LABEL_COLOR}运行列表:${NONE} ${VALUE_COLOR}${DOCKER_NAMES}${NONE}"
fi
echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"
fi
# --- 活动与统计 ---
LAST_LOGIN_INFO=$(last -n 1 -wFai 2>/dev/null | head -n 1) # -a 把hostname放最后, -i 显示IP
LAST_LOGIN_DISPLAY=""
if [[ "$LAST_LOGIN_INFO" == *"wtmp begins"* || -z "$LAST_LOGIN_INFO" || $(echo "$LAST_LOGIN_INFO" | wc -w) -lt 5 ]]; then # 增加字段数检查
LAST_LOGIN_DISPLAY="${VALUE_COLOR}无先前登录记录或记录格式异常${NONE}"
else
# --- 修改的上次登录部分 ---
USER=$(echo "$LAST_LOGIN_INFO" | awk '{print $1}')
# 对于 -wFai, IP/hostname 通常是第三列
FROM_IP_OR_HOST=$(echo "$LAST_LOGIN_INFO" | awk '{print $3}')
# 精确提取日期和时间部分,跳过 'still' 和年份 (字段 4到7)
LOGIN_TIME_FIELDS=$(echo "$LAST_LOGIN_INFO" | awk '{print $4, $5, $6, $7}')
# 尝试用date格式化如果失败则显示原始字段
LOGIN_TIME_FORMATTED=$(date -d "$LOGIN_TIME_FIELDS $(date +%Y)" +"%Y-%m-%d %H:%M:%S" 2>/dev/null) # 显式添加年份尝试格式化
if [ -z "$LOGIN_TIME_FORMATTED" ]; then
LOGIN_TIME_FORMATTED="${VALUE_COLOR}${LOGIN_TIME_FIELDS}${NONE} (raw)" # 格式化失败,显示原始字段并标记
fi
LAST_LOGIN_DISPLAY="${LABEL_COLOR}用户:${NONE} ${INFO_COLOR}$USER${NONE}, ${LABEL_COLOR}来自:${NONE} ${INFO_COLOR}$FROM_IP_OR_HOST${NONE}, ${LABEL_COLOR}时间:${NONE} ${VALUE_COLOR}$LOGIN_TIME_FORMATTED${NONE}"
fi
PACKAGE_COUNT=$(dpkg-query -f '${Package}\n' -W 2>/dev/null | wc -l || echo "N/A") # Debian/APT
echo -e "${TITLE_COLOR}${BOLD}活动与统计${NONE}"
echo -e " ${LABEL_COLOR}上次登录:${NONE} $LAST_LOGIN_DISPLAY"
# 检查是否是 Debian/Ubuntu 系列系统,然后显示包数
if command -v dpkg-query &> /dev/null; then
PACKAGE_COUNT=$(dpkg-query -f '${Package}\n' -W 2>/dev/null | wc -l || echo "N/A")
echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}$PACKAGE_COUNT (Debian/APT)${NONE}"
elif command -v rpm &> /dev/null; then
PACKAGE_COUNT=$(rpm -qa 2>/dev/null | wc -l || echo "N/A")
echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}$PACKAGE_COUNT (RPM/Yum/Dnf)${NONE}"
elif command -v pacman &> /dev/null; then
PACKAGE_COUNT=$(pacman -Qq 2>/dev/null | wc -l || echo "N/A")
echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}$PACKAGE_COUNT (Pacman)${NONE}"
else
echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}N/A (未知包管理器)${NONE}"
fi
CURRENT_DATETIME=$(date +"%Y年%m月%d日 %A %H:%M:%S %Z")
echo -e " ${LABEL_COLOR}当前登录时间:${NONE} ${VALUE_COLOR}$CURRENT_DATETIME$"
echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"

View File

@@ -0,0 +1,143 @@
#!/usr/bin/env bash
set -euo pipefail
# MengyaMonitor 一键安装脚本
# 用法示例curl -fsSL "https://pan.shumengya.top/d/scripts/mengyamonitor/install_mengyamonitor.sh" | sudo bash
# 目录结构假设:
# BASE_URL/linux_amd64/mengyamonitor-backend
# BASE_URL/linux_arm64/mengyamonitor-backend
BASE_URL="https://pan.shumengya.top/d/scripts/mengyamonitor"
INSTALL_DIR="/shumengya/bin/mengyamonitor"
SERVICE_NAME="smy-mengyamonitor"
BINARY_NAME="mengyamonitor-backend"
log() { printf '[MengyaMonitor-安装] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 进度条函数
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[MengyaMonitor-安装] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash install_mengyamonitor.sh)"
fi
}
detect_arch() {
local machine
machine=$(uname -m)
case "$machine" in
x86_64|amd64) echo "linux_amd64" ;;
aarch64|arm64) echo "linux_arm64" ;;
*) fail "不支持的架构: $machine" ;;
esac
}
download_and_install() {
local arch=$1
local tmp_dir
tmp_dir=$(mktemp -d)
trap 'if [ -n "${tmp_dir:-}" ] && [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi' EXIT
mkdir -p "$INSTALL_DIR"
local bin_url="${BASE_URL}/${arch}/${BINARY_NAME}"
log "正在处理 ${BINARY_NAME} ..."
# 停止旧服务
systemctl stop "${SERVICE_NAME}.service" 2>/dev/null || true
# 强制清理可能残留的进程 (避免 Text file busy)
pids=$(pgrep -f "$BINARY_NAME" || true)
if [ -n "$pids" ]; then
log "清理残留进程..."
kill -9 $pids 2>/dev/null || true
fi
# 优先检测当前目录下是否有二进制文件(本地安装模式)
if [ -f "./${BINARY_NAME}" ]; then
log "发现本地文件 ./${BINARY_NAME},跳过下载..."
cp "./${BINARY_NAME}" "$tmp_dir/$BINARY_NAME"
else
# 下载二进制
curl -fsSL "$bin_url" -o "$tmp_dir/$BINARY_NAME" &
show_progress $! "下载二进制文件"
[ -f "$tmp_dir/$BINARY_NAME" ] || fail "下载失败"
fi
# 安装文件
cp "$tmp_dir/$BINARY_NAME" "$INSTALL_DIR/$BINARY_NAME"
chmod +x "$INSTALL_DIR/$BINARY_NAME"
# 配置服务
write_service
# 启动服务
systemctl daemon-reload
systemctl enable "${SERVICE_NAME}.service"
systemctl restart "${SERVICE_NAME}.service"
sleep 2
if systemctl is-active --quiet "${SERVICE_NAME}.service"; then
log "服务启动成功"
else
log "警告: 服务启动失败,查看日志:"
journalctl -u "${SERVICE_NAME}.service" --no-pager -n 10
fi
}
write_service() {
local service_file="/etc/systemd/system/${SERVICE_NAME}.service"
cat > "$service_file" <<EOF
[Unit]
Description=MengyaMonitor Backend Service
After=network.target
[Service]
Type=simple
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/$BINARY_NAME
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/mengyamonitor.log
StandardError=append:/var/log/mengyamonitor.log
[Install]
WantedBy=multi-user.target
EOF
}
main() {
require_root
local arch
arch=$(detect_arch)
log "检测到架构: $arch"
download_and_install "$arch"
log "=========================================="
log "安装任务完成!"
log "安装目录: $INSTALL_DIR"
log "服务名称: $SERVICE_NAME"
log "=========================================="
}
main "$@"

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,15 @@
[Unit]
Description=MengyaMonitor Backend Service
After=network.target
[Service]
Type=simple
WorkingDirectory=/shumengya/bin/mengyamonitor
ExecStart=/shumengya/bin/mengyamonitor/mengyamonitor-backend
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/mengyamonitor.log
StandardError=append:/var/log/mengyamonitor.log
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,102 @@
#!/usr/bin/env bash
set -euo pipefail
# MengyaMonitor 一键卸载脚本
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/mengyamonitor/uninstall_mengyamonitor.sh" | sudo bash
INSTALL_DIR="/shumengya/bin/mengyamonitor"
SERVICE_NAME="smy-mengyamonitor"
BINARY_NAME="mengyamonitor-backend"
log() { printf '[MengyaMonitor-卸载] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[MengyaMonitor-卸载] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash uninstall_mengyamonitor.sh)"
fi
}
stop_and_disable_service() {
if systemctl is-active --quiet "${SERVICE_NAME}.service"; then
systemctl stop "${SERVICE_NAME}.service"
fi
if systemctl is-enabled --quiet "${SERVICE_NAME}.service" 2>/dev/null; then
systemctl disable "${SERVICE_NAME}.service"
fi
}
remove_service_file() {
local service_file="/etc/systemd/system/${SERVICE_NAME}.service"
if [ -f "$service_file" ]; then
rm -f "$service_file"
systemctl daemon-reload
fi
}
cleanup_process() {
# 查找并杀掉所有匹配的进程
local pids
pids=$(pgrep -f "$BINARY_NAME" || true)
if [ -n "$pids" ]; then
kill -9 $pids 2>/dev/null || true
fi
}
uninstall_main() {
log "正在卸载 MengyaMonitor ..."
(stop_and_disable_service) &
show_progress $! "停止服务"
cleanup_process
(remove_service_file) &
show_progress $! "删除服务文件"
if [ -f "$INSTALL_DIR/$BINARY_NAME" ]; then
rm -f "$INSTALL_DIR/$BINARY_NAME"
fi
# 清理日志文件(可选,这里默认清理)
if [ -f "/var/log/mengyamonitor.log" ]; then
rm -f "/var/log/mengyamonitor.log"
log "已删除日志文件"
fi
# 如果目录为空,则删除目录
if [ -d "$INSTALL_DIR" ]; then
rm -rf "$INSTALL_DIR"
log "已删除安装目录"
fi
log "=========================================="
log "卸载任务完成"
log "=========================================="
}
main() {
require_root
uninstall_main
}
main "$@"

View File

@@ -0,0 +1,182 @@
#!/usr/bin/env bash
set -euo pipefail
# openlist 一键安装脚本
# 用法示例curl -fsSL "https://pan.shumengya.top/d/scripts/openlist/install_openlist.sh" | bash
BASE_URL="https://pan.shumengya.top/d/scripts/openlist/openlist"
INSTALL_DIR="/shumengya/bin/openlist"
SERVICE_NAME="smy-openlist"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
log() { printf '[openlist-安装] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 进度条函数
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[openlist-安装] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
check_port() {
# 检查端口占用并尝试清理
local port=5244
if lsof -i :$port >/dev/null 2>&1 || netstat -tunlp | grep -q ":$port "; then
log "检测到端口 $port 被占用,尝试清理..."
fuser -k -n tcp $port >/dev/null 2>&1 || true
sleep 1
if lsof -i :$port >/dev/null 2>&1; then
# 尝试查找占用进程并强制杀掉
local pid
pid=$(lsof -t -i:$port 2>/dev/null || true)
if [ -n "$pid" ]; then
kill -9 "$pid" 2>/dev/null || true
fi
fi
fi
}
require_root() {
# 必须使用 root 权限执行
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash install_openlist.sh)"
fi
}
detect_arch() {
# 自动检测 CPU 架构,选择对应二进制
local machine
machine=$(uname -m)
case "$machine" in
x86_64|amd64) echo "amd64" ;;
aarch64|arm64) echo "arm64" ;;
*) fail "不支持的架构: $machine" ;;
esac
}
download_files() {
# 下载对应架构的二进制包和 data 目录
local arch tmp_dir binary_url data_url
arch="$1"
tmp_dir=$(mktemp -d)
# 只在 tmp_dir 存在时清理
trap 'if [ -n "${tmp_dir:-}" ] && [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi' EXIT
binary_url="${BASE_URL}/linux-${arch}.tar.gz"
data_url="${BASE_URL}/data.tgz"
# 后台下载并显示进度
curl -fsSL "$binary_url" -o "$tmp_dir/openlist.tar.gz" &
show_progress $! "正在下载 ${arch} 架构的二进制文件"
[ -f "$tmp_dir/openlist.tar.gz" ] || fail "下载二进制文件失败"
# 检查 data 目录是否已存在,如果存在则跳过下载
if [ -d "$INSTALL_DIR/data" ]; then
log "检测到已存在 data 目录,跳过下载以保护现有数据"
else
curl -fsSL "$data_url" -o "$tmp_dir/data.tgz" &
show_progress $! "正在下载 data 配置文件"
[ -f "$tmp_dir/data.tgz" ] || fail "下载 data 文件失败"
fi
echo "$tmp_dir"
}
install_binary_and_data() {
# 解压并安装二进制文件和 data 目录
local tmp_dir extracted_dir bin_path
tmp_dir="$1"
log "正在安装 openlist 到 $INSTALL_DIR..."
# 尝试停止服务
systemctl stop "$SERVICE_NAME" 2>/dev/null || true
# 检查并清理端口
check_port
mkdir -p "$INSTALL_DIR"
# 只在下载了 data.tgz 时才解压
if [ -f "$tmp_dir/data.tgz" ]; then
tar -xzf "$tmp_dir/data.tgz" -C "$INSTALL_DIR/" || fail "解压 data 目录失败"
else
log "保留现有 data 目录,不进行覆盖"
fi
# 解压二进制文件
extracted_dir=$(mktemp -d)
trap 'if [ -n "${tmp_dir:-}" ] && [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi; if [ -n "${extracted_dir:-}" ] && [ -d "$extracted_dir" ]; then rm -rf "$extracted_dir"; fi' EXIT
tar -xzf "$tmp_dir/openlist.tar.gz" -C "$extracted_dir" || fail "解压二进制文件失败"
bin_path=$(find "$extracted_dir" -maxdepth 2 -type f -name "openlist" -perm -111 | head -n 1)
[ -n "$bin_path" ] || fail "未找到 openlist 可执行文件"
cp "$bin_path" "$INSTALL_DIR/openlist" || fail "复制可执行文件失败"
chmod +x "$INSTALL_DIR/openlist"
log "文件安装完成"
}
write_service() {
# 写入 systemd 服务文件,默认自启动并在失败时重启
log "正在配置 systemd 服务..."
cat > "$SERVICE_FILE" <<'EOF'
[Unit]
Description=openlist
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/shumengya/bin/openlist
ExecStart=/shumengya/bin/openlist/openlist server
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
}
enable_service() {
# 重新加载 systemd,设置开机自启并立即启动
log "正在启用并启动服务..."
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"
# 等待几秒钟以捕获立即崩溃的情况
sleep 3
}
main() {
require_root
local arch tmp_dir=""
arch=$(detect_arch)
log "检测到系统架构: $arch"
tmp_dir=$(download_files "$arch")
install_binary_and_data "$tmp_dir"
write_service
enable_service
log "=========================================="
log "安装完成! openlist 已安装到: $INSTALL_DIR"
log "服务已启动,查看状态: systemctl status $SERVICE_NAME"
# 检查服务状态
if ! systemctl is-active --quiet "$SERVICE_NAME"; then
log "警告: 服务未能正常启动"
journalctl -u "$SERVICE_NAME" --no-pager -n 20
fi
log "=========================================="
}
main "$@"

BIN
openlist/openlist/data.tgz Normal file

Binary file not shown.

View File

@@ -0,0 +1,145 @@
{
"force": false,
"site_url": "",
"cdn": "",
"jwt_secret": "J4l3vzgvqQPWy1yH",
"token_expires_in": 48,
"database": {
"type": "sqlite3",
"host": "",
"port": 0,
"user": "",
"password": "",
"name": "",
"db_file": "data/data.db",
"table_prefix": "x_",
"ssl_mode": "",
"dsn": ""
},
"meilisearch": {
"host": "http://localhost:7700",
"api_key": "",
"index": "openlist"
},
"scheme": {
"address": "0.0.0.0",
"http_port": 5244,
"https_port": -1,
"force_https": false,
"cert_file": "",
"key_file": "",
"unix_file": "",
"unix_file_perm": "",
"enable_h2c": false,
"enable_h3": false
},
"temp_dir": "data/temp",
"bleve_dir": "data/bleve",
"dist_dir": "",
"log": {
"enable": true,
"name": "data/log/log.log",
"max_size": 50,
"max_backups": 30,
"max_age": 28,
"compress": false,
"filter": {
"enable": false,
"filters": [
{
"cidr": "",
"path": "/ping",
"method": ""
},
{
"cidr": "",
"path": "",
"method": "HEAD"
},
{
"cidr": "",
"path": "/dav/",
"method": "PROPFIND"
}
]
}
},
"delayed_start": 0,
"max_buffer_limitMB": -1,
"mmap_thresholdMB": 4,
"max_connections": 0,
"max_concurrency": 64,
"tls_insecure_skip_verify": true,
"tasks": {
"download": {
"workers": 5,
"max_retry": 1,
"task_persistant": false
},
"transfer": {
"workers": 5,
"max_retry": 2,
"task_persistant": false
},
"upload": {
"workers": 5,
"max_retry": 0,
"task_persistant": false
},
"copy": {
"workers": 5,
"max_retry": 2,
"task_persistant": false
},
"move": {
"workers": 5,
"max_retry": 2,
"task_persistant": false
},
"decompress": {
"workers": 5,
"max_retry": 2,
"task_persistant": false
},
"decompress_upload": {
"workers": 5,
"max_retry": 2,
"task_persistant": false
},
"allow_retry_canceled": false
},
"cors": {
"allow_origins": [
"*"
],
"allow_methods": [
"*"
],
"allow_headers": [
"*"
]
},
"s3": {
"enable": false,
"port": 5246,
"ssl": false
},
"ftp": {
"enable": false,
"listen": ":5221",
"find_pasv_port_attempts": 50,
"active_transfer_port_non_20": false,
"idle_timeout": 900,
"connection_timeout": 30,
"disable_active_mode": false,
"default_transfer_binary": false,
"enable_active_conn_ip_check": true,
"enable_pasv_conn_ip_check": true
},
"sftp": {
"enable": false,
"listen": ":5222"
},
"last_launched_version": "refs/heads/main",
"proxy_address": ""
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,12 @@
[Unit]
Description=openlist
After=network.target
[Service]
Type=simple
WorkingDirectory=/shumengya/bin/openlist
ExecStart=/shumengya/bin/openlist/openlist server
Restart=on-failure
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail
# 恢复并启动 openlist 服务
# 该脚本用于在执行 stopkill 后恢复服务的正常运行和开机自启
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/openlist/start_openlist.sh" | sudo bash
SERVICE_NAME="smy-openlist"
log() { printf '[openlist-启动] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 检查 root 权限
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行"
fi
log "正在检查服务状态..."
# 检查服务文件是否存在
if [ ! -f "/etc/systemd/system/${SERVICE_NAME}.service" ]; then
fail "未找到服务文件 /etc/systemd/system/${SERVICE_NAME}.service请先运行安装脚本。"
fi
log "正在恢复服务设置..."
# 重置可能的失败状态
systemctl reset-failed "$SERVICE_NAME" 2>/dev/null || true
log "正在启用并启动服务..."
# --now 选项会同时启用(enable)并启动(start)服务
systemctl enable --now "$SERVICE_NAME"
# 等待服务启动
sleep 2
# 检查启动状态
if systemctl is-active --quiet "$SERVICE_NAME"; then
log "服务启动成功!"
log "状态: $(systemctl is-active "$SERVICE_NAME")"
log "您可以访问 http://IP:5244 使用服务"
else
log "警告: 服务启动似乎遇到了问题"
log "以下是最后 10 行日志:"
systemctl status "$SERVICE_NAME" --no-pager -n 10 || true
exit 1
fi

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env bash
set -euo pipefail
# 强制停止 openlist 服务并清理进程
# 用法curl -fsSL "https://pan.shumengya.top/d/scripts/openlist/stopkill_openlist.sh" | sudo bash
SERVICE_NAME="smy-openlist"
BIN_NAME="openlist"
PORT=5244
log() { printf '[openlist-停止] %s\n' "$*" >&2; }
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
log "请使用 root 权限运行"
exit 1
fi
log "正在停止 systemd 服务..."
# systemctl stop 会将服务状态置为 inactivesystemd 不会自动重启它,除非手动 start/restart
# 即使服务被 disablesystemctl restart 仍然可以启动它
systemctl disable --now "$SERVICE_NAME" 2>/dev/null || true
systemctl stop "$SERVICE_NAME" 2>/dev/null || true
log "正在检查残留进程..."
# 排除当前脚本自身的 PID防止误杀
current_pid=$$
# 按进程名强制杀 (使用 -x 精确匹配进程名,避免匹配到脚本自身)
pids=$(pgrep -x "$BIN_NAME" || true)
# 如果 -x 没找到,尝试 -f 但过滤掉脚本自身
if [ -z "$pids" ]; then
pids=$(pgrep -f "$BIN_NAME" | grep -v "$current_pid" || true)
fi
if [ -n "$pids" ]; then
log "发现残留进程 PID: $pids,正在强制终止..."
kill -9 $pids 2>/dev/null || true
fi
# 按端口强制杀
pid_port=""
if command -v lsof >/dev/null 2>&1; then
pid_port=$(lsof -t -i:$PORT 2>/dev/null || true)
elif command -v ss >/dev/null 2>&1; then
# ss 输出格式处理,提取 pid
pid_port=$(ss -lptn "sport = :$PORT" | grep -oE 'pid=[0-9]+' | cut -d= -f2 | sort -u || true)
elif command -v netstat >/dev/null 2>&1; then
pid_port=$(netstat -nlp | grep ":$PORT " | awk '{print $7}' | cut -d/ -f1 || true)
fi
if [ -n "$pid_port" ]; then
# 再次过滤掉当前 PID (虽然不太可能占用端口,但为了安全)
pid_port=$(echo "$pid_port" | grep -v "^$current_pid$")
if [ -n "$pid_port" ]; then
log "发现端口 $PORT 占用进程 PID: $pid_port,正在强制终止..."
kill -9 $pid_port 2>/dev/null || true
fi
fi
# 重置服务失败状态,避免 systemd 认为服务处于错误状态
systemctl reset-failed "$SERVICE_NAME" 2>/dev/null || true
# 最终状态检查
log "正在验证服务状态..."
if pgrep -x "$BIN_NAME" >/dev/null; then
log "警告: 进程仍在运行!"
ps -fp $(pgrep -x "$BIN_NAME")
else
log "openlist 已完全停止 (服务已禁用,进程已清理)。"
fi

View File

@@ -0,0 +1,104 @@
#!/usr/bin/env bash
set -euo pipefail
# openlist 一键卸载脚本
# 用法sudo bash uninstall_openlist.sh
INSTALL_DIR="/shumengya/bin/openlist"
SERVICE_NAME="smy-openlist"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
log() { printf '[openlist-卸载] %s\n' "$*" >&2; }
fail() { log "错误: $*" >&2; exit 1; }
# 进度条函数
show_progress() {
local pid=$1
local text=$2
local delay=0.1
local spin='-\|/'
printf "[openlist-卸载] %s... " "$text" >&2
while ps -p "$pid" > /dev/null 2>&1; do
local temp=${spin#?}
printf "\b%c" "$spin" >&2
local spin=$temp${spin%"$temp"}
sleep $delay
done
printf "\b完成\n" >&2
}
require_root() {
# 必须使用 root 权限执行
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
fail "请使用 root 权限运行 (sudo bash uninstall_openlist.sh)"
fi
}
stop_and_disable_service() {
# 停止并禁用 systemd 服务
if systemctl is-active --quiet "$SERVICE_NAME"; then
log "正在停止服务 $SERVICE_NAME..."
systemctl stop "$SERVICE_NAME"
fi
if systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null; then
log "正在禁用服务 $SERVICE_NAME..."
systemctl disable "$SERVICE_NAME"
fi
}
remove_service_file() {
# 删除 systemd 服务文件
if [ -f "$SERVICE_FILE" ]; then
log "正在删除服务文件..."
rm -f "$SERVICE_FILE"
systemctl daemon-reload
fi
}
remove_install_dir() {
# 删除安装目录
if [ -d "$INSTALL_DIR" ]; then
log "正在删除安装目录 $INSTALL_DIR..."
rm -rf "$INSTALL_DIR"
fi
}
check_and_kill_port() {
local port=5244
if lsof -i :$port >/dev/null 2>&1 || netstat -tunlp | grep -q ":$port "; then
log "检测到端口 $port 仍被占用,尝试强制清理..."
fuser -k -n tcp $port >/dev/null 2>&1 || true
sleep 1
# 二次检查
local pid
pid=$(lsof -t -i:$port 2>/dev/null || true)
if [ -n "$pid" ]; then
kill -9 "$pid" 2>/dev/null || true
fi
fi
}
main() {
require_root
log "开始卸载 openlist..."
(stop_and_disable_service) &
show_progress $! "正在停止服务"
(remove_service_file) &
show_progress $! "正在删除服务文件"
check_and_kill_port
(remove_install_dir) &
show_progress $! "正在删除安装目录"
log "=========================================="
log "卸载完成! openlist 已从系统中移除"
log "=========================================="
}
main "$@"

201
port-info/AGENTS.md Normal file
View File

@@ -0,0 +1,201 @@
# AGENTS.md - Agent Coding Guidelines
This document provides guidelines for agents working in this repository.
## Project Overview
This is a **Bash shell script** project for displaying Linux port information (TCP, UDP, HTTP services). The main file is `port_info.sh`.
## Build / Lint / Test Commands
### Running the Script
```bash
# Make executable and run
chmod +x port_info.sh
./port_info.sh
# Or run directly with bash
bash port_info.sh
```
### Linting
Use **shellcheck** for static analysis:
```bash
# Install shellcheck (if not present)
apt-get install shellcheck # Debian/Ubuntu
yum install epel-release && yum install ShellCheck # RHEL/CentOS
# Run shellcheck on the script
shellcheck port_info.sh
# Run with specific severity levels
shellcheck -S error port_info.sh # Errors only
shellcheck -S warning port_info.sh # Warnings and errors
```
### Testing a Single Function
Bash doesn't have traditional unit tests, but you can test functions interactively:
```bash
# Source the script and test specific functions
source port_info.sh
get_service_name 80 # Test port-to-service lookup
check_commands # Test command detection
```
### Syntax Validation
```bash
# Check bash syntax without executing
bash -n port_info.sh
```
## Code Style Guidelines
### File Organization
- Single script files for small utilities
- Use clear section separators: `#===============================================================================`
- Group related functions together
- Main execution at the bottom of the file
### Formatting
- Indentation: 4 spaces
- Use `#!/bin/bash` shebang (not `#!/bin/sh` for bash-specific features)
- Maximum line length: ~100 characters (flexible for output formatting)
- Use uppercase for constants/variables, lowercase for function names
### Variable Naming
- Constants (colors, separators): UPPERCASE with underscores, e.g., `RED`, `SEPARATOR`
- Global variables: UPPERCASE, e.g., `PORT_CMD`
- Local variables in functions: lowercase with underscores, e.g., `local port=$1`
- Function names: lowercase with underscores, e.g., `check_commands()`
### Functions
```bash
# Good function definition
function_name() {
local arg1=$1
local arg2=$2
# function body
return 0 # Always return explicit status
}
# Or with function keyword
check_commands() {
# ...
}
```
### Color Variables
Define colors at the top of the script using ANSI escape codes:
```bash
RED='\033[38;5;196m'
GREEN='\033[38;5;46m'
NC='\033[0m' # No Color - always reset at end
```
### Error Handling
- Use `command -v` to check command availability
- Redirect stderr with `2>/dev/null` for expected errors
- Exit with status 1 on fatal errors: `exit 1`
- Use descriptive error messages with colors
### Input Handling
- Prefer arguments over interactive input
- Validate inputs before processing
- Use `local` for all function parameters
- Check for required arguments
### String Comparisons
```bash
# String equality
if [ "$var" = "value" ]; then
# ...
fi
# Numeric comparison
if [ "$num" -eq 0 ]; then
# ...
fi
# Regex matching
if [[ "$port" =~ ^[0-9]+$ ]]; then
# ...
fi
```
### Output Formatting
- Use `printf` for formatted output (not `echo` for complex output)
- Use color codes with `${COLOR}...${NC}` pattern
- Consistent column widths in tables
### Common Patterns
#### Command Availability Check
```bash
if command -v ss &> /dev/null; then
PORT_CMD="ss"
elif command -v netstat &> /dev/null; then
PORT_CMD="netstat"
else
echo -e "${RED}Error: command not found${NC}"
exit 1
fi
```
#### Reading Lines
```bash
while IFS= read -r line; do
# process line
done < <(command)
```
#### Safe Variable Usage
- Always quote variables: `"$var"` not `$var`
- Use `${var}` for clarity in complex expressions
- Initialize variables before use
### Shellcheck Compliance
Run `shellcheck` and fix all warnings:
- SC2086: Quote variables to prevent word splitting
- SC2166: Use `&&` instead of `-a` in test expressions
- SC2027: Quote strings containing newlines
- SC2248: Prefer printf over echo
## File Extensions
- Bash scripts: `.sh`
- No extension for executable scripts (optional)
## Documentation
- Add Chinese comments for Chinese-language projects
- Use section headers: `#===============================================================================`
- Document function purpose before definition
- Include usage information in comments
## Dependencies
This script requires:
- `ss` or `netstat net` (from-tools package)
- Standard Linux utilities: `awk`, `grep`, `sed`, `sort`, `uniq`
## Common Tasks
### Adding a New Port Service
Edit `get_service_name()` function in `port_info.sh`:
```bash
get_service_name() {
local port=$1
case $port in
80) echo "HTTP" ;;
443) echo "HTTPS" ;;
3306) echo "MySQL" ;;
# Add new port here
9000) echo "PHP-FPM" ;;
*) echo "未知" ;;
esac
}
```
### Adding a New Display Section
1. Create a new function following existing patterns
2. Add function call in `main()`
3. Use consistent color scheme and formatting

260
port-info/port_info.sh Executable file
View File

@@ -0,0 +1,260 @@
#!/bin/bash
#===============================================================================
# Linux 端口信息查看脚本
# 兼容: Ubuntu / Debian 及衍生版
# 功能: 显示 TCP、UDP、HTTP 端口服务信息
#===============================================================================
##
RED='\033[38;5;196m'
GREEN='\033[38;5;46m'
YELLOW='\033[38;5;226m'
BLUE='\033[38;5;21m'
MAGENTA='\033[38;5;201m'
CYAN='\033[38;5;51m'
WHITE='\033[38;5;255m'
ORANGE='\033[38;5;208m'
PINK='\033[38;5;219m'
LIME='\033[38;5;154m'
PURPLE='\033[38;5;141m'
GOLD='\033[38;5;220m'
GRAY='\033[38;5;244m'
NC='\033[0m'
SEPARATOR="━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
#===============================================================================
check_commands() {
# echo -e "${CYAN}▸ 检测命令...${NC}"
if command -v ss &> /dev/null; then
PORT_CMD="ss"
elif command -v netstat &> /dev/null; then
PORT_CMD="netstat"
else
echo -e "${RED}✗ 错误: 未找到 ss 或 netstat 命令${NC}"
echo -e "${YELLOW} 请安装: apt-get install net-tools${NC}"
exit 1
fi
# echo -e "${GREEN}✓ 使用命令: ${PORT_CMD}${NC}"
}
#===============================================================================
##
get_service_name() {
local port=$1
case $port in
20) echo "FTP-DATA" ;;
21) echo "FTP" ;;
22) echo "SSH" ;;
23) echo "Telnet" ;;
25) echo "SMTP" ;;
53) echo "DNS" ;;
67|68) echo "DHCP" ;;
80) echo "HTTP" ;;
110) echo "POP3" ;;
123) echo "NTP" ;;
443) echo "HTTPS" ;;
3306) echo "MySQL" ;;
3389) echo "RDP" ;;
5432) echo "PostgreSQL" ;;
6379) echo "Redis" ;;
8080) echo "HTTP-Proxy" ;;
8443) echo "HTTPS-Alt" ;;
27017) echo "MongoDB" ;;
*) echo "未知" ;;
esac
}
#===============================================================================
show_tcp_ports() {
echo -e "\n${SEPARATOR}"
echo -e "${BLUE} 🔵 TCP 端口监听列表 ${NC}"
echo -e "${SEPARATOR}"
printf "${GREEN}%-6s %-10s %-14s %-10s %-20s${NC}\n" "协议" "端口" "服务(参考)" "PID" "进程名称"
echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}"
if [ "$PORT_CMD" = "ss" ]; then
ss -tulnp 2>/dev/null | grep LISTEN | while IFS= read -r line; do
addr=$(echo "$line" | awk '{print $5}')
port="${addr##*:}"
[[ "$port" =~ ^[0-9]+$ ]] || continue
prog_field=$(echo "$line" | awk '{print $NF}')
pid=$(echo "$prog_field" | grep -oP 'pid=\K[0-9]+' | head -1)
name=$(echo "$prog_field" | sed -n 's/.*("\([^"]*\)".*/\1/p' | head -1)
[ -z "$pid" ] && pid="-"
[ -z "$name" ] && name="-"
service=$(get_service_name "$port")
printf "TCP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name"
done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do
printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "$p" "$s" "$rv" "$pi" "$n"
done
else
netstat -tulnp 2>/dev/null | grep LISTEN | while read -r line; do
port=$(echo "$line" | awk '{split($4,a,":"); print a[length(a)]}')
[[ "$port" =~ ^[0-9]+$ ]] || continue
prog=$(echo "$line" | awk '{print $NF}')
pid=$(echo "$prog" | cut -d'/' -f1)
name=$(echo "$prog" | cut -d'/' -f2 | cut -d' ' -f1)
[ -z "$pid" ] && pid="-"
[ -z "$name" ] && name="-"
service=$(get_service_name "$port")
printf "TCP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name"
done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do
printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "TCP" "$p" "$s" "$pi" "$n"
done
fi
echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}"
}
#===============================================================================
show_udp_ports() {
echo -e "\n${SEPARATOR}"
echo -e "${MAGENTA} 🟣 UDP 端口监听列表 ${NC}"
echo -e "${SEPARATOR}"
printf "${PINK}%-6s %-10s %-14s %-10s %-20s${NC}\n" "协议" "端口" "服务(参考)" "PID" "进程名称"
echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}"
if [ "$PORT_CMD" = "ss" ]; then
ss -ulnp 2>/dev/null | awk 'NR>1 && $1!="State"' | while IFS= read -r line; do
addr=$(echo "$line" | awk '{print $4}')
port="${addr##*:}"
[[ "$port" =~ ^[0-9]+$ ]] || continue
prog_field=$(echo "$line" | awk '{print $NF}')
pid=$(echo "$prog_field" | grep -oP 'pid=\K[0-9]+' | head -1)
name=$(echo "$prog_field" | sed -n 's/.*("\([^"]*\)".*/\1/p' | head -1)
[ -z "$pid" ] && pid="-"
[ -z "$name" ] && name="-"
service=$(get_service_name "$port")
printf "UDP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name"
done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do
printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "$p" "$s" "$rv" "$pi" "$n"
done
else
netstat -ulnp 2>/dev/null | awk 'NR>1' | while read -r line; do
port=$(echo "$line" | awk '{split($4,a,":"); print a[length(a)]}')
[[ "$port" =~ ^[0-9]+$ ]] || continue
prog=$(echo "$line" | awk '{print $NF}')
pid=$(echo "$prog" | cut -d'/' -f1)
name=$(echo "$prog" | cut -d'/' -f2 | cut -d' ' -f1)
[ -z "$pid" ] && pid="-"
[ -z "$name" ] && name="-"
service=$(get_service_name "$port")
printf "UDP|%-10s|%-14s|%-10s|%-20s\n" "$port" "$service" "$pid" "$name"
done | sort -t'|' -k2 -n | uniq | while IFS='|' read -r p s rv pi n; do
printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-20s${NC}\n" "$p" "$s" "$rv" "$pi" "$n"
done
fi
echo -e "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}"
}
#===============================================================================
show_http_ports() {
echo -e "\n${SEPARATOR}"
echo -e "${YELLOW} 🟡 HTTP/HTTPS 常用端口 ${NC}"
echo -e "${SEPARATOR}"
printf "${ORANGE}%-6s %-10s %-14s %-10s %-10s %-20s${NC}\n" "协议" "端口" "服务(参考)" "状态" "PID" "进程名称"
echo -e "${GRAY}────────────────────────────────────────────────────────────────────────────────────────${NC}"
http_ports="80 443 8080 8443 8000 8888 3000 5000"
for port in $http_ports; do
if [ "$PORT_CMD" = "ss" ]; then
result=$(ss -tulnp 2>/dev/null | grep ":$port " | grep -v grep)
if [ -n "$result" ]; then
proto=$(echo "$result" | awk '{print $1}' | head -1 | tr '[:upper:]' '[:lower:]')
prog_field=$(echo "$result" | awk '{print $NF}')
pid=$(echo "$prog_field" | grep -oP 'pid=\K[0-9]+' | head -1)
name=$(echo "$prog_field" | sed -n 's/.*("\([^"]*\)".*/\1/p' | head -1)
[ -z "$pid" ] && pid="-"
[ -z "$name" ] && name="-"
service=$(get_service_name "$port")
printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-10s${NC} %-20s${NC}\n" "$proto" "$port" "$service" "监听中" "$pid" "$name"
fi
else
result=$(netstat -tulnp 2>/dev/null | grep ":$port " | grep -v grep)
if [ -n "$result" ]; then
proto=$(echo "$result" | awk '{print $6}' | head -1 | tr '[:upper:]' '[:lower:]')
prog=$(echo "$result" | awk '{print $7}')
pid=$(echo "$prog" | cut -d'/' -f1)
name=$(echo "$prog" | cut -d'/' -f2 | cut -d' ' -f1)
[ -z "$pid" ] && pid="-"
[ -z "$name" ] && name="-"
service=$(get_service_name "$port")
printf "${LIME}%-6s${NC} %-10s${NC} %-14s${NC} %-10s${NC} %-10s${NC} %-20s${NC}\n" "$proto" "$port" "$service" "监听中" "$pid" "$name"
fi
fi
done
echo -e "${GRAY}────────────────────────────────────────────────────────────────────────────────────────${NC}"
echo -e "${GRAY}※ 服务(参考) 列为常用端口的默认服务名称,仅供参考,实际占用程序以进程名称列为准${NC}"
}
#===============================================================================
show_statistics() {
echo -e "\n${SEPARATOR}"
echo -e "${CYAN} 📊 端口统计信息 ${NC}"
echo -e "${SEPARATOR}"
if [ "$PORT_CMD" = "ss" ]; then
tcp_count=$(ss -tuln 2>/dev/null | grep -c LISTEN)
udp_count=$(ss -uln 2>/dev/null | awk 'NR>1 && $1 != "State" && /:[0-9]+/ {print}' | wc -l)
else
tcp_count=$(netstat -tuln 2>/dev/null | grep -c LISTEN)
udp_count=$(netstat -uln 2>/dev/null | awk 'NR>1 && /:[0-9]+/ {print}' | wc -l)
fi
total=$((tcp_count + udp_count))
printf " ${BLUE}TCP 监听端口:${NC} ${GREEN}%d${NC}\n" "$tcp_count"
printf " ${MAGENTA}UDP 监听端口:${NC} ${GREEN}%d${NC}\n" "$udp_count"
printf " ${YELLOW}总 计:${NC} ${ORANGE}%d${NC}\n" "$total"
}
#===============================================================================
show_header() {
clear
echo -e ""
echo -e "${SEPARATOR}"
echo -e "${PURPLE} ║ Linux 系统端口信息查看工具${NC}"
echo -e "${SEPARATOR}"
echo -e " ${GOLD}▸ 兼容系统:${NC} ${WHITE}Ubuntu / Debian 及衍生版本${NC}"
echo -e " ${GOLD}▸ 生成时间:${NC} ${WHITE}$(date '+%Y-%m-%d %H:%M:%S')${NC}"
echo -e "${SEPARATOR}"
}
#===============================================================================
main() {
show_header
check_commands
show_tcp_ports
show_udp_ports
show_http_ports
show_statistics
}
main

0
readme.md Normal file
View File

48
ssh/alycd.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# ssh_connect_embedded.sh
# 在脚本内直接写明密码(仅在你确认在安全内网且风险可接受时使用)
# Usage: ./bigmengya.sh [user] [host] [port]
# Example: ./bigmengya.sh alice 10.0.0.5 22
set -euo pipefail
# -------------------------
# << 在这里修改密码等配置 >>
# -------------------------
USER="root" # 可通过第一个参数覆盖
HOST="47.108.90.0" # 可通过第二个参数覆盖
PORT="22" # 可通过第三个参数覆盖
PASSWORD="tyh@19900420"
# -------------------------
# 结束配置
# -------------------------
# 小安全缓解措施
umask 077 # 新创建文件仅对当前用户可读写
trap 'unset PASSWORD' EXIT INT TERM # 退出时尝试清除变量
# 可选:如果想在调用时强制使用脚本内的 USER/HOST 而不允许参数覆盖,
# 请把上面 USER/HOST 赋值方式改为固定字面量。
# 检查 sshpass 是否存在
if ! command -v sshpass >/dev/null 2>&1; then
echo "错误:找不到 sshpass。请安装后重试。例如 Debian/Ubuntu: sudo apt install sshpass"
exit 2
fi
# 连接(禁用第一次主机密钥交互以便脚本自动连接)
# 如果你希望每次确认主机密钥,可以去掉 -o StrictHostKeyChecking=no
# 添加以下选项:
# -o PreferredAuthentications=password 强制使用密码认证
# -o PubkeyAuthentication=no 禁用公钥认证
# -o PasswordAuthentication=yes 启用密码认证
# -t 强制分配伪终端(解决curl|bash问题)
sshpass -p "$PASSWORD" ssh -t \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o PasswordAuthentication=yes \
-p "$PORT" "$USER@$HOST"
# 在脚本尾尝试清理(再次)
unset PASSWORD

48
ssh/alyxg.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# ssh_connect_embedded.sh
# 在脚本内直接写明密码(仅在你确认在安全内网且风险可接受时使用)
# Usage: ./bigmengya.sh [user] [host] [port]
# Example: ./bigmengya.sh alice 10.0.0.5 22
set -euo pipefail
# -------------------------
# << 在这里修改密码等配置 >>
# -------------------------
USER="root" # 可通过第一个参数覆盖
HOST="47.76.191.104" # 可通过第二个参数覆盖
PORT="22" # 可通过第三个参数覆盖
PASSWORD="tyh@19900420"
# -------------------------
# 结束配置
# -------------------------
# 小安全缓解措施
umask 077 # 新创建文件仅对当前用户可读写
trap 'unset PASSWORD' EXIT INT TERM # 退出时尝试清除变量
# 可选:如果想在调用时强制使用脚本内的 USER/HOST 而不允许参数覆盖,
# 请把上面 USER/HOST 赋值方式改为固定字面量。
# 检查 sshpass 是否存在
if ! command -v sshpass >/dev/null 2>&1; then
echo "错误:找不到 sshpass。请安装后重试。例如 Debian/Ubuntu: sudo apt install sshpass"
exit 2
fi
# 连接(禁用第一次主机密钥交互以便脚本自动连接)
# 如果你希望每次确认主机密钥,可以去掉 -o StrictHostKeyChecking=no
# 添加以下选项:
# -o PreferredAuthentications=password 强制使用密码认证
# -o PubkeyAuthentication=no 禁用公钥认证
# -o PasswordAuthentication=yes 启用密码认证
# -t 强制分配伪终端(解决curl|bash问题)
sshpass -p "$PASSWORD" ssh -t \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o PasswordAuthentication=yes \
-p "$PORT" "$USER@$HOST"
# 在脚本尾尝试清理(再次)
unset PASSWORD

48
ssh/bigmengya.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# ssh_connect_embedded.sh
# 在脚本内直接写明密码(仅在你确认在安全内网且风险可接受时使用)
# Usage: ./bigmengya.sh [user] [host] [port]
# Example: ./bigmengya.sh alice 10.0.0.5 22
set -euo pipefail
# -------------------------
# << 在这里修改密码等配置 >>
# -------------------------
USER="root" # 可通过第一个参数覆盖
HOST="10.0.0.233" # 可通过第二个参数覆盖
PORT="22" # 可通过第三个参数覆盖
PASSWORD="tyh@19900420"
# -------------------------
# 结束配置
# -------------------------
# 小安全缓解措施
umask 077 # 新创建文件仅对当前用户可读写
trap 'unset PASSWORD' EXIT INT TERM # 退出时尝试清除变量
# 可选:如果想在调用时强制使用脚本内的 USER/HOST 而不允许参数覆盖,
# 请把上面 USER/HOST 赋值方式改为固定字面量。
# 检查 sshpass 是否存在
if ! command -v sshpass >/dev/null 2>&1; then
echo "错误:找不到 sshpass。请安装后重试。例如 Debian/Ubuntu: sudo apt install sshpass"
exit 2
fi
# 连接(禁用第一次主机密钥交互以便脚本自动连接)
# 如果你希望每次确认主机密钥,可以去掉 -o StrictHostKeyChecking=no
# 添加以下选项:
# -o PreferredAuthentications=password 强制使用密码认证
# -o PubkeyAuthentication=no 禁用公钥认证
# -o PasswordAuthentication=yes 启用密码认证
# -t 强制分配伪终端(解决curl|bash问题)
sshpass -p "$PASSWORD" ssh -t \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o PasswordAuthentication=yes \
-p "$PORT" "$USER@$HOST"
# 在脚本尾尝试清理(再次)
unset PASSWORD

48
ssh/mengyathree.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# ssh_connect_embedded.sh
# 在脚本内直接写明密码(仅在你确认在安全内网且风险可接受时使用)
# Usage: ./bigmengya.sh [user] [host] [port]
# Example: ./bigmengya.sh alice 10.0.0.5 22
set -euo pipefail
# -------------------------
# << 在这里修改密码等配置 >>
# -------------------------
USER="root" # 可通过第一个参数覆盖
HOST="10.0.0.33" # 可通过第二个参数覆盖
PORT="22" # 可通过第三个参数覆盖
PASSWORD="tyh@19900420"
# -------------------------
# 结束配置
# -------------------------
# 小安全缓解措施
umask 077 # 新创建文件仅对当前用户可读写
trap 'unset PASSWORD' EXIT INT TERM # 退出时尝试清除变量
# 可选:如果想在调用时强制使用脚本内的 USER/HOST 而不允许参数覆盖,
# 请把上面 USER/HOST 赋值方式改为固定字面量。
# 检查 sshpass 是否存在
if ! command -v sshpass >/dev/null 2>&1; then
echo "错误:找不到 sshpass。请安装后重试。例如 Debian/Ubuntu: sudo apt install sshpass"
exit 2
fi
# 连接(禁用第一次主机密钥交互以便脚本自动连接)
# 如果你希望每次确认主机密钥,可以去掉 -o StrictHostKeyChecking=no
# 添加以下选项:
# -o PreferredAuthentications=password 强制使用密码认证
# -o PubkeyAuthentication=no 禁用公钥认证
# -o PasswordAuthentication=yes 启用密码认证
# -t 强制分配伪终端(解决curl|bash问题)
sshpass -p "$PASSWORD" ssh -t \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o PasswordAuthentication=yes \
-p "$PORT" "$USER@$HOST"
# 在脚本尾尝试清理(再次)
unset PASSWORD

48
ssh/redmi.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# ssh_connect_embedded.sh
# 在脚本内直接写明密码(仅在你确认在安全内网且风险可接受时使用)
# Usage: ./bigmengya.sh [user] [host] [port]
# Example: ./bigmengya.sh alice 10.0.0.5 22
set -euo pipefail
# -------------------------
# << 在这里修改密码等配置 >>
# -------------------------
USER="root" # 可通过第一个参数覆盖
HOST="10.0.0.10" # 可通过第二个参数覆盖
PORT="22" # 可通过第三个参数覆盖
PASSWORD="tyh@19900420"
# -------------------------
# 结束配置
# -------------------------
# 小安全缓解措施
umask 077 # 新创建文件仅对当前用户可读写
trap 'unset PASSWORD' EXIT INT TERM # 退出时尝试清除变量
# 可选:如果想在调用时强制使用脚本内的 USER/HOST 而不允许参数覆盖,
# 请把上面 USER/HOST 赋值方式改为固定字面量。
# 检查 sshpass 是否存在
if ! command -v sshpass >/dev/null 2>&1; then
echo "错误:找不到 sshpass。请安装后重试。例如 Debian/Ubuntu: sudo apt install sshpass"
exit 2
fi
# 连接(禁用第一次主机密钥交互以便脚本自动连接)
# 如果你希望每次确认主机密钥,可以去掉 -o StrictHostKeyChecking=no
# 添加以下选项:
# -o PreferredAuthentications=password 强制使用密码认证
# -o PubkeyAuthentication=no 禁用公钥认证
# -o PasswordAuthentication=yes 启用密码认证
# -t 强制分配伪终端(解决curl|bash问题)
sshpass -p "$PASSWORD" ssh -t \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o PasswordAuthentication=yes \
-p "$PORT" "$USER@$HOST"
# 在脚本尾尝试清理(再次)
unset PASSWORD

48
ssh/smallmengya.sh Normal file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# ssh_connect_embedded.sh
# 在脚本内直接写明密码(仅在你确认在安全内网且风险可接受时使用)
# Usage: ./bigmengya.sh [user] [host] [port]
# Example: ./bigmengya.sh alice 10.0.0.5 22
set -euo pipefail
# -------------------------
# << 在这里修改密码等配置 >>
# -------------------------
USER="root" # 可通过第一个参数覆盖
HOST="10.0.0.100" # 可通过第二个参数覆盖
PORT="22" # 可通过第三个参数覆盖
PASSWORD="tyh@19900420"
# -------------------------
# 结束配置
# -------------------------
# 小安全缓解措施
umask 077 # 新创建文件仅对当前用户可读写
trap 'unset PASSWORD' EXIT INT TERM # 退出时尝试清除变量
# 可选:如果想在调用时强制使用脚本内的 USER/HOST 而不允许参数覆盖,
# 请把上面 USER/HOST 赋值方式改为固定字面量。
# 检查 sshpass 是否存在
if ! command -v sshpass >/dev/null 2>&1; then
echo "错误:找不到 sshpass。请安装后重试。例如 Debian/Ubuntu: sudo apt install sshpass"
exit 2
fi
# 连接(禁用第一次主机密钥交互以便脚本自动连接)
# 如果你希望每次确认主机密钥,可以去掉 -o StrictHostKeyChecking=no
# 添加以下选项:
# -o PreferredAuthentications=password 强制使用密码认证
# -o PubkeyAuthentication=no 禁用公钥认证
# -o PasswordAuthentication=yes 启用密码认证
# -t 强制分配伪终端(解决curl|bash问题)
sshpass -p "$PASSWORD" ssh -t \
-o StrictHostKeyChecking=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o PasswordAuthentication=yes \
-p "$PORT" "$USER@$HOST"
# 在脚本尾尝试清理(再次)
unset PASSWORD

67
systemctl-info/AGENTS.md Normal file
View File

@@ -0,0 +1,67 @@
# AGENTS.md - iFlow CLI 项目指南
## 项目概述
这是一个 **systemctl 详细信息查看脚本** (v2.0 模块化版本),用于在 Linux 系统中显示 Systemd 相关的全面信息。
### 项目类型
- **语言**: Bash Shell 脚本
- **平台**: Linux
- **版本**: 2.0 (模块化版本)
- **用途**: 系统管理、信息查看
### 模块化结构
脚本已重构为 22 个独立的功能模块,每个模块对应一个 `module_xxx()` 函数:
| 模块编号 | 模块名称 | 功能描述 |
|---------|---------|---------|
| 1 | `module_systemd_version` | Systemd 版本信息 |
| 2 | `module_system_info` | 系统基础信息 (主机名、内核、OS等) |
| 3 | `module_systemd_status` | Systemd 系统状态 |
| 4 | `module_service_stats` | 服务统计信息 |
| 5 | `module_failed_services` | 失败的服务详情 |
| 6 | `module_masked_services` | 已屏蔽(Masked)的服务 |
| 7 | `module_running_services` | 运行中的服务列表 |
| 8 | `module_timer` | Timer 定时任务 |
| 9 | `module_socket` | Socket 监听单元 |
| 10 | `module_target` | Target 目标单元 |
| 11 | `module_mount` | Mount 和 Automount 挂载点 |
| 12 | `module_path` | Path 路径监控单元 (新增) |
| 13 | `module_device` | Device 设备单元 (新增) |
| 14 | `module_scope_slice` | Scope 和 Slice 资源控制单元 (新增) |
| 15 | `module_dependencies` | 系统依赖关系 (新增) |
| 16 | `module_journal` | Journal 日志摘要 |
| 17 | `module_environment` | Systemd 环境变量 |
| 18 | `module_cgroup` | Cgroup 信息 (新增) |
| 19 | `module_performance` | 系统性能信息 |
| 20 | `module_power_management` | 电源管理状态 (新增) |
| 21 | `module_critical_services` | 关键系统服务状态 |
| 22 | `module_help` | 常用命令提示 |
### 新增功能 (相比 v1.0)
- **Path 单元**: 路径监控单元的状态和监控路径
- **Device 单元**: 设备单元的详细信息
- **Scope 和 Slice**: 资源控制单元的统计和资源使用
- **依赖关系**: 系统单元依赖树和依赖数量统计
- **Cgroup 信息**: cgroup 版本、控制器、资源使用
- **电源管理**: suspend/hibernate 状态和日志
- **已屏蔽服务**: 单独列出所有被屏蔽的服务
## 运行方式
```bash
# 直接运行脚本
./systemctl-info
# 或使用 bash 执行
bash systemctl-info
```
## 注意事项
- 需要 root 权限或适当的 systemd 访问权限
- 依赖系统命令:`systemctl`, `journalctl`, `uptime`, `free`, `top`, `hostname`, `uname`, `numfmt`
- 脚本会使用 `journalctl` 查看错误日志,可能需要相应权限
- 脚本输出使用 ANSI 颜色代码,建议在支持颜色的终端中运行

802
systemctl-info/systemctl-info Executable file
View File

@@ -0,0 +1,802 @@
#!/bin/bash
# systemctl-info - 详细的systemctl信息查看脚本
# 作者: iFlow CLI
# 日期: 2026-02-13
# 版本: 2.0 (模块化版本)
# ═══════════════════════════════════════════════════════════════════════════════
# 颜色定义
# ═══════════════════════════════════════════════════════════════════════════════
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[0;37m'
BRIGHT_RED='\033[1;31m'
BRIGHT_GREEN='\033[1;32m'
BRIGHT_YELLOW='\033[1;33m'
BRIGHT_BLUE='\033[1;34m'
BRIGHT_MAGENTA='\033[1;35m'
BRIGHT_CYAN='\033[1;36m'
BRIGHT_WHITE='\033[1;37m'
ORANGE='\033[38;5;208m'
PINK='\033[38;5;205m'
PURPLE='\033[38;5;141m'
LIME='\033[38;5;154m'
RESET='\033[0m'
# ═══════════════════════════════════════════════════════════════════════════════
# 分割线样式
# ═══════════════════════════════════════════════════════════════════════════════
SEPARATOR="${BRIGHT_CYAN}═══════════════════════════════════════════════════════════════════════════════${RESET}"
THIN_SEPARATOR="${CYAN}──────────────────────────────────────────────────────────────────────────────────────${RESET}"
DASH_SEPARATOR="${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
LINE="${BRIGHT_CYAN}═══════════════════════════════════════════════════════════════════════════════${RESET}"
# ═══════════════════════════════════════════════════════════════════════════════
# 通用工具函数
# ═══════════════════════════════════════════════════════════════════════════════
# 打印标题
print_header() {
echo -e "${BRIGHT_CYAN}[Systemctl Info Viewer v2.0]${RESET}"
echo -e "${BRIGHT_CYAN}模块化 Systemd 信息查看脚本${RESET}"
echo ""
}
# 打印带颜色的小节标题
print_section() {
echo -e "${THIN_SEPARATOR}"
echo -e "${BRIGHT_BLUE}[ $1 ]${RESET}"
echo -e "${THIN_SEPARATOR}"
}
# 打印带图标的信息行
print_info() {
local icon="$1"
local label="$2"
local value="$3"
local color="$4"
echo -e "${icon} ${BRIGHT_WHITE}${label}:${RESET} ${color}${value}${RESET}"
}
# 打印子项
print_subitem() {
local label="$1"
local value="$2"
local color="$3"
echo -e " ${BRIGHT_CYAN}▸${RESET} ${BRIGHT_WHITE}${label}:${RESET} ${color}${value}${RESET}"
}
# 打印带颜色的列表项
print_list_item() {
local icon="$1"
local name="$2"
local status="$3"
local status_color="$4"
local extra="$5"
printf "${icon} ${BRIGHT_WHITE}%-45s${RESET} ${status_color}%s${RESET}%s\n" "$name" "$status" "$extra"
}
# 获取状态图标和颜色
get_state_icon_color() {
local state="$1"
case "$state" in
active|running|listening)
echo -e "✅|${BRIGHT_GREEN}"
;;
inactive)
echo -e "⭕|${BRIGHT_YELLOW}"
;;
failed)
echo -e "❌|${BRIGHT_RED}"
;;
activating|deactivating)
echo -e "🔄|${BRIGHT_CYAN}"
;;
*)
echo -e "❓|${BRIGHT_WHITE}"
;;
esac
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块1: Systemd 版本信息
# ═══════════════════════════════════════════════════════════════════════════════
module_systemd_version() {
print_section "📋 Systemd 版本信息"
SYSTEMD_VERSION=$(systemctl --version | head -n 1 | awk '{print $2}')
FEATURE_COUNT=$(systemctl --version | grep -c "features")
print_info "🔧" "Systemd 版本" "$SYSTEMD_VERSION" "${BRIGHT_GREEN}"
print_info "✨" "支持功能特性" "$FEATURE_COUNT 项" "${LIME}"
echo -e "${BRIGHT_CYAN}详细版本信息:${RESET}"
systemctl --version | while IFS= read -r line; do
echo -e " ${CYAN}${line}${RESET}"
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块2: 系统基础信息
# ═══════════════════════════════════════════════════════════════════════════════
module_system_info() {
print_section "🖥️ 系统基础信息"
HOSTNAME=$(hostname)
KERNEL_VERSION=$(uname -r)
OS_ID=$(grep '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"')
OS_NAME=$(grep '^PRETTY_NAME=' /etc/os-release | cut -d'=' -f2 | tr -d '"')
ARCH=$(uname -m)
UPTIME=$(uptime -p)
print_info "🖥️" "主机名" "$HOSTNAME" "${BRIGHT_YELLOW}"
print_info "🐧" "内核版本" "$KERNEL_VERSION" "${ORANGE}"
print_info "📦" "操作系统ID" "$OS_ID" "${PINK}"
print_info "💻" "系统名称" "$OS_NAME" "${PURPLE}"
print_info "🏗️" "系统架构" "$ARCH" "${BRIGHT_CYAN}"
print_info "⏱️" "系统运行时间" "$UPTIME" "${LIME}"
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块3: Systemd 系统状态
# ═══════════════════════════════════════════════════════════════════════════════
module_systemd_status() {
print_section "⚙️ Systemd 系统状态"
SYSTEM_STATE=$(systemctl is-system-running)
DEFAULT_TARGET=$(systemctl get-default)
INIT_PID=$(systemctl show --property=MainPID --value)
BOOT_TIME=$(systemctl show --property=UserspaceTimestamp --value | cut -d' ' -f1)
case $SYSTEM_STATE in
running)
STATE_COLOR="${BRIGHT_GREEN}"
STATE_ICON="✅"
;;
degraded)
STATE_COLOR="${BRIGHT_YELLOW}"
STATE_ICON="⚠️"
;;
maintenance)
STATE_COLOR="${BRIGHT_RED}"
STATE_ICON="🔧"
;;
*)
STATE_COLOR="${BRIGHT_WHITE}"
STATE_ICON="❓"
;;
esac
print_info "$STATE_ICON" "系统状态" "$SYSTEM_STATE" "$STATE_COLOR"
print_info "🎯" "默认运行级别" "$DEFAULT_TARGET" "${BRIGHT_CYAN}"
print_info "🔄" "Init 进程 PID" "$INIT_PID" "${ORANGE}"
print_info "🚀" "启动时间" "$BOOT_TIME" "${PURPLE}"
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块4: 服务(Service)统计与状态
# ═══════════════════════════════════════════════════════════════════════════════
module_service_stats() {
print_section "🔌 服务(Service)统计与状态"
TOTAL_UNITS=$(systemctl list-unit-files --type=service --no-legend | wc -l)
ENABLED_SERVICES=$(systemctl list-unit-files --type=service --state=enabled --no-legend | wc -l)
DISABLED_SERVICES=$(systemctl list-unit-files --type=service --state=disabled --no-legend | wc -l)
STATIC_SERVICES=$(systemctl list-unit-files --type=service --state=static --no-legend | wc -l)
MASKED_SERVICES=$(systemctl list-unit-files --type=service --state=masked --no-legend | wc -l)
RUNNING_SERVICES=$(systemctl list-units --type=service --state=running --no-legend | wc -l)
FAILED_SERVICES=$(systemctl list-units --type=service --state=failed --no-legend | wc -l)
echo -e "${BRIGHT_CYAN}服务文件统计:${RESET}"
print_subitem "总服务数" "$TOTAL_UNITS" "${BRIGHT_WHITE}"
print_subitem "已启用(enabled)" "$ENABLED_SERVICES" "${BRIGHT_GREEN}"
print_subitem "已禁用(disabled)" "$DISABLED_SERVICES" "${BRIGHT_RED}"
print_subitem "静态服务(static)" "$STATIC_SERVICES" "${BRIGHT_YELLOW}"
print_subitem "已屏蔽(masked)" "$MASKED_SERVICES" "${PURPLE}"
echo -e "${BRIGHT_CYAN}服务运行状态:${RESET}"
print_subitem "运行中" "$RUNNING_SERVICES" "${LIME}"
print_subitem "失败" "$FAILED_SERVICES" "${BRIGHT_RED}"
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块5: 失败的服务详情
# ═══════════════════════════════════════════════════════════════════════════════
module_failed_services() {
FAILED_SERVICES=$(systemctl list-units --type=service --state=failed --no-legend | wc -l)
if [ "$FAILED_SERVICES" -gt 0 ]; then
print_section "❌ 失败的服务详情 (共 $FAILED_SERVICES 个)"
systemctl list-units --type=service --state=failed --no-pager | sed '1,1d' | while IFS= read -r line; do
if [ -n "$line" ]; then
SERVICE_NAME=$(echo "$line" | awk '{print $1}')
LOAD_STATE=$(echo "$line" | awk '{print $2}')
ACTIVE_STATE=$(echo "$line" | awk '{print $3}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
DESCRIPTION=$(echo "$line" | awk '{for(i=5;i<=NF;i++)print $i}' | tr '\n' ' ' | sed 's/ $//')
echo -e "${BRIGHT_RED}✗${RESET} ${BRIGHT_WHITE}${SERVICE_NAME}${RESET}"
echo -e " ${CYAN}描述:${RESET} ${WHITE}${DESCRIPTION}${RESET}"
echo -e " ${CYAN}状态:${RESET} ${RED}${LOAD_STATE}${RESET}|${RED}${ACTIVE_STATE}${RESET}|${RED}${SUB_STATE}${RESET}"
fi
done
else
print_section "✅ 失败的服务详情"
echo -e "${BRIGHT_GREEN} 没有失败的服务${RESET}"
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块6: 已屏蔽(Masked)的服务
# ═══════════════════════════════════════════════════════════════════════════════
module_masked_services() {
MASKED_COUNT=$(systemctl list-unit-files --type=service --state=masked --no-legend | wc -l)
print_section "🚫 已屏蔽(Masked)的服务"
print_subitem "已屏蔽服务数" "$MASKED_COUNT" "${PURPLE}"
if [ "$MASKED_COUNT" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}已屏蔽的服务列表:${RESET}"
systemctl list-unit-files --type=service --state=masked --no-legend | while IFS= read -r line; do
if [ -n "$line" ]; then
echo -e " ${PURPLE}✗${RESET} ${BRIGHT_WHITE}${line}${RESET}"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块7: 运行中的服务
# ═══════════════════════════════════════════════════════════════════════════════
module_running_services() {
print_section "🟢 运行中的服务 (Top 20)"
RUNNING_COUNT=$(systemctl list-units --type=service --state=running --no-legend | wc -l)
print_subitem "运行中服务总数" "$RUNNING_COUNT" "${LIME}"
echo -e "${BRIGHT_CYAN}运行中的服务列表:${RESET}"
systemctl list-units --type=service --state=running --no-pager --no-legend | head -20 | while IFS= read -r line; do
if [ -n "$line" ]; then
SERVICE_NAME=$(echo "$line" | awk '{print $1}')
LOAD_STATE=$(echo "$line" | awk '{print $2}')
ACTIVE_STATE=$(echo "$line" | awk '{print $3}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
printf " ${BRIGHT_GREEN}●${RESET} ${BRIGHT_WHITE}%-40s${RESET} ${CYAN}%-8s${RESET} ${BRIGHT_GREEN}%-10s${RESET} ${BRIGHT_CYAN}%s${RESET}\n" "$SERVICE_NAME" "$LOAD_STATE" "$ACTIVE_STATE" "$SUB_STATE"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块8: Timer 定时任务
# ═══════════════════════════════════════════════════════════════════════════════
module_timer() {
print_section "⏰ Timer 定时任务"
TOTAL_TIMERS=$(systemctl list-units --type=timer --all --no-legend | wc -l)
ACTIVE_TIMERS=$(systemctl list-units --type=timer --state=active --no-legend | wc -l)
print_subitem "总 Timer 数" "$TOTAL_TIMERS" "${BRIGHT_WHITE}"
print_subitem "活跃 Timer" "$ACTIVE_TIMERS" "${LIME}"
if [ "$ACTIVE_TIMERS" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}活跃的定时任务 (Top 15):${RESET}"
systemctl list-units --type=timer --state=active --no-pager --no-legend | head -15 | while IFS= read -r line; do
if [ -n "$line" ]; then
TIMER_NAME=$(echo "$line" | awk '{print $1}')
NEXT_RUN=$(systemctl show "$TIMER_NAME" --property=NextElapseUSec --value 2>/dev/null)
printf " ${BRIGHT_YELLOW}⏱${RESET} ${BRIGHT_WHITE}%-40s${RESET} ${CYAN}下次执行:${RESET} ${LIME}%s${RESET}\n" "$TIMER_NAME" "$NEXT_RUN"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块9: Socket 单元
# ═══════════════════════════════════════════════════════════════════════════════
module_socket() {
print_section "🔌 Socket 监听"
TOTAL_SOCKETS=$(systemctl list-units --type=socket --all --no-legend | wc -l)
LISTENING_SOCKETS=$(systemctl list-units --type=socket --state=listening --no-legend | wc -l)
print_subitem "总 Socket 数" "$TOTAL_SOCKETS" "${BRIGHT_WHITE}"
print_subitem "监听中" "$LISTENING_SOCKETS" "${LIME}"
if [ "$LISTENING_SOCKETS" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}正在监听的 Socket (Top 15):${RESET}"
systemctl list-units --type=socket --state=listening --no-pager --no-legend | head -15 | while IFS= read -r line; do
if [ -n "$line" ]; then
SOCKET_NAME=$(echo "$line" | awk '{print $1}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
printf " ${BRIGHT_MAGENTA}🔌${RESET} ${BRIGHT_WHITE}%-40s${RESET} ${CYAN}%s${RESET}\n" "$SOCKET_NAME" "$SUB_STATE"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块10: Target 目标单元
# ═══════════════════════════════════════════════════════════════════════════════
module_target() {
print_section "🎯 Target 目标单元"
ACTIVE_TARGETS=$(systemctl list-units --type=target --state=active --no-legend | wc -l)
print_subitem "当前激活的 Target" "$ACTIVE_TARGETS" "${LIME}"
echo -e "${BRIGHT_CYAN}重要的 Target 单元:${RESET}"
IMPORTANT_TARGETS=("default.target" "multi-user.target" "graphical.target" "basic.target" "rescue.target" "emergency.target" "network.target" "sysinit.target")
for target in "${IMPORTANT_TARGETS[@]}"; do
TARGET_STATE=$(systemctl is-active "$target" 2>/dev/null)
TARGET_ENABLED=$(systemctl is-enabled "$target" 2>/dev/null)
if [ -n "$TARGET_STATE" ]; then
case $TARGET_STATE in
active) STATE_ICON="✅"; STATE_COLOR="${BRIGHT_GREEN}" ;;
inactive) STATE_ICON="⭕"; STATE_COLOR="${BRIGHT_YELLOW}" ;;
*) STATE_ICON="❓"; STATE_COLOR="${BRIGHT_WHITE}" ;;
esac
printf " ${STATE_ICON} ${BRIGHT_WHITE}%-25s${RESET} ${STATE_COLOR}状态:%-10s${RESET} ${CYAN}启用:%s${RESET}\n" "$target" "$TARGET_STATE" "$TARGET_ENABLED"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块11: Mount 和 Automount 单元
# ═══════════════════════════════════════════════════════════════════════════════
module_mount() {
print_section "📁 挂载点(Mount)信息"
TOTAL_MOUNTS=$(systemctl list-units --type=mount --all --no-legend | wc -l)
ACTIVE_MOUNTS=$(systemctl list-units --type=mount --state=active --no-legend | wc -l)
TOTAL_AUTOMOUNTS=$(systemctl list-units --type=automount --all --no-legend | wc -l)
ACTIVE_AUTOMOUNTS=$(systemctl list-units --type=automount --state=active --no-legend | wc -l)
print_subitem "挂载点总数" "$TOTAL_MOUNTS" "${BRIGHT_WHITE}"
print_subitem "活跃挂载点" "$ACTIVE_MOUNTS" "${LIME}"
print_subitem "自动挂载总数" "$TOTAL_AUTOMOUNTS" "${BRIGHT_WHITE}"
print_subitem "活跃自动挂载" "$ACTIVE_AUTOMOUNTS" "${LIME}"
if [ "$ACTIVE_MOUNTS" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}挂载点详情 (Top 10):${RESET}"
systemctl list-units --type=mount --state=active --no-pager --no-legend | head -10 | while IFS= read -r line; do
if [ -n "$line" ]; then
MOUNT_NAME=$(echo "$line" | awk '{print $1}')
MOUNT_POINT=$(systemctl show "$MOUNT_NAME" --property=Where --value 2>/dev/null)
SUB_STATE=$(echo "$line" | awk '{print $4}')
printf " ${BRIGHT_CYAN}📂${RESET} ${BRIGHT_WHITE}%-35s${RESET} ${PURPLE}%s${RESET}\n" "$MOUNT_POINT" "$SUB_STATE"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块12: Path 单元
# ═══════════════════════════════════════════════════════════════════════════════
module_path() {
print_section "📍 Path 路径监控单元"
TOTAL_PATHS=$(systemctl list-units --type=path --all --no-legend | wc -l)
ACTIVE_PATHS=$(systemctl list-units --type=path --state=active --no-legend | wc -l)
print_subitem "总 Path 数" "$TOTAL_PATHS" "${BRIGHT_WHITE}"
print_subitem "活跃 Path" "$ACTIVE_PATHS" "${LIME}"
if [ "$ACTIVE_PATHS" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}活跃的 Path 监控 (Top 10):${RESET}"
systemctl list-units --type=path --state=active --no-pager --no-legend | head -10 | while IFS= read -r line; do
if [ -n "$line" ]; then
PATH_NAME=$(echo "$line" | awk '{print $1}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
PATH_PATH=$(systemctl show "$PATH_NAME" --property=PathExists --value 2>/dev/null)
printf " ${BRIGHT_CYAN}📍${RESET} ${BRIGHT_WHITE}%-40s${RESET} ${CYAN}监控:${RESET} ${LIME}%s${RESET} ${CYAN}状态:%s${RESET}\n" "$PATH_NAME" "$PATH_PATH" "$SUB_STATE"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块13: Device 单元
# ═══════════════════════════════════════════════════════════════════════════════
module_device() {
print_section "🔧 Device 设备单元"
TOTAL_DEVICES=$(systemctl list-units --type=device --all --no-legend | wc -l)
ACTIVE_DEVICES=$(systemctl list-units --type=device --state=active --no-legend | wc -l)
print_subitem "总设备数" "$TOTAL_DEVICES" "${BRIGHT_WHITE}"
print_subitem "活跃设备" "$ACTIVE_DEVICES" "${LIME}"
if [ "$ACTIVE_DEVICES" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}活跃的设备 (Top 10):${RESET}"
systemctl list-units --type=device --state=active --no-pager --no-legend | head -10 | while IFS= read -r line; do
if [ -n "$line" ]; then
DEVICE_NAME=$(echo "$line" | awk '{print $1}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
printf " ${BRIGHT_YELLOW}🔧${RESET} ${BRIGHT_WHITE}%-45s${RESET} ${LIME}%s${RESET}\n" "$DEVICE_NAME" "$SUB_STATE"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块14: Scope 和 Slice 单元
# ═══════════════════════════════════════════════════════════════════════════════
module_scope_slice() {
print_section "📊 Scope 和 Slice 资源控制单元"
# Scope 单元
TOTAL_SCOPES=$(systemctl list-units --type=scope --all --no-legend | wc -l)
ACTIVE_SCOPES=$(systemctl list-units --type=scope --state=running --no-legend | wc -l)
print_subitem "Scope 总数" "$TOTAL_SCOPES" "${BRIGHT_WHITE}"
print_subitem "运行中 Scope" "$ACTIVE_SCOPES" "${LIME}"
if [ "$ACTIVE_SCOPES" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}运行中的 Scope (Top 10):${RESET}"
systemctl list-units --type=scope --state=running --no-pager --no-legend | head -10 | while IFS= read -r line; do
if [ -n "$line" ]; then
SCOPE_NAME=$(echo "$line" | awk '{print $1}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
printf " ${BRIGHT_CYAN}📊${RESET} ${BRIGHT_WHITE}%-45s${RESET} ${LIME}%s${RESET}\n" "$SCOPE_NAME" "$SUB_STATE"
fi
done
fi
# Slice 单元
echo ""
TOTAL_SLICES=$(systemctl list-units --type=slice --all --no-legend | wc -l)
ACTIVE_SLICES=$(systemctl list-units --type=slice --state=active --no-legend | wc -l)
print_subitem "Slice 总数" "$TOTAL_SLICES" "${BRIGHT_WHITE}"
print_subitem "活跃 Slice" "$ACTIVE_SLICES" "${LIME}"
if [ "$ACTIVE_SLICES" -gt 0 ]; then
echo -e "${BRIGHT_CYAN}活跃的 Slice:${RESET}"
systemctl list-units --type=slice --state=active --no-pager --no-legend | head -10 | while IFS= read -r line; do
if [ -n "$line" ]; then
SLICE_NAME=$(echo "$line" | awk '{print $1}')
SUB_STATE=$(echo "$line" | awk '{print $4}')
MEMORY=$(systemctl show "$SLICE_NAME" --property=MemoryCurrent --value 2>/dev/null)
if [ -n "$MEMORY" ] && [ "$MEMORY" != "[not set]" ]; then
MEMORY_DISPLAY="内存: $(numfmt --to=iec $MEMORY 2>/dev/null || echo $MEMORY)"
else
MEMORY_DISPLAY=""
fi
printf " ${BRIGHT_MAGENTA}📦${RESET} ${BRIGHT_WHITE}%-30s${RESET} ${LIME}%s${RESET} %s\n" "$SLICE_NAME" "$SUB_STATE" "$MEMORY_DISPLAY"
fi
done
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块15: 依赖关系
# ═══════════════════════════════════════════════════════════════════════════════
module_dependencies() {
print_section "🔗 系统依赖关系"
# 显示默认.target的依赖树
DEFAULT_TARGET=$(systemctl get-default)
echo -e "${BRIGHT_CYAN}默认目标 '$DEFAULT_TARGET' 的依赖 (前15个):${RESET}"
systemctl list-dependencies "$DEFAULT_TARGET" --no-pager --no-legend | head -15 | while IFS= read -r line; do
if [ -n "$line" ]; then
UNIT_TYPE=$(echo "$line" | grep -o '\.[a-z]*$' | tr -d '.')
case "$UNIT_TYPE" in
service) ICON="🔌" ;;
target) ICON="🎯" ;;
timer) ICON="⏰" ;;
socket) ICON="🔌" ;;
mount) ICON="📁" ;;
path) ICON="📍" ;;
*) ICON="📄" ;;
esac
printf " ${ICON} ${BRIGHT_WHITE}%s${RESET}\n" "$line"
fi
done
# 显示被依赖最多的服务
echo ""
echo -e "${BRIGHT_CYAN}系统关键.target的依赖数量:${RESET}"
for target in "multi-user.target" "graphical.target" "basic.target" "network.target"; do
DEP_COUNT=$(systemctl list-dependencies "$target" --no-legend 2>/dev/null | wc -l)
if [ -n "$DEP_COUNT" ]; then
print_subitem "$target" "$DEP_COUNT 个依赖" "${BRIGHT_CYAN}"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块16: Systemd 日志信息
# ═══════════════════════════════════════════════════════════════════════════════
module_journal() {
print_section "📝 Systemd Journal 日志摘要"
JOURNAL_SIZE=$(journalctl --disk-usage | grep "Journals use" | awk '{print $3,$4}')
JOURNAL_ENTRIES=$(journalctl --no-pager -n 0 2>/dev/null | wc -l)
print_subitem "日志磁盘占用" "$JOURNAL_SIZE" "${ORANGE}"
print_subitem "日志总条目" "$JOURNAL_ENTRIES" "${BRIGHT_CYAN}"
echo -e "${BRIGHT_CYAN}最近的错误日志 (最近5条):${RESET}"
journalctl -p err -n 5 --no-pager 2>/dev/null | while IFS= read -r line; do
if [ -n "$line" ]; then
echo -e " ${RED}✗${RESET} ${WHITE}${line}${RESET}"
fi
done
echo -e "${BRIGHT_CYAN}最近的警告日志 (最近3条):${RESET}"
journalctl -p warning -n 3 --no-pager 2>/dev/null | while IFS= read -r line; do
if [ -n "$line" ]; then
echo -e " ${YELLOW}⚠${RESET} ${WHITE}${line}${RESET}"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块17: Systemd 环境变量
# ═══════════════════════════════════════════════════════════════════════════════
module_environment() {
print_section "🔧 Systemd 环境变量"
ENV_COUNT=$(systemctl show-environment 2>/dev/null | wc -l)
print_subitem "环境变量数量" "$ENV_COUNT" "${BRIGHT_CYAN}"
echo -e "${BRIGHT_CYAN}系统环境变量:${RESET}"
systemctl show-environment 2>/dev/null | head -15 | while IFS= read -r line; do
if [ -n "$line" ]; then
KEY=$(echo "$line" | cut -d'=' -f1)
VALUE=$(echo "$line" | cut -d'=' -f2-)
echo -e " ${BRIGHT_YELLOW}●${RESET} ${BRIGHT_CYAN}${KEY}${RESET}=${BRIGHT_WHITE}${VALUE}${RESET}"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块18: Cgroup 信息
# ═══════════════════════════════════════════════════════════════════════════════
module_cgroup() {
print_section "🧊 Cgroup 信息"
# 获取 cgroup 版本
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
CGROUP_VERSION="v2 (unified)"
else
CGROUP_VERSION="v1 (legacy)"
fi
print_subitem "Cgroup 版本" "$CGROUP_VERSION" "${BRIGHT_CYAN}"
# 获取控制器信息
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
CONTROLLERS=$(cat /sys/fs/cgroup/cgroup.controllers 2>/dev/null | tr ' ' ', ')
else
CONTROLLERS=$(cat /sys/fs/cgroup/devices.list 2>/dev/null | head -1 | cut -d' ' -f1 || echo "N/A")
fi
print_subitem "可用控制器" "$CONTROLLERS" "${LIME}"
# Slice 资源统计
echo -e "${BRIGHT_CYAN}Slice 资源使用 (Top 5):${RESET}"
for slice in $(systemctl list-units --type=slice --state=active --no-legend | awk '{print $1}' | head -5); do
MEM_CURRENT=$(systemctl show "$slice" --property=MemoryCurrent --value 2>/dev/null)
MEM_MAX=$(systemctl show "$slice" --property=MemoryMax --value 2>/dev/null)
CPU_WEIGHT=$(systemctl show "$slice" --property=CPUWeight --value 2>/dev/null)
MEM_DISP=""
if [ -n "$MEM_CURRENT" ] && [ "$MEM_CURRENT" != "[not set]" ]; then
MEM_DISP="内存: $(numfmt --to=iec $MEM_CURRENT 2>/dev/null || echo $MEM_CURRENT)"
fi
if [ -n "$CPU_WEIGHT" ] && [ "$CPU_WEIGHT" != "[not set]" ]; then
MEM_DISP="$MEM_DISP CPU权重: $CPU_WEIGHT"
fi
if [ -n "$MEM_DISP" ]; then
printf " ${BRIGHT_MAGENTA}📦${RESET} ${BRIGHT_WHITE}%-25s${RESET} ${LIME}%s${RESET}\n" "$slice" "$MEM_DISP"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块19: 系统性能信息
# ═══════════════════════════════════════════════════════════════════════════════
module_performance() {
print_section "📊 系统性能信息"
# 获取 CPU 使用率
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
# 获取内存信息
MEM_INFO=$(free -h | grep "Mem:")
MEM_TOTAL=$(echo "$MEM_INFO" | awk '{print $2}')
MEM_USED=$(echo "$MEM_INFO" | awk '{print $3}')
MEM_FREE=$(echo "$MEM_INFO" | awk '{print $4}')
MEM_PERCENT=$(free | grep "Mem:" | awk '{printf "%.1f", $3/$2*100}')
# 获取启动时间
BOOT_TIME_SEC=$(systemctl show --property=UserspaceTimestampMonotonic --value | cut -d' ' -f1)
BOOT_TIME_SEC=${BOOT_TIME_SEC:-0}
BOOT_TIME_SEC=$((BOOT_TIME_SEC / 1000000))
print_subitem "CPU 使用率" "${CPU_USAGE}%" "${BRIGHT_YELLOW}"
print_subitem "内存总量" "$MEM_TOTAL" "${BRIGHT_CYAN}"
print_subitem "已用内存" "$MEM_USED (${MEM_PERCENT}%)" "${ORANGE}"
print_subitem "可用内存" "$MEM_FREE" "${LIME}"
print_subitem "启动耗时" "${BOOT_TIME_SEC} 秒" "${PURPLE}"
# Swap 信息
SWAP_TOTAL=$(free -h | grep "Swap:" | awk '{print $2}')
SWAP_USED=$(free -h | grep "Swap:" | awk '{print $3}')
SWAP_FREE=$(free -h | grep "Swap:" | awk '{print $4}')
if [ "$SWAP_TOTAL" != "0" ]; then
print_subitem "Swap总量" "$SWAP_TOTAL" "${PINK}"
print_subitem "Swap已用" "$SWAP_USED" "${PINK}"
print_subitem "Swap可用" "$SWAP_FREE" "${PINK}"
fi
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块20: 电源管理状态
# ═══════════════════════════════════════════════════════════════════════════════
module_power_management() {
print_section "🔋 电源管理状态"
# 检查 systemd-suspend 服务
if systemctl list-unit-files | grep -q "systemd-suspend.service"; then
SUSPEND_STATE=$(systemctl is-enabled systemd-suspend.service 2>/dev/null || echo "N/A")
print_subitem "Suspend 服务" "$SUSPEND_STATE" "${BRIGHT_CYAN}"
fi
# 检查 systemd-hibernate 服务
if systemctl list-unit-files | grep -q "systemd-hibernate.service"; then
HIBERNATE_STATE=$(systemctl is-enabled systemd-hibernate.service 2>/dev/null || echo "N/A")
print_subitem "Hibernate 服务" "$HIBERNATE_STATE" "${BRIGHT_CYAN}"
fi
# 检查 logind 状态
if systemctl list-unit-files | grep -q "systemd-logind.service"; then
LOGIND_STATE=$(systemctl is-active systemd-logind.service 2>/dev/null || echo "N/A")
print_subitem "Logind 状态" "$LOGIND_STATE" "${LIME}"
fi
# 显示电源相关事件
echo -e "${BRIGHT_CYAN}最近的电源相关日志:${RESET}"
journalctl -u systemd-logind -u upower -n 3 --no-pager 2>/dev/null | while IFS= read -r line; do
if [ -n "$line" ]; then
echo -e " ${CYAN}▸${RESET} ${WHITE}${line}${RESET}"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块21: 关键服务状态
# ═══════════════════════════════════════════════════════════════════════════════
module_critical_services() {
print_section "🔑 关键系统服务状态"
KEY_SERVICES=(
"sshd.service"
"NetworkManager.service"
"cron.service"
"rsyslog.service"
"dbus.service"
"systemd-logind.service"
"systemd-journald.service"
"systemd-udevd.service"
"polkit.service"
)
for service in "${KEY_SERVICES[@]}"; do
if systemctl list-unit-files 2>/dev/null | grep -q "$service"; then
SERVICE_STATE=$(systemctl is-active "$service" 2>/dev/null)
SERVICE_ENABLED=$(systemctl is-enabled "$service" 2>/dev/null)
case $SERVICE_STATE in
active) STATE_ICON="✅"; STATE_COLOR="${BRIGHT_GREEN}" ;;
inactive) STATE_ICON="⭕"; STATE_COLOR="${BRIGHT_YELLOW}" ;;
failed) STATE_ICON="❌"; STATE_COLOR="${BRIGHT_RED}" ;;
*) STATE_ICON="❓"; STATE_COLOR="${BRIGHT_WHITE}" ;;
esac
printf " ${STATE_ICON} ${BRIGHT_WHITE}%-30s${RESET} ${STATE_COLOR}%-10s${RESET} ${CYAN}启用:%s${RESET}\n" "$service" "$SERVICE_STATE" "$SERVICE_ENABLED"
fi
done
}
# ═══════════════════════════════════════════════════════════════════════════════
# 模块22: 常用命令提示
# ═══════════════════════════════════════════════════════════════════════════════
module_help() {
print_section "💡 常用 Systemctl 命令"
echo -e "${BRIGHT_YELLOW}=== 服务管理 ===${RESET}"
echo -e "${BRIGHT_WHITE}systemctl status <service>${RESET} - 查看服务状态"
echo -e "${BRIGHT_WHITE}systemctl start <service>${RESET} - 启动服务"
echo -e "${BRIGHT_WHITE}systemctl stop <service>${RESET} - 停止服务"
echo -e "${BRIGHT_WHITE}systemctl restart <service>${RESET} - 重启服务"
echo -e "${BRIGHT_WHITE}systemctl enable <service>${RESET} - 启用开机自启"
echo -e "${BRIGHT_WHITE}systemctl disable <service>${RESET} - 禁用开机自启"
echo -e "${BRIGHT_WHITE}systemctl mask <service>${RESET} - 屏蔽服务"
echo -e "${BRIGHT_WHITE}systemctl unmask <service>${RESET} - 取消屏蔽"
echo -e "${BRIGHT_YELLOW}=== 状态查看 ===${RESET}"
echo -e "${BRIGHT_WHITE}systemctl is-active <service>${RESET} - 检查服务是否活跃"
echo -e "${BRIGHT_WHITE}systemctl is-enabled <service>${RESET} - 检查服务是否启用"
echo -e "${BRIGHT_WHITE}systemctl --failed${RESET} - 查看失败的服务"
echo -e "${BRIGHT_WHITE}systemctl list-dependencies <unit>${RESET} - 查看依赖"
echo -e "${BRIGHT_YELLOW}=== 日志查看 ===${RESET}"
echo -e "${BRIGHT_WHITE}journalctl -u <service>${RESET} - 查看服务日志"
echo -e "${BRIGHT_WHITE}journalctl -xe${RESET} - 查看最近日志"
echo -e "${BRIGHT_WHITE}journalctl -p err${RESET} - 查看错误日志"
echo -e "${BRIGHT_YELLOW}=== 电源管理 ===${RESET}"
echo -e "${BRIGHT_WHITE}systemctl suspend${RESET} - 挂起"
echo -e "${BRIGHT_WHITE}systemctl hibernate${RESET} - 休眠"
echo -e "${BRIGHT_WHITE}systemctl reboot${RESET} - 重启"
echo -e "${BRIGHT_WHITE}systemctl poweroff${RESET} - 关机"
}
# ═══════════════════════════════════════════════════════════════════════════════
# 主函数 - 模块调度
# ═══════════════════════════════════════════════════════════════════════════════
main() {
print_header
# 基础信息模块
module_systemd_version
module_system_info
module_systemd_status
# 单元统计模块
module_service_stats
module_running_services
module_failed_services
module_masked_services
# 各类单元模块
module_timer
module_socket
module_target
module_mount
module_path
module_device
module_scope_slice
# 系统信息模块
module_dependencies
module_journal
module_environment
module_cgroup
module_performance
module_power_management
# 服务状态模块
module_critical_services
# 帮助信息
module_help
# 结束
echo -e "${DASH_SEPARATOR}"
echo -e "${BRIGHT_MAGENTA}✨ 信息收集完成!时间: $(date '+%Y-%m-%d %H:%M:%S') ✨${RESET}"
echo -e "${DASH_SEPARATOR}"
}
# 执行主函数
main "@"

1219
user-manager/user-manager.sh Executable file

File diff suppressed because it is too large Load Diff