feat: 更新通用脚本库存储路径

This commit is contained in:
2023-08-14 15:20:53 +08:00
parent 64bec1b12c
commit b7d97ffd41
11 changed files with 613 additions and 240 deletions
@@ -1,29 +1,29 @@
#!/bin/bash
# Ver: 1.3 by Endial Fang (endial@126.com)
# Ver: 1.5 by Endial Fang (endial@126.com)
#
# 通用函数库
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
. /colovu/lib/liblog.sh # 日志输出函数库
# 函数列表
# 打印包含包含Logo的欢迎信息
print_welcome_info() {
[[ -n "${APP_NAME}" ]] && github_url="/docker-${APP_NAME}"
[[ -n "${APP_NAME:-}" ]] && github_repo="https://github.com/colovu/docker-${APP_NAME}"
LOG_I ' ____ _ '
LOG_I ' / ___|___ | | _____ ___ _ '
LOG_I '| | / _ \| |/ _ \ \ / / | | | '"Docker : ${BOLD}${APP_NAME:-undefined}${RESET}"
LOG_I '| |__| (_) | | (_) \ V /| |_| | '"Version: ${BOLD}${APP_VERSION:-0.0}${RESET}"
LOG_I ' \____\___/|_|\___/ \_/ \__,_| '"PowerBy: ${BOLD}Endial@126.com${RESET}"
LOG_D " Project Repo: https://github.com/colovu/${github_url:-}"
LOG_I " ____ _ "
LOG_I " / ___|___ | | _____ ___ _ "
LOG_I "| | / _ \| |/ _ \ \ / / | | | Docker : ${BOLD}${APP_NAME:-undefined}${RESET}"
LOG_I "| |__| (_) | | (_) \ V /| |_| | Version: ${BOLD}${APP_VER:-0.0}${RESET}"
LOG_I " \____\___/|_|\___/ \_/ \__,_| PowerBy: ${BOLD}Endial@126.com${RESET}"
LOG_D " Project Repo: ${github_repo:-}"
LOG_I ""
}
# 根据需要打印欢迎信息
print_image_welcome() {
if [[ "$(id -u)" = "0" ]]; then
if [[ ! "$(id -u)" = "0" ]]; then
print_welcome_info
fi
}
@@ -35,7 +35,7 @@ print_command_help() {
local arg
for arg; do
case "$arg" in
-'?'|--help|-V|--version|-version)
-'?'|-H|-h|--help|-help|-V|-v|--version|-version)
exec "$@"
exit
;;
@@ -100,17 +100,6 @@ process_init_files() {
done
}
# 检测当前是否为 root 用户
is_root() {
if [[ "$(id -u)" = "0" ]]; then
LOG_D "Run as root."
true
else
LOG_D "Run as non-root: $(id -u)"
false
fi
}
# 检测当前脚本是被直接执行的,还是从其他脚本中使用 "source" 调用的
is_sourced() {
[ "${#FUNCNAME[@]}" -ge 2 ] \
@@ -1,10 +1,10 @@
#!/bin/bash
# Ver: 1.0 by Endial Fang (endial@126.com)
# Ver: 1.1 by Endial Fang (endial@126.com)
#
# 文件操作函数库
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
. /colovu/lib/liblog.sh # 日志输出函数库
# 函数列表
@@ -76,3 +76,18 @@ remove_in_file() {
fi
echo "$result" > "$filename"
}
# 在符合条件的行后增加文本
# 参数:
# $1 - 文件名
# $2 - 正则表达式
# $3 - 待增加的文本
append_in_file() {
local file="${1:?missing file}"
local match_regex="${2:?missing pattern}"
local value="${3:?missing value}"
# We read the file in reverse, replace the first match (0,/pattern/s) and then reverse the results again
result="$(tac "$file" | sed -E "0,/($match_regex)/s||${value}\n\1|" | tac)"
echo "$result" > "$file"
}
@@ -1,13 +1,24 @@
#!/bin/bash
# Ver: 1.1 by Endial Fang (endial@126.com)
# Ver: 1.2 by Endial Fang (endial@126.com)
#
# 文件管理函数库
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
. /colovu/lib/liblog.sh # 日志输出函数库
# 函数列表
# 确保指定的 文件/路径 所属权为指定的 用户/组
# 参数:
# $1 - 文件路径
# $2 - 用户
ensure_owned_by() {
local path="${1:?path is missing}"
local owner="${2:?owner is missing}"
chown "$owner":"$owner" "$path"
}
# 检测目录是否存在,如果不存在则创建,同时修改为指定的用户
# 参数:
# $1 - 目录路径
@@ -18,7 +29,7 @@ ensure_dir_exists() {
mkdir -p "${dir}"
if [[ -n $owner ]]; then
chown "$owner":"$owner" "$dir"
ensure_owned_by "$dir" "$owner"
fi
}
@@ -35,6 +46,23 @@ is_dir_empty() {
fi
}
# 检测指定的路径当前用户是否可写入
# 参数:
# $1 - 文件或路径
# 返回值:
# true / false
is_writable() {
local file="${1:?missing file}"
local dir
dir="$(dirname "$file")"
if [[ ( -f "$file" && -w "$file" ) || ( ! -f "$file" && -d "$dir" && -w "$dir" ) ]]; then
true
else
false
fi
}
# 循环设置目录中子目录及文件权限
# 参数:
# $1 - paths (as a string).
@@ -38,8 +38,7 @@ stderr_print() {
# 输出实际日志信息
# 参数:
# $1 - 日志类型
# $2 - 日志信息
# $1 - 日志信息
LOG() {
local -r bool="${ENV_DEBUG:-false}"
shopt -s nocasematch
@@ -48,13 +47,12 @@ LOG() {
else
debugInfo="${CYAN}${APP_NAME:-}"
fi
stderr_print "${debugInfo} ${MAGENTA}$(date "+%T")${RESET} ${*}"
stderr_print "${debugInfo} ${MAGENTA}$(date "+%F %T.%3N")${RESET} ${*}"
}
# 输出调试类日志信息,尽量少使用
# 参数:
# $1 - 日志类型
# $2 - 日志信息
# $1 - 日志信息
LOG_D() {
local -r bool="${ENV_DEBUG:-false}"
shopt -s nocasematch
@@ -65,24 +63,21 @@ LOG_D() {
# 输出提示信息类日志信息
# 参数:
# $1 - 日志类型
# $2 - 日志信息
# $1 - 日志信息
LOG_I() {
LOG "${GREEN}INF${RESET}: ${*}"
}
# 输出警告类日志信息至sterr
# 参数:
# $1 - 日志类型
# $2 - 日志信息
# $1 - 日志信息
LOG_W() {
LOG "${YELLOW}WRN${RESET}: ${*}"
}
# 输出错误类日志信息至sterr,并退出脚本
# 参数:
# $1 - 日志类型
# $2 - 日志信息
# $1 - 日志信息
LOG_E() {
LOG "${RED}ERR${RESET}: ${*}"
}
@@ -4,13 +4,16 @@
# 文件管理函数库
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
. /colovu/lib/liblog.sh # 日志输出函数库
# 函数列表
# 域名解析
# 参数:
# $1 - 需要解析的主机名
# $2 - IP 地址版本 v4/v6, 为空时解析所有版本
# 返回值:
# IP地址
dns_lookup() {
local host="${1:?host is missing}"
getent ahosts "$host" | awk '/STREAM/ {print $1 }'
@@ -21,6 +24,8 @@ dns_lookup() {
# $1 - 主机名
# $2 - 尝试次数
# $3 - 重试间隔时间(秒)
# 返回值:
# IP地址
wait_for_dns_lookup() {
local hostname="${1:?hostname is missing}"
local retries="${2:-5}"
@@ -38,6 +43,8 @@ wait_for_dns_lookup() {
}
# 获取当前主机 IP
# 返回值:
# IP地址
get_machine_ip() {
local -a ip_addresses
local hostname
@@ -52,11 +59,11 @@ get_machine_ip() {
echo "${ip_addresses[0]}"
}
# Check if the provided argument is a resolved hostname
# 检测指定的主机名是否可解析
# 参数:
# $1 - 待检测的主机名
# 返回值:
# 布尔值
# true / false
is_hostname_resolved() {
local -r host="${1:?missing value}"
if [[ -n "$(dns_lookup "$host")" ]]; then
+302
View File
@@ -0,0 +1,302 @@
#!/bin/bash
# Ver: 1.3 by Endial Fang (endial@126.com)
#
# 操作系统控制函数库
# 加载依赖项
. /colovu/lib/libfs.sh # 文件系统函数库
# 函数列表
# 检测指定用户账户是否存在
# 参数:
# $1 - 用户账户
# 返回值:
# 0 / 1
is_user_exists() {
local user="${1:?user is missing}"
id "$user" >/dev/null 2>&1
}
# 检测指定用户分组是否存在
# 参数:
# $1 - 用户组
# 返回值:
# 0 / 1
is_group_exists() {
local group="${1:?group is missing}"
getent group "$group" >/dev/null 2>&1
}
# 检测当前是否为 root 用户
# 返回值:
# true / false
is_root() {
if [[ "$(id -u)" = "0" ]]; then
LOG_D "Run as root."
true
else
LOG_D "Run as non-root: $(id -u)"
false
fi
}
# 确保指定用户组在系统中存在
# 参数:
# $1 - 用户组
# 标志位:
# -s|--system - 创建系统用户 (uid <= 999)
ensure_group_exists() {
local group="${1:?group is missing}"
local is_system_user=false
# 检测标志位
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-s|--system)
is_system_user=true
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
if ! is_group_exists "$group"; then
local -a args=("$group")
$is_system_user && args+=("--system")
groupadd "${args[@]}" >/dev/null 2>&1
fi
}
# 确保指定用户在系统中存在
# 参数:
# $1 - 用户
# 标志位:
# -g|--group - 用户组
# -h|--home - 用户家目录
# -s|--system - 创建系统用户 (uid <= 999)
ensure_user_exists() {
local user="${1:?user is missing}"
local group=""
local home=""
local is_system_user=false
# Validate arguments
shift 1
while [ "$#" -gt 0 ]; do
case "$1" in
-g|--group)
shift
group="${1:?missing group}"
;;
-h|--home)
shift
home="${1:?missing home directory}"
;;
-s|--system)
is_system_user=true
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
if ! is_user_exists "$user"; then
local -a user_args=("-N" "$user")
$is_system_user && user_args+=("--system")
useradd "${user_args[@]}" >/dev/null 2>&1
fi
if [[ -n "$group" ]]; then
local -a group_args=("$group")
$is_system_user && group_args+=("--system")
ensure_group_exists "${group_args[@]}"
usermod -g "$group" "$user" >/dev/null 2>&1
fi
if [[ -n "$home" ]]; then
mkdir -p "$home"
usermod -d "$home" "$user" >/dev/null 2>&1
configure_permissions_ownership "$home" -d "775" -f "664" -u "$user" -g "$group"
fi
}
# 获取系统可用内存大小(MB)信息
# 返回值:
# 内存大小(兆字节)
get_total_memory() {
echo $(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024))
}
# 获取以内存定量方式描述的机器类型
# 标志位:
# --memory - 内存大小 (MB,可选)
# 返回值:
# 类型名称
get_machine_size() {
local memory=""
# 检测标志位
while [[ "$#" -gt 0 ]]; do
case "$1" in
--memory)
shift
memory="${1:?missing memory}"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
if [[ -z "$memory" ]]; then
debug "Memory was not specified, detecting available memory automatically"
memory="$(get_total_memory)"
fi
sanitized_memory=$(convert_to_mb "$memory")
if [[ "$sanitized_memory" -gt 26000 ]]; then
echo 2xlarge
elif [[ "$sanitized_memory" -gt 13000 ]]; then
echo xlarge
elif [[ "$sanitized_memory" -gt 6000 ]]; then
echo large
elif [[ "$sanitized_memory" -gt 3000 ]]; then
echo medium
elif [[ "$sanitized_memory" -gt 1500 ]]; then
echo small
else
echo micro
fi
}
# 获取已定义的所有内存大小描述
# 返回值:
# 描述值列表
get_supported_machine_sizes() {
echo micro small medium large xlarge 2xlarge
}
# 将以字符串表示的内存大小转换为以MB为单位的内存大小值 (i.e. 2G -> 2048)
# 参数:
# $1 - 内存大小
# 返回值:
# 转换后的数值
convert_to_mb() {
local amount="${1:-}"
if [[ $amount =~ ^([0-9]+)(M|G) ]]; then
size="${BASH_REMATCH[1]}"
unit="${BASH_REMATCH[2]}"
if [[ "$unit" = "G" ]]; then
amount="$((size * 1024))"
else
amount="$size"
fi
fi
echo "$amount"
}
# 如果禁用调试模式,将输出信息重定向至 /dev/null
# 参数:
# $@ - 待执行的命令
debug_execute() {
local bool="${ENV_DEBUG:-false}"
shopt -s nocasematch
if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
"$@"
else
"$@" >/dev/null 2>&1
fi
}
# 重试执行命令
# 参数:
# $1 - 命令 (字符串)
# $2 - 最大尝试次数. 默认值: 12
# $3 - 重试前等待时间(秒). 默认值: 5
# 返回值:
# 0 / 1
retry_while() {
local -r cmd="${1:?cmd is missing}"
local -r retries="${2:-12}"
local -r sleep_time="${3:-5}"
local return_value=1
read -r -a command <<< "$cmd"
for ((i = 1 ; i <= retries ; i+=1 )); do
"${command[@]}" && return_value=0 && break
sleep "$sleep_time"
done
return $return_value
}
# 生成随机字符串
# 标志位:
# -t|--type - 字符串类型 (ascii, alphanumeric, numeric). 默认值: ascii
# -c|--count - 字符串长度. 默认值: 32
# 返回值:
# 字符串
generate_random_string() {
local type="ascii"
local count="32"
local filter
local result
# 检测标志位
while [[ "$#" -gt 0 ]]; do
case "$1" in
-t|--type)
shift
type="$1"
;;
-c|--count)
shift
count="$1"
;;
*)
echo "Invalid command line flag $1" >&2
return 1
;;
esac
shift
done
# 检测类型
case "$type" in
ascii)
filter="[:print:]"
;;
alphanumeric)
filter="a-zA-Z0-9"
;;
numeric)
filter="0-9"
;;
*)
echo "Invalid type ${type}" >&2
return 1
esac
# Obtain count + 10 lines from /dev/urandom to ensure that the resulting string has the expected size
# Note there is a very small chance of strings starting with EOL character
# Therefore, the higher amount of lines read, this will happen less frequently
result="$(head -n "$((count + 10))" /dev/urandom | tr -dc "$filter" | head -c "$count")"
echo "$result"
}
# 为指定字符串生成 MD5 值
# 参数:
# $1 - 字符串
# 返回值:
# 字符串对应的 MD5
generate_md5_hash() {
local -r str="${1:?missing input string}"
echo -n "$str" | md5sum | awk '{print $1}'
}
+212
View File
@@ -0,0 +1,212 @@
#!/bin/bash
# Ver: 1.1 by Endial Fang (endial@126.com)
#
# 服务管理函数库
# shellcheck disable=SC1091
# 加载依赖项
. /colovu/lib/libvalidations.sh # 数据有效性检测函数库
# 函数列表
# 获取并返回服务 PID
# 参数:
# $1 - PID 文件
# 返回值:
# PID
get_pid_from_file() {
local pid_file="${1:?pid file is missing}"
if [[ -f "$pid_file" ]]; then
if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then
echo "$(< "$pid_file")"
fi
fi
}
# 检测 PID 对应的服务是否在运行中
# 参数:
# $1 - PID
# 返回值:
# 0 / 1
is_service_running() {
local pid="${1:?pid is missing}"
kill -0 "$pid" 2>/dev/null
}
# 通过发送信号停止一个指定 PID 的服务
# 参数:
# $1 - PID 文件
# $2 - 信号 (可选)
stop_service_using_pid() {
local pid_file="${1:?pid file is missing}"
local signal="${2:-}"
local pid
pid="$(get_pid_from_file "$pid_file")"
[[ -z "$pid" ]] || ! is_service_running "$pid" && return
if [[ -n "$signal" ]]; then
kill "-${signal}" "$pid"
else
kill "$pid"
fi
local counter=10
while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do
sleep 1
counter=$((counter - 1))
done
}
# 启动一个 cron 守护进程
# 返回值:
# true / false
cron_start() {
if [[ -x "/usr/sbin/cron" ]]; then
/usr/sbin/cron
elif [[ -x "/usr/sbin/crond" ]]; then
/usr/sbin/crond
else
false
fi
}
# 为指定的服务生成 cron 配置文件
# 参数:
# $1 - 服务名称
# $2 - 命令
# 标志位:
# --run-as - 运行的用户. 默认值: root
# --schedule - Cron 周期配置. 默认值: * * * * *
generate_cron_conf() {
local service_name="${1:?service name is missing}"
local cmd="${2:?command is missing}"
local run_as="root"
local schedule="* * * * *"
local clean="true"
local clean="true"
# 检测标志位
shift 2
while [[ "$#" -gt 0 ]]; do
case "$1" in
--run-as)
shift
run_as="$1"
;;
--schedule)
shift
schedule="$1"
;;
--no-clean)
clean="false"
;;
*)
echo "Invalid command line flag ${1}" >&2
return 1
;;
esac
shift
done
mkdir -p /etc/cron.d
if "$clean"; then
echo "${schedule} ${run_as} ${cmd}" > /etc/cron.d/"$service_name"
else
echo "${schedule} ${run_as} ${cmd}" >> /etc/cron.d/"$service_name"
fi
}
# 为指定的服务生成 monit 配置文件
# 参数:
# $1 - 服务名
# $2 - PID 文件
# $3 - 启动命令
# $4 - 停止命令
# 标志位:
# --disabled - 是否禁用. 默认值: no
generate_monit_conf() {
local service_name="${1:?service name is missing}"
local pid_file="${2:?pid file is missing}"
local start_command="${3:?start command is missing}"
local stop_command="${4:?stop command is missing}"
local monit_conf_dir="/etc/monit/conf.d"
local disabled="no"
# 检测标志位
shift 4
while [[ "$#" -gt 0 ]]; do
case "$1" in
--disabled)
shift
disabled="$1"
;;
*)
echo "Invalid command line flag ${1}" >&2
return 1
;;
esac
shift
done
is_boolean_yes "$disabled" && conf_suffix=".disabled"
mkdir -p "$monit_conf_dir"
cat >"${monit_conf_dir}/${service_name}.conf${conf_suffix:-}" <<EOF
check process ${service_name}
with pidfile "${pid_file}"
start program = "${start_command}" with timeout 90 seconds
stop program = "${stop_command}" with timeout 90 seconds
EOF
}
# 为指定的服务生成 Logrotate 配置文件
# 参数:
# $1 - 应用名称
# $2 - 日志路径
# 标志位:
# --period - 周期
# --rotations - Rotations 存储的数量
# --extra - 扩展参数 (可选)
generate_logrotate_conf() {
local service_name="${1:?service name is missing}"
local log_path="${2:?log path is missing}"
local period="weekly"
local rotations="150"
local extra=""
local logrotate_conf_dir="/etc/logrotate.d"
local var_name
# 检测标志位
shift 2
while [[ "$#" -gt 0 ]]; do
case "$1" in
--period|--rotations|--extra)
var_name="$(echo "$1" | sed -e "s/^--//" -e "s/-/_/g")"
shift
declare "$var_name"="${1:?"$var_name" is missing}"
;;
*)
echo "Invalid command line flag ${1}" >&2
return 1
;;
esac
shift
done
mkdir -p "$logrotate_conf_dir"
cat <<EOF | sed '/^\s*$/d' >"${logrotate_conf_dir}/${service_name}"
${log_path} {
${period}
rotate ${rotations}
dateext
compress
copytruncate
missingok
$(indent "$extra" 2)
}
EOF
}
@@ -1,16 +1,18 @@
#!/bin/bash
# Ver: 1.0 by Endial Fang (endial@126.com)
# Ver: 1.1 by Endial Fang (endial@126.com)
#
# 数据有效性校验函数库
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
. /colovu/lib/liblog.sh # 日志输出函数库
# 函数列表
# 检测数据是否为整数
# 参数:
# $1 - 待检测的数据
# 返回值:
# true / false
is_int() {
local -r int="${1:?missing value}"
if [[ "$int" =~ ^-?[0-9]+ ]]; then
@@ -23,6 +25,8 @@ is_int() {
# 检测数据是否为正整数
# 参数:
# $1 - 待检测的数据
# 返回值:
# true / false
is_positive_int() {
local -r int="${1:?missing value}"
if is_int "$int" && (( "${int}" >= 0 )); then
@@ -35,6 +39,8 @@ is_positive_int() {
# 检测数据是否为布尔值 '1' 或字符串 'yes/true'
# 参数:
# $1 - 待检测的数据
# 返回值:
# true / false
is_boolean_yes() {
local -r bool="${1:-}"
# comparison is performed without regard to the case of alphabetic characters
@@ -49,6 +55,8 @@ is_boolean_yes() {
# 检测数据是否为字符串 'yes/no'
# 参数:
# $1 - 待检测的数据
# 返回值:
# true / false
is_yes_no_value() {
local -r bool="${1:-}"
if [[ "$bool" =~ ^(yes|no)$ ]]; then
@@ -61,6 +69,8 @@ is_yes_no_value() {
# 检测数据是否为字符串 'true/false'
# 参数:
# $1 - 待检测的数据
# 返回值:
# true / false
is_true_false_value() {
local -r bool="${1:-}"
if [[ "$bool" =~ ^(true|false)$ ]]; then
@@ -73,6 +83,8 @@ is_true_false_value() {
# 检测提供的参数是否为空字符串或未定义
# 参数:
# $1 - 待检测的数据
# 返回值:
# true / false
is_empty_value() {
local -r val="${1:-}"
if [[ -z "$val" ]]; then
@@ -83,10 +95,12 @@ is_empty_value() {
}
# 检测数据是否为有效的端口号
# 标志位:
# -unprivileged - 没有特权的端口
# 参数:
# $1 - 待检测的数据
# 返回值:
# 布尔值 或 错误消息
# true / false 或 错误消息
validate_port() {
local value
local unprivileged=0
@@ -145,6 +159,8 @@ validate_port() {
# 检测数据是否为有效的IPv4地址
# 参数:
# $1 - 待检测的数据
# 返回值:
# 0 / 1
validate_ipv4() {
local ip="${1:?ip is missing}"
local stat=1
@@ -159,8 +175,13 @@ validate_ipv4() {
}
# 校验字符串格式
# 标志位:
# -min-length - 最小长度
# -max-length - 最大长度
# 参数:
# $1 - 待检测的数据
# 返回值:
# 0 / 1
validate_string() {
local string
local min_length=-1
-109
View File
@@ -1,109 +0,0 @@
#!/bin/bash
# Ver: 1.2 by Endial Fang (endial@126.com)
#
# 操作系统控制函数库
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
# 函数列表
# 检测指定用户账户是否存在
# 参数:
# $1 - 用户账户
user_exists() {
local user="${1:?user is missing}"
id "$user" >/dev/null 2>&1
}
# 检测指定用户分组是否存在
# 参数:
# $1 - 用户组
group_exists() {
local group="${1:?group is missing}"
getent group "$group" >/dev/null 2>&1
}
# 获取系统可用内存大小(MB)信息
get_total_memory() {
echo $(($(grep MemTotal /proc/meminfo | awk '{print $2}') / 1024))
}
# 获取以定量方式描述的内存大小
# 参数:
# $1 - 内存大小 (MB,可选)
get_machine_size() {
local memory="${1:-}"
if [[ -z "$memory" ]]; then
debug "Memory was not specified, detecting available memory automatically"
memory="$(get_total_memory)"
fi
sanitized_memory=$(convert_to_mb "$memory")
if [[ "$sanitized_memory" -gt 26000 ]]; then
echo 2xlarge
elif [[ "$sanitized_memory" -gt 13000 ]]; then
echo xlarge
elif [[ "$sanitized_memory" -gt 6000 ]]; then
echo large
elif [[ "$sanitized_memory" -gt 3000 ]]; then
echo medium
elif [[ "$sanitized_memory" -gt 1500 ]]; then
echo small
else
echo micro
fi
}
# 获取已定义的所有内存大小描述
get_supported_machine_sizes() {
echo micro small medium large xlarge 2xlarge
}
# 将以字符串表示的内存大小转换为以MB为单位的内存大小值 (i.e. 2G -> 2048)
# 参数:
# $1 - 内存大小
convert_to_mb() {
local amount="${1:-}"
if [[ $amount =~ ^([0-9]+)(M|G) ]]; then
size="${BASH_REMATCH[1]}"
unit="${BASH_REMATCH[2]}"
if [[ "$unit" = "G" ]]; then
amount="$((size * 1024))"
else
amount="$size"
fi
fi
echo "$amount"
}
# 如果禁用调试模式,将输出信息重定向至 /dev/null
# 参数:
# $@ - 待执行的命令
debug_execute() {
local -r bool="${ENV_DEBUG:-false}"
shopt -s nocasematch
if [[ "$bool" = 1 || "$bool" =~ ^(yes|true)$ ]]; then
"$@"
else
"$@" >/dev/null 2>&1
fi
}
# 重试执行命令
# 参数:
# $1 - cmd (as a string)
# $2 - 最大尝试次数. Default: 12
# $3 - 重试前等待时间(秒). Default: 5
retry_while() {
local -r cmd="${1:?cmd is missing}"
local -r retries="${2:-12}"
local -r sleep_time="${3:-5}"
local return_value=1
read -r -a command <<< "$cmd"
for ((i = 1 ; i <= retries ; i+=1 )); do
"${command[@]}" && return_value=0 && break
sleep "$sleep_time"
done
return $return_value
}
-87
View File
@@ -1,87 +0,0 @@
#!/bin/bash
# Ver: 1.0 by Endial Fang (endial@126.com)
#
# 服务管理函数库
# shellcheck disable=SC1091
# 加载依赖项
. /usr/local/scripts/liblog.sh # 日志输出函数库
# 函数列表
# 获取并返回服务 PID
# 参数:
# $1 - PID 文件
get_pid_from_file() {
local pid_file="${1:?pid file is missing}"
if [[ -f "$pid_file" ]]; then
if [[ -n "$(< "$pid_file")" ]] && [[ "$(< "$pid_file")" -gt 0 ]]; then
echo "$(< "$pid_file")"
fi
fi
}
# 检测 PID 对应的服务是否在运行中
# 参数:
# $1 - PID
is_service_running() {
local pid="${1:?pid is missing}"
kill -0 "$pid" 2>/dev/null
}
# 通过发送信号停止一个指定的服务
# 参数:
# $1 - PID 文件
# $2 - 信号 (可选)
stop_service_using_pid() {
local pid_file="${1:?pid file is missing}"
local signal="${2:-}"
local pid
pid="$(get_pid_from_file "$pid_file")"
[[ -z "$pid" ]] || ! is_service_running "$pid" && return
if [[ -n "$signal" ]]; then
kill "-${signal}" "$pid"
else
kill "$pid"
fi
local counter=10
while [[ "$counter" -ne 0 ]] && is_service_running "$pid"; do
sleep 1
counter=$((counter - 1))
done
}
# 生成一个 Logrotate 配置文件
# 参数:
# $1 - 应用名称
# $2 - 日志路径及日志文件名
# $3 - 周期
# $4 - Rotations 存储的数量
# $5 - 其他参数 (可选)
generate_logrotate_conf() {
local service_name="${1:?service name is missing}"
local log_path="${2:?log path is missing}"
local period="${3:-weekly}"
local rotations="${4:-150}"
local extra_options="${5:-}"
local logrotate_conf_dir="/etc/logrotate.d"
mkdir -p "$logrotate_conf_dir"
cat >"${logrotate_conf_dir}/${service_name}" <<-'EOF'
${log_path} {
${period}
rotate ${rotations}
dateext
compress
copytruncate
missingok
${extra_options}
}
EOF
}