文件包含是Shell脚本编程中实现代码重用和模块化的重要技术。通过文件包含,我们可以将常用的函数、配置和代码片段分离到独立的文件中,提高代码的可维护性和重用性。
在当前Shell环境中执行指定文件中的命令。
.操作符是source命令的简写形式。
将相关函数组织到库文件中,实现代码模块化。
将配置参数分离到单独文件中,便于管理和修改。
在包含文件前进行存在性检查和权限验证。
将大型脚本拆分为多个小模块,提高可维护性。
文件包含是Shell脚本实现模块化编程的基础。通过合理的文件包含,我们可以避免代码重复,提高开发效率,使脚本更加易于维护和扩展。合理的模块化设计是编写高质量Shell脚本的关键。
学习使用source命令和点操作符进行文件包含。
| 方法 | 语法 | 说明 | 示例 |
|---|---|---|---|
source |
source filename |
在当前Shell环境中执行文件 | source config.sh |
.(点) |
. filename |
source的简写形式 |
. functions.sh |
相对路径 |
source ./lib/utils.sh |
使用相对路径包含文件 | source ../config.sh |
绝对路径 |
source /path/to/file |
使用绝对路径包含文件 | source /opt/app/config.sh |
条件包含 |
[ -f file ] && source file |
检查文件存在性后再包含 | [ -f config.sh ] && source config.sh |
#!/bin/bash
# 应用配置
APP_NAME="MyApplication"
APP_VERSION="1.0.0"
LOG_LEVEL="INFO"
MAX_RETRY=3
# 数据库配置
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="myapp"
DB_USER="app_user"
# 路径配置
LOG_DIR="/var/log/myapp"
DATA_DIR="/var/lib/myapp"
TEMP_DIR="/tmp/myapp"
# 颜色配置(用于输出)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
#!/bin/bash
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
# 检查命令是否存在
check_command() {
if ! command -v "$1" &> /dev/null; then
log_error "命令不存在: $1"
return 1
fi
return 0
}
# 检查文件是否存在
check_file() {
if [ ! -f "$1" ]; then
log_error "文件不存在: $1"
return 1
fi
return 0
}
# 创建目录(如果不存在)
ensure_dir() {
if [ ! -d "$1" ]; then
mkdir -p "$1"
log_info "创建目录: $1"
fi
}
# 安全删除文件
safe_remove() {
if [ -f "$1" ]; then
rm -f "$1"
log_info "删除文件: $1"
fi
}
#!/bin/bash
# 主脚本 - 文件包含示例
echo "=== Shell文件包含演示 ==="
# 方法1: 使用source命令包含配置文件
echo "1. 包含配置文件..."
source config.sh
# 方法2: 使用点操作符包含工具函数
echo "2. 包含工具函数..."
. utils.sh
# 使用包含的配置和函数
echo "3. 使用包含的内容..."
log_info "应用程序: $APP_NAME v$APP_VERSION"
log_info "数据库: $DB_HOST:$DB_PORT/$DB_NAME"
# 检查必要命令
echo "4. 检查系统依赖..."
check_command "curl" || exit 1
check_command "wget" || exit 1
# 创建必要目录
echo "5. 初始化目录结构..."
ensure_dir "$LOG_DIR"
ensure_dir "$DATA_DIR"
ensure_dir "$TEMP_DIR"
# 演示函数使用
echo "6. 演示工具函数..."
log_success "所有检查通过!"
log_warn "这是一个警告信息"
log_error "这是一个错误信息"
# 条件包含示例
echo "7. 条件包含演示..."
if [ -f "optional.sh" ]; then
source optional.sh
log_info "可选模块已加载"
else
log_warn "可选模块不存在,跳过"
fi
echo "=== 脚本执行完成 ==="
学习如何创建和使用函数库来实现代码重用。
#!/bin/bash
# 字符串处理函数库
# 转换为大写
string_upper() {
echo "$1" | tr '[:lower:]' '[:upper:]'
}
# 转换为小写
string_lower() {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
# 字符串长度
string_length() {
echo ${#1}
}
# 去除首尾空格
string_trim() {
local str="$1"
str="${str#"${str%%[![:space:]]*}"}" # 去除前导空格
str="${str%"${str##*[![:space:]]}"}" # 去除尾部空格
echo "$str"
}
# 字符串替换
string_replace() {
local str="$1"
local search="$2"
local replace="$3"
echo "${str//$search/$replace}"
}
# 检查是否包含子字符串
string_contains() {
[[ "$1" == *"$2"* ]]
}
# 检查是否以指定字符串开头
string_starts_with() {
[[ "$1" == "$2"* ]]
}
# 检查是否以指定字符串结尾
string_ends_with() {
[[ "$1" == *"$2" ]]
}
# 生成随机字符串
string_random() {
local length=${1:-8}
tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c "$length"
}
# 字符串分割为数组
string_split() {
local str="$1"
local delimiter="$2"
IFS="$delimiter" read -ra arr <<< "$str"
printf '%s\n' "${arr[@]}"
}
#!/bin/bash
# 文件操作函数库
# 获取文件大小(字节)
file_size() {
stat -f%z "$1" 2>/dev/null || stat -c%s "$1" 2>/dev/null
}
# 获取文件修改时间
file_mtime() {
stat -f%m "$1" 2>/dev/null || stat -c%Y "$1" 2>/dev/null
}
# 获取文件扩展名
file_extension() {
local filename=$(basename "$1")
echo "${filename##*.}"
}
# 获取文件名(不含扩展名)
file_basename() {
local filename=$(basename "$1")
echo "${filename%.*}"
}
# 备份文件
file_backup() {
local file="$1"
local backup="${file}.backup.$(date +%Y%m%d_%H%M%S)"
if cp "$file" "$backup"; then
echo "$backup"
return 0
else
return 1
fi
}
# 安全写入文件(先备份原文件)
file_safe_write() {
local file="$1"
local content="$2"
# 如果文件存在,先备份
if [ -f "$file" ]; then
file_backup "$file" > /dev/null
fi
# 写入新内容
echo "$content" > "$file"
}
# 在文件中查找并替换
file_replace() {
local file="$1"
local search="$2"
local replace="$3"
if sed -i.tmp "s/$search/$replace/g" "$file" 2>/dev/null; then
rm -f "${file}.tmp"
return 0
else
return 1
fi
}
# 检查文件是否可读
file_is_readable() {
[ -r "$1" ]
}
# 检查文件是否可写
file_is_writable() {
[ -w "$1" ]
}
# 获取文件行数
file_line_count() {
wc -l < "$1" 2>/dev/null || echo "0"
}
#!/bin/bash
# 主脚本 - 函数库使用示例
# 设置库文件路径
LIB_DIR="$(dirname "$0")/lib"
# 包含所有库文件
echo "加载函数库..."
for lib_file in "$LIB_DIR"/*.sh; do
if [ -f "$lib_file" ]; then
echo " 加载: $(basename "$lib_file")"
source "$lib_file"
fi
done
echo -e "\n=== 字符串函数演示 ==="
# 字符串函数测试
test_str=" Hello, World! "
echo "原始字符串: '$test_str'"
echo "大写: '$(string_upper "$test_str")'"
echo "小写: '$(string_lower "$test_str")'"
echo "去除空格: '$(string_trim "$test_str")'"
echo "长度: $(string_length "$test_str")"
echo "替换: '$(string_replace "$test_str" "World" "Shell")'"
echo "包含 'Hello': $(string_contains "$test_str" "Hello" && echo "是" || echo "否")"
echo "随机字符串: $(string_random 10)"
echo -e "\n=== 文件函数演示 ==="
# 创建测试文件
TEST_FILE="test_file.txt"
echo "Line 1" > "$TEST_FILE"
echo "Line 2" >> "$TEST_FILE"
echo "Line 3" >> "$TEST_FILE"
echo "测试文件: $TEST_FILE"
echo "文件大小: $(file_size "$TEST_FILE") 字节"
echo "文件行数: $(file_line_count "$TEST_FILE")"
echo "文件扩展名: $(file_extension "$TEST_FILE")"
# 文件备份演示
backup_file=$(file_backup "$TEST_FILE")
echo "备份文件: $backup_file"
# 文件替换演示
file_replace "$TEST_FILE" "Line" "Row"
echo "替换后的内容:"
cat "$TEST_FILE"
echo -e "\n=== 综合示例 ==="
# 处理文件名
filename="/path/to/example.tar.gz"
echo "文件名: $filename"
echo "基础名: $(file_basename "$filename")"
echo "扩展名: $(file_extension "$filename")"
# 清理测试文件
rm -f "$TEST_FILE" "$backup_file"
echo -e "\n=== 库函数验证完成 ==="
学习如何使用文件包含来管理应用程序配置。
#!/bin/bash
# 应用程序配置文件
# 应用基本信息
APP_NAME="MyApplication"
APP_VERSION="2.1.0"
APP_DESCRIPTION="一个强大的Shell应用程序"
# 日志配置
LOG_LEVEL="INFO"
LOG_FILE="/var/log/myapp/app.log"
LOG_MAX_SIZE="10M"
LOG_BACKUP_COUNT=5
# 数据库配置
DB_DRIVER="postgresql"
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="production_db"
DB_USER="app_user"
DB_PASSWORD="secure_password"
# API配置
API_BASE_URL="https://api.example.com"
API_TIMEOUT=30
API_RETRY_COUNT=3
# 功能开关
FEATURE_AUTH_ENABLED=true
FEATURE_CACHE_ENABLED=true
FEATURE_LOGGING_ENABLED=true
# 路径配置
UPLOAD_DIR="/var/www/uploads"
TEMP_DIR="/tmp/myapp"
BACKUP_DIR="/var/backups/myapp"
#!/bin/bash
# 数据库配置文件
# 连接池配置
DB_POOL_MIN=2
DB_POOL_MAX=20
DB_CONNECTION_TIMEOUT=30
DB_QUERY_TIMEOUT=60
# 性能配置
DB_CACHE_SIZE="256MB"
DB_WAL_BUFFER_SIZE="16MB"
# 备份配置
DB_BACKUP_ENABLED=true
DB_BACKUP_SCHEDULE="0 2 * * *" # 每天凌晨2点
DB_BACKUP_RETENTION=30 # 保留30天
# 监控配置
DB_MONITOR_ENABLED=true
DB_MONITOR_INTERVAL=60 # 60秒
DB_SLOW_QUERY_THRESHOLD=1000 # 1秒
#!/bin/bash
# 配置文件加载器
# 配置目录
CONFIG_DIR="$(dirname "$0")/config"
# 默认配置值
declare -A DEFAULT_CONFIG=(
["LOG_LEVEL"]="INFO"
["API_TIMEOUT"]=30
["DB_POOL_MIN"]=2
["FEATURE_AUTH_ENABLED"]=true
)
# 加载配置文件
load_config() {
local config_file="$1"
if [ ! -f "$config_file" ]; then
echo "错误: 配置文件不存在: $config_file" >&2
return 1
fi
# 检查文件权限(不应该全局可写)
if [ "$(stat -c %a "$config_file" 2>/dev/null || stat -f %A "$config_file")" -eq 666 ] ||
[ "$(stat -c %a "$config_file" 2>/dev/null || stat -f %A "$config_file")" -eq 777 ]; then
echo "警告: 配置文件权限过于宽松: $config_file" >&2
fi
# 加载配置文件
source "$config_file"
echo "加载配置文件: $config_file"
}
# 加载所有配置文件
load_all_configs() {
echo "开始加载配置文件..."
# 加载主配置
load_config "$CONFIG_DIR/app.conf"
# 加载数据库配置
if [ -f "$CONFIG_DIR/database.conf" ]; then
load_config "$CONFIG_DIR/database.conf"
fi
# 加载环境特定配置
local env_config="$CONFIG_DIR/app.${APP_ENV:-production}.conf"
if [ -f "$env_config" ]; then
load_config "$env_config"
fi
# 加载本地开发配置(如果存在)
if [ -f "$CONFIG_DIR/app.local.conf" ]; then
load_config "$CONFIG_DIR/app.local.conf"
fi
echo "配置文件加载完成"
}
# 验证配置
validate_config() {
local errors=0
echo "验证配置..."
# 检查必要配置项
local required_vars=("APP_NAME" "DB_HOST" "DB_NAME")
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
echo "错误: 缺少必要配置项: $var" >&2
((errors++))
fi
done
# 验证数值范围
if [ "$API_TIMEOUT" -lt 1 ] || [ "$API_TIMEOUT" -gt 300 ]; then
echo "错误: API_TIMEOUT 必须在 1-300 之间" >&2
((errors++))
fi
# 验证布尔值
local bool_vars=("FEATURE_AUTH_ENABLED" "FEATURE_CACHE_ENABLED")
for var in "${bool_vars[@]}"; do
if [ "${!var}" != "true" ] && [ "${!var}" != "false" ]; then
echo "错误: $var 必须是 'true' 或 'false'" >&2
((errors++))
fi
done
return $errors
}
# 显示当前配置
show_config() {
echo "=== 当前配置 ==="
# 显示应用配置
echo "应用信息:"
echo " 名称: $APP_NAME"
echo " 版本: $APP_VERSION"
echo " 日志级别: $LOG_LEVEL"
# 显示数据库配置(隐藏密码)
echo "数据库:"
echo " 主机: $DB_HOST"
echo " 端口: $DB_PORT"
echo " 数据库: $DB_NAME"
echo " 用户: $DB_USER"
echo " 密码: ******"
# 显示功能开关
echo "功能开关:"
echo " 认证: $FEATURE_AUTH_ENABLED"
echo " 缓存: $FEATURE_CACHE_ENABLED"
echo " 日志: $FEATURE_LOGGING_ENABLED"
}
# 导出配置为环境变量
export_config() {
export APP_NAME APP_VERSION LOG_LEVEL
export DB_HOST DB_PORT DB_NAME DB_USER DB_PASSWORD
export API_BASE_URL API_TIMEOUT
export FEATURE_AUTH_ENABLED FEATURE_CACHE_ENABLED FEATURE_LOGGING_ENABLED
echo "配置已导出为环境变量"
}
# 主函数
main() {
# 设置环境(开发/测试/生产)
export APP_ENV="${1:-production}"
echo "运行环境: $APP_ENV"
# 加载配置
if ! load_all_configs; then
echo "配置加载失败" >&2
return 1
fi
# 验证配置
if ! validate_config; then
echo "配置验证失败" >&2
return 1
fi
# 显示配置
show_config
# 导出配置
export_config
echo "配置管理完成"
}
# 如果直接执行此脚本,则运行主函数
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
学习文件包含的高级用法和最佳实践。
#!/bin/bash
# 高级文件包含技巧示例
echo "=== 动态文件包含 ==="
# 根据条件动态包含文件
OS_TYPE=$(uname -s)
case $OS_TYPE in
"Linux")
source "lib/linux.sh"
echo "已加载 Linux 特定库"
;;
"Darwin")
source "lib/macos.sh"
echo "已加载 macOS 特定库"
;;
"CYGWIN"*|"MINGW"*|"MSYS"*)
source "lib/windows.sh"
echo "已加载 Windows 特定库"
;;
*)
echo "未知操作系统: $OS_TYPE"
;;
esac
echo -e "\n=== 安全的文件包含 ==="
# 安全的文件包含函数
safe_source() {
local file="$1"
# 检查文件是否存在
if [ ! -f "$file" ]; then
echo "错误: 文件不存在: $file" >&2
return 1
fi
# 检查文件权限(不应该全局可写)
local permissions=$(stat -c %a "$file" 2>/dev/null || stat -f %A "$file")
if [ "$permissions" -eq 666 ] || [ "$permissions" -eq 777 ]; then
echo "错误: 文件权限不安全: $file" >&2
return 1
fi
# 检查文件大小(避免包含过大的文件)
local file_size=$(stat -c %s "$file" 2>/dev/null || stat -f %z "$file")
if [ "$file_size" -gt 1048576 ]; then # 1MB
echo "错误: 文件过大: $file" >&2
return 1
fi
# 包含文件
source "$file"
echo "安全加载: $file"
return 0
}
# 使用安全包含
safe_source "config.sh"
echo -e "\n=== 递归文件包含 ==="
# 自动加载目录下的所有库文件
load_libraries() {
local lib_dir="$1"
if [ ! -d "$lib_dir" ]; then
echo "错误: 库目录不存在: $lib_dir" >&2
return 1
fi
# 查找所有 .sh 文件(除了以 _ 开头的)
while IFS= read -r -d '' lib_file; do
local basename=$(basename "$lib_file")
# 跳过以 _ 开头的文件(如 _template.sh)
if [[ "$basename" != _* ]]; then
safe_source "$lib_file"
fi
done < <(find "$lib_dir" -name "*.sh" -type f -print0)
echo "已加载 $lib_dir 目录下的所有库文件"
}
# 创建示例库目录结构
mkdir -p libs/{string,file,network}
echo "# 字符串库" > libs/string/strings.sh
echo "# 文件库" > libs/file/files.sh
echo "# 网络库" > libs/network/network.sh
echo "# 模板文件" > libs/string/_template.sh
# 加载所有库
load_libraries "libs"
echo -e "\n=== 条件函数定义 ==="
# 避免函数重复定义
if ! declare -f "my_function" > /dev/null; then
my_function() {
echo "这是 my_function"
}
echo "函数 my_function 已定义"
else
echo "函数 my_function 已存在,跳过定义"
fi
echo -e "\n=== 命名空间模拟 ==="
# 使用前缀模拟命名空间
namespace_example() {
local ns="$1"
# 定义命名空间函数
eval "${ns}_hello() { echo \"Hello from $ns\"; }"
eval "${ns}_config() { echo \"Config for $ns: \$1\"; }"
}
# 创建不同命名空间的函数
namespace_example "app"
namespace_example "db"
namespace_example "api"
# 使用命名空间函数
app_hello
db_hello
app_config "database"
db_config "connection"
echo -e "\n=== 配置覆盖机制 ==="
# 基础配置
load_base_config() {
DEFAULT_TIMEOUT=30
DEFAULT_RETRIES=3
LOG_LEVEL="INFO"
}
# 用户配置(如果存在)
load_user_config() {
local user_config="$HOME/.myapp/config.sh"
if [ -f "$user_config" ]; then
source "$user_config"
echo "已加载用户配置: $user_config"
fi
}
# 环境特定配置
load_env_config() {
local env="${APP_ENV:-production}"
local env_config="config/$env.sh"
if [ -f "$env_config" ]; then
source "$env_config"
echo "已加载环境配置: $env_config"
fi
}
# 加载配置(后面的配置会覆盖前面的)
load_base_config
load_user_config
load_env_config
echo "最终配置: TIMEOUT=$DEFAULT_TIMEOUT, RETRIES=$DEFAULT_RETRIES, LOG_LEVEL=$LOG_LEVEL"
echo -e "\n=== 错误处理和恢复 ==="
# 带错误恢复的文件包含
source_with_fallback() {
local primary_file="$1"
local fallback_file="$2"
if safe_source "$primary_file"; then
echo "使用主文件: $primary_file"
return 0
elif [ -n "$fallback_file" ] && safe_source "$fallback_file"; then
echo "使用备用文件: $fallback_file"
return 0
else
echo "错误: 无法加载任何配置文件" >&2
return 1
fi
}
# 尝试加载配置,有备用方案
source_with_fallback "production.conf" "default.conf"
# 清理临时文件
rm -rf libs
echo -e "\n=== 高级技巧演示完成 ==="
set -e在包含失败时退出脚本通过实际项目示例展示Shell文件包含的综合应用。
使用文件包含技术构建一个完整的Shell应用框架。
#!/bin/bash
# 应用核心库
# 应用基本信息
APP_NAME="MyApp Framework"
APP_VERSION="1.0.0"
APP_AUTHOR="Dev Team"
# 应用根目录
APP_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# 初始化应用
app_init() {
echo "初始化 $APP_NAME v$APP_VERSION"
# 加载配置
load_config
# 加载库文件
load_libraries
# 设置信号处理
setup_signal_handlers
# 验证环境
validate_environment
}
# 加载配置
load_config() {
local config_dir="$APP_ROOT/config"
# 加载主配置
if [ -f "$config_dir/app.conf" ]; then
source "$config_dir/app.conf"
fi
# 加载数据库配置
if [ -f "$config_dir/database.conf" ]; then
source "$config_dir/database.conf"
fi
# 加载日志配置
if [ -f "$config_dir/logging.conf" ]; then
source "$config_dir/logging.conf"
fi
# 设置默认值
: ${LOG_LEVEL:="INFO"}
: ${LOG_FILE:="$APP_ROOT/logs/app.log"}
: ${DB_HOST:="localhost"}
: ${DB_PORT:="3306"}
}
# 加载库文件
load_libraries() {
local lib_dir="$APP_ROOT/lib"
for lib_file in "$lib_dir"/*.sh; do
if [ -f "$lib_file" ] && [ "$(basename "$lib_file")" != "core.sh" ]; then
source "$lib_file"
fi
done
}
# 设置信号处理
setup_signal_handlers() {
trap 'cleanup' EXIT INT TERM
}
# 清理函数
cleanup() {
log_info "应用正在关闭..."
# 执行清理操作
log_info "清理完成"
}
# 验证环境
validate_environment() {
log_info "验证运行环境..."
# 检查必要命令
local required_commands=("bash" "curl" "awk" "sed")
for cmd in "${required_commands[@]}"; do
if ! command -v "$cmd" > /dev/null; then
log_error "缺少必要命令: $cmd"
return 1
fi
done
# 检查目录权限
local required_dirs=("$APP_ROOT/logs" "$APP_ROOT/tmp")
for dir in "${required_dirs[@]}"; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
fi
if [ ! -w "$dir" ]; then
log_error "目录不可写: $dir"
return 1
fi
done
log_success "环境验证通过"
return 0
}
# 运行命令
run_command() {
local command_name="$1"
shift
local command_file="$APP_ROOT/commands/${command_name}.sh"
if [ ! -f "$command_file" ]; then
log_error "命令不存在: $command_name"
return 1
fi
# 在子shell中运行命令,避免污染当前环境
(
source "$command_file"
if declare -f "command_$command_name" > /dev/null; then
"command_$command_name" "$@"
else
log_error "命令函数未定义: command_$command_name"
return 1
fi
)
}
#!/bin/bash
# 初始化命令
command_init() {
echo "执行初始化操作..."
# 创建必要目录
local directories=(
"$APP_ROOT/logs"
"$APP_ROOT/tmp"
"$APP_ROOT/data"
"$APP_ROOT/backups"
)
for dir in "${directories[@]}"; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
log_info "创建目录: $dir"
fi
done
# 创建配置文件(如果不存在)
init_config_files
# 初始化数据库
init_database
log_success "初始化完成"
}
# 初始化配置文件
init_config_files() {
local config_dir="$APP_ROOT/config"
# 应用配置
if [ ! -f "$config_dir/app.conf" ]; then
cat > "$config_dir/app.conf" << 'EOF'
#!/bin/bash
# 应用配置
APP_NAME="MyApp"
APP_ENV="development"
LOG_LEVEL="INFO"
# 功能开关
FEATURE_API=true
FEATURE_JOBS=true
FEATURE_REPORTS=true
EOF
log_info "创建应用配置文件"
fi
# 数据库配置
if [ ! -f "$config_dir/database.conf" ]; then
cat > "$config_dir/database.conf" << 'EOF'
#!/bin/bash
# 数据库配置
DB_DRIVER="mysql"
DB_HOST="localhost"
DB_PORT="3306"
DB_NAME="myapp"
DB_USER="app_user"
DB_PASSWORD="password"
# 连接池
DB_POOL_MIN=2
DB_POOL_MAX=20
EOF
log_info "创建数据库配置文件"
fi
}
# 初始化数据库
init_database() {
log_info "初始化数据库..."
# 这里应该是实际的数据库初始化逻辑
# 例如:创建数据库、表、初始数据等
# 模拟数据库初始化
if [ "$DB_DRIVER" = "mysql" ]; then
log_info "初始化 MySQL 数据库"
# mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASSWORD" -e "CREATE DATABASE IF NOT EXISTS $DB_NAME;"
elif [ "$DB_DRIVER" = "postgresql" ]; then
log_info "初始化 PostgreSQL 数据库"
# psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;"
fi
log_success "数据库初始化完成"
}
#!/bin/bash
# MyApp 主程序
# 应用根目录
APP_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# 加载核心库
source "$APP_ROOT/lib/core.sh"
# 显示帮助信息
show_help() {
cat << EOF
MyApp - Shell 应用框架
用法: $0 [命令] [选项]
命令:
init 初始化应用
deploy 部署应用
backup 备份数据
status 查看状态
help 显示此帮助信息
选项:
-h, --help 显示帮助
-v, --version 显示版本
示例:
$0 init
$0 deploy --environment=production
$0 status
EOF
}
# 显示版本
show_version() {
echo "$APP_NAME v$APP_VERSION"
}
# 主函数
main() {
local command="${1:-help}"
case "$command" in
-h|--help|help)
show_help
;;
-v|--version|version)
show_version
;;
init|deploy|backup|status)
# 初始化应用
app_init || exit 1
# 执行命令
run_command "$command" "${@:2}"
;;
*)
echo "错误: 未知命令 '$command'" >&2
echo "使用 '$0 help' 查看可用命令" >&2
exit 1
;;
esac
}
# 运行主函数
main "$@"
使用 set -x 开启调试模式查看文件包含过程。使用 declare -f 查看已定义的函数。在库文件中使用 return 而不是 exit 避免意外退出主脚本。