函数自动加载器
获取
~/.config/shell_functions
目录下的所有shell文件中的函数,将函数注册到~/.bashrc
文件,方便终端使用
一、创建shell函数目录
mkdir -p ~/.config/shell_functions
二、添加功能函数
1. 添加函数加载器
cat > ~/.config/shell_functions/function_loader.sh <<'EOF'
#!/bin/bash
# ====================== 函数自动加载器 ======================
# 文件位置: ~/.config/shell_functions/function_loader.sh
# 颜色定义
COLOR_RED='\033[0;31m'
COLOR_GREEN='\033[0;32m'
COLOR_YELLOW='\033[0;33m'
COLOR_BLUE='\033[0;34m'
COLOR_CYAN='\033[0;36m'
COLOR_RESET='\033[0m'
# 主加载函数
__load_shell_function() {
local func_name="$1"
local loaded_files=()
for func_file in ~/.config/shell_functions/*.sh; do
[[ "$func_file" == *"function_loader.sh" ]] && continue
if [[ -f "$func_file" ]]; then
if grep -q -E "^(function[[:space:]]+)?${func_name}[[:space:]]*[({]" "$func_file"; then
if [[ ! " ${loaded_files[*]} " =~ " ${func_file} " ]]; then
source "$func_file"
loaded_files+=("$func_file")
fi
return 0
fi
fi
done
echo -e "${COLOR_RED}错误: 未找到函数 ${func_name} 的实现${COLOR_RESET}" >&2
return 1
}
# 安全提取函数名
__extract_function_name() {
local line="$1"
# 严格匹配函数定义行
if [[ "$line" =~ ^[[:space:]]*(function[[:space:]]+)?([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*[\(\{] ]]; then
echo "${BASH_REMATCH[2]}"
fi
}
# 动态发现所有可用函数
__discover_shell_functions() {
declare -A FUNC_CATEGORIES
declare -a SHELL_FUNCTIONS=()
for func_file in ~/.config/shell_functions/*.sh; do
[[ "$func_file" == *"function_loader.sh" ]] && continue
if [[ -f "$func_file" ]]; then
local category=$(basename "$func_file" .sh)
local functions_in_file=()
# 逐行读取文件内容
while IFS= read -r line; do
# 跳过注释行和空行
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "${line//[[:space:]]/}" ]] && continue
# 提取函数名
local func_name=$(__extract_function_name "$line")
[[ -n "$func_name" ]] && functions_in_file+=("$func_name")
done < "$func_file"
# 过滤私有函数并去重
local public_functions=()
for func in $(printf "%s\n" "${functions_in_file[@]}" | sort -u); do
[[ "$func" != _* ]] && public_functions+=("$func")
done
# 添加到分类
if (( ${#public_functions[@]} > 0 )); then
FUNC_CATEGORIES["$category"]="${public_functions[*]}"
SHELL_FUNCTIONS+=("${public_functions[@]}")
fi
fi
done
# 显示分类信息(不包含在函数列表中)
echo -e "${COLOR_BLUE}\n可用命令分类:${COLOR_RESET}" >&2
for category in $(printf "%s\n" "${!FUNC_CATEGORIES[@]}" | sort); do
echo -e "${COLOR_YELLOW}${category}:${COLOR_RESET}" >&2
echo "${FUNC_CATEGORIES[$category]}" | tr ' ' '\n' | sed 's/^/ /' >&2
done
# 返回去重后的函数列表
printf "%s\n" "${SHELL_FUNCTIONS[@]}" | sort -u
}
# 安全创建函数桩
__create_function_stub() {
local func="$1"
# 验证函数名是否有效
if [[ "$func" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] && [[ -n "$func" ]]; then
if ! declare -f "$func" >/dev/null 2>&1; then
eval "function ${func}() { __load_shell_function \"${func}\" && \"${func}\" \"\$@\"; }"
fi
else
echo -e "${COLOR_RED}警告: 跳过无效函数名 '${func}'${COLOR_RESET}" >&2
fi
}
# 主初始化过程
function __init_function_loader() {
# 初始化数组
local all_functions=()
# 发现所有函数
mapfile -t all_functions < <(__discover_shell_functions)
# 为每个函数创建桩
for func in "${all_functions[@]}"; do
__create_function_stub "$func"
done
# 显示统计信息
echo -e "\n${COLOR_GREEN}已注册 ${#all_functions[@]} 个延迟加载函数${COLOR_RESET}" >&2
echo -e "${COLOR_CYAN}提示: 首次使用命令时会自动加载相应模块${COLOR_RESET}" >&2
}
# 执行初始化
__init_function_loader
EOF
2. 添加功能函数
以添加 proxy_utils.sh
为例(该函数功能在于能够便捷地开关代理,其中的代理端口、测试地址等根据实际情况改写)
cat > ~/.config/shell_functions/proxy_utils.sh <<'EOF'
#!/bin/bash
# ====================== 代理控制模块 ======================
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 配置区(修改这里适应你的环境)
PROXY_HOST="127.0.0.1"
HTTP_PORT="7897"
SOCKS_PORT="7897"
NO_PROXY="localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,.internal,.local"
TEST_URL="https://www.google.com" # 用于测试代理的网站
DIRECT_TEST_URL="https://www.baidu.com" # 用于测试直连的网站
TIMEOUT=3 # 测试超时时间(秒)
# 网络测试函数
_test_connection() {
local url=$1
local proxy_type=$2
local proxy_addr=$3
echo -e "${CYAN}测试连接: $url ...${NC}"
local start_time=$(date +%s.%N)
if [ -z "$proxy_type" ]; then
# 直连测试
if curl -Is "$url" --connect-timeout $TIMEOUT &>/dev/null; then
local end_time=$(date +%s.%N)
local elapsed=$(printf "%.2f" $(echo "$end_time - $start_time" | bc))
echo -e "${GREEN}✓ 直连成功 (${elapsed}s)${NC}"
return 0
else
echo -e "${RED}✗ 直连失败${NC}"
return 1
fi
else
# 代理测试
case $proxy_type in
http)
if curl -Is "$url" --connect-timeout $TIMEOUT -x "$proxy_addr" &>/dev/null; then
local end_time=$(date +%s.%N)
local elapsed=$(printf "%.2f" $(echo "$end_time - $start_time" | bc))
echo -e "${GREEN}✓ HTTP代理成功 (${elapsed}s)${NC}"
return 0
else
echo -e "${RED}✗ HTTP代理失败${NC}"
return 1
fi
;;
socks5)
if curl -Is "$url" --connect-timeout $TIMEOUT --socks5-hostname "$proxy_addr" &>/dev/null; then
local end_time=$(date +%s.%N)
local elapsed=$(printf "%.2f" $(echo "$end_time - $start_time" | bc))
echo -e "${GREEN}✓ SOCKS5代理成功 (${elapsed}s)${NC}"
return 0
else
echo -e "${RED}✗ SOCKS5代理失败${NC}"
return 1
fi
;;
esac
fi
}
# 状态检测
_proxy_status_check() {
echo -e "${BLUE}====== 代理状态 ======${NC}"
[ -n "$http_proxy" ] && echo -e "HTTP 代理: ${GREEN}已启用${NC} ($http_proxy)" || echo -e "HTTP 代理: ${RED}未启用${NC}"
[ -n "$https_proxy" ] && echo -e "HTTPS 代理: ${GREEN}已启用${NC} ($https_proxy)" || echo -e "HTTPS 代理: ${RED}未启用${NC}"
[ -n "$all_proxy" ] && echo -e "SOCKS 代理: ${GREEN}已启用${NC} ($all_proxy)" || echo -e "SOCKS 代理: ${RED}未启用${NC}"
echo -e "${BLUE}=====================${NC}"
}
# 启用代理
proxy_on() {
export http_proxy="http://${PROXY_HOST}:${HTTP_PORT}"
export https_proxy="http://${PROXY_HOST}:${HTTP_PORT}"
export all_proxy="socks5://${PROXY_HOST}:${SOCKS_PORT}"
export no_proxy="$NO_PROXY"
echo -e "${YELLOW}正在启用代理并测试连接...${NC}"
echo -e "HTTP 代理: http://${PROXY_HOST}:${HTTP_PORT}"
echo -e "SOCKS5 代理: socks5://${PROXY_HOST}:${SOCKS_PORT}"
# 测试HTTP代理
_test_connection "$TEST_URL" "http" "${PROXY_HOST}:${HTTP_PORT}"
# 测试SOCKS5代理
_test_connection "$TEST_URL" "socks5" "${PROXY_HOST}:${SOCKS_PORT}"
_proxy_status_check
}
# 禁用代理
proxy_off() {
unset http_proxy https_proxy all_proxy no_proxy
echo -e "${YELLOW}正在关闭代理并测试直连...${NC}"
# 测试直连
_test_connection "$DIRECT_TEST_URL" ""
_proxy_status_check
}
# 状态切换
proxy_toggle() {
if [ -n "$http_proxy" ]; then
proxy_off
else
proxy_on
fi
}
# 帮助信息
proxy_help() {
echo -e "${YELLOW}代理快捷命令:${NC}"
echo -e "${YELLOW}当前配置:${NC}"
echo -e " 代理地址: ${CYAN}${PROXY_HOST}${NC}"
echo -e " HTTP端口: ${CYAN}${HTTP_PORT}${NC}"
echo -e " SOCKS端口: ${CYAN}${SOCKS_PORT}${NC}"
echo -e " 测试URL: ${CYAN}${TEST_URL}${NC}"
echo -e " 直连测试URL: ${CYAN}${DIRECT_TEST_URL}${NC}"
}
EOF
三. 修改并更新~/.bashrc
文件
1. 修改
cat >> ~/.bashrc <<'EOF'
# ====================== Shell 函数加载 ======================
# 加载函数自动加载器
if [ -f ~/.config/shell_functions/function_loader.sh ]; then
source ~/.config/shell_functions/function_loader.sh
fi
EOF
2. 更新
source ~/.bashrc
四、测试函数
在终端执行以下命令:
# 开启代理
proxy_on
# 关闭代理
proxy_off
# 切换代理状态
proxy_toggle