#!/usr/bin/env bash
#--------------------------------------------------
# Script Name : template.sh
# Description : Standard script template with common functions
# Version : 2.0.0 (2024-05-20)
# Author : Wang Endao <1209233066@qq.com>
# License : MIT
#--------------------------------------------------
### Execution Control ###
set -o errexit # Exit immediately if a command exits with non-zero status
set -o nounset # Treat unset variables as an error
set -o pipefail # Pipeline returns exit status of the last command that failed
shopt -s extglob # Enable extended globbing
# 日志
readonly VERSION="2.0.0"
readonly SCRIPT_NAME=$(basename "${BASH_SOURCE[0]}")
readonly TERM_WIDTH=$(tput cols 2>/dev/null || echo 78)
declare -A LOG_LEVEL_COLORS=(
[DEBUG]="\033[0;36m"
[INFO]="\033[0;32m"
[WARN]="\033[0;33m"
[ERROR]="\033[0;31m"
)
### Initialization ###
declare DEBUG=false
declare LOG_FILE=""
declare LOG_FORMAT="%Y-%m-%d %H:%M:%S"
### Functions ###
# 打印带边框的居中文本
print_bordered() {
local text=$1
local border_char=${2:-#}
local padding=$(( TERM_WIDTH - 4 ))
# 构建边框
local border_line
border_line=$(printf "%${TERM_WIDTH}s" | tr ' ' "$border_char")
# 文本居中处理
local text_length=${#text}
local left_pad=$(( (padding - text_length) / 2 ))
local right_pad=$(( padding - text_length - left_pad ))
printf "%s\n" "$border_line"
printf "%s%*s%s%*s%s\n" "$border_char" $left_pad "" "$text" $right_pad "" "$border_char"
printf "%s\n" "$border_line"
}
# 格式化输出日志
log() {
local level=$1
local message=$2
local timestamp
timestamp=$(date +"$LOG_FORMAT")
local color=${LOG_LEVEL_COLORS[$level]:-\033[0m}
local reset="\033[0m"
# 构建日志内容
local log_content="[${timestamp}] ${color}${level}${reset} ${message}"
# 输出到控制台和日志文件
if [ "$DEBUG" = true ]; then
echo -e "$log_content"
fi
if [ -n "$LOG_FILE" ]; then
echo -e "[${timestamp}] ${level} ${message}" >> "$LOG_FILE"
fi
}
# 智能单位转换
humanize_size() {
local -i bytes=$1
local units=("B" "KB" "MB" "GB" "TB" "PB")
local unit=0
local precision=2
while (( bytes > 1024 && unit < ${#units[@]} - 1 )); do
bytes=$((bytes / 1024))
((unit++))
done
printf "%0.*f %s" $precision "$(echo "scale=3; $bytes / 1" | bc)" "${units[unit]}"
}
### Argument Parsing ###
show_help() {
print_bordered "Script Help"
echo "Usage: ${SCRIPT_NAME} [options]"
echo
echo "Options:"
echo " -d Enable debug mode"
echo " -f FORMAT Set log format (default: \"%Y-%m-%d %H:%M:%S\")"
echo " -l FILE Specify log file path"
echo " -h Show this help message"
exit 0
}
parse_arguments() {
while getopts ":df:l:h" opt; do
case $opt in
d) DEBUG=true ;;
f) LOG_FORMAT="$OPTARG" ;;
l) LOG_FILE="$OPTARG"
mkdir -p "$(dirname "$LOG_FILE")" ;;
h) show_help ;;
\?) log ERROR "Invalid option: -$OPTARG" >&2; exit 1 ;;
:) log ERROR "Option -$OPTARG requires an argument." >&2; exit 1 ;;
esac
done
shift $((OPTIND-1))
}
# 主函数
main() {
# 设置本地化
export LC_ALL=C 2>/dev/null || log WARN "Failed to set LC_ALL=C locale"
# 参数解析
parse_arguments "$@"
# 显示头信息
print_bordered "Script: ${SCRIPT_NAME} (Version: ${VERSION})"
# 示例使用
log INFO "Script initialized"
log DEBUG "Terminal width: ${TERM_WIDTH}"
# 示例单位转换
sample_size=$(( 5*1024*1024 + 512*1024 )) # 5.5GB
converted_size=$(humanize_size $sample_size)
log INFO "Converted size: ${converted_size}"
}
### Entry Point ###
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi