#!/bin/bashset -eo pipefail
set +e
# Script trace mode# 设置是否启用调试模式,即使用set -o xtraceif["${DEBUG_MODE}"=="true"];thenset -o xtrace
fi# Type of Zabbix component# Possible values: [server, proxy, agent, frontend, java-gateway, appliance]# 设置组件类型,通过zbx_type接收来自容器ENV中的ZBX_TYPE的变量
zbx_type=${ZBX_TYPE}# Type of Zabbix database# Possible values: [mysql, postgresql]# 设置数据库类型,通过zbx_db_type接收来自容器启动时ZBX_DB_TYPE的变量内容
zbx_db_type=${ZBX_DB_TYPE}# Type of web-server. Valid only with zbx_type = frontend# Possible values: [apache, nginx]# 设置zabbix-web类型,支持apache以及nginx
zbx_opt_type=${ZBX_OPT_TYPE}# Default Zabbix installation name# Used only by Zabbix web-interface# 变量赋值,如果没有配置,则会采用'-'右边的默认值
ZBX_SERVER_NAME=${
ZBX_SERVER_NAME:-"Zabbix docker"}# Default Zabbix server host
ZBX_SERVER_HOST=${
ZBX_SERVER_HOST:-"zabbix-server"}# Default Zabbix server port number
ZBX_SERVER_PORT=${
ZBX_SERVER_PORT:-"10051"}# Default timezone for web interface
PHP_TZ=${
PHP_TZ:-"Europe/Riga"}#Enable PostgreSQL timescaleDB feature:
ENABLE_TIMESCALEDB=${
ENABLE_TIMESCALEDB:-"false"}# Default directories# User 'zabbix' home directory
ZABBIX_USER_HOME_DIR="/var/lib/zabbix"# Configuration files directory
ZABBIX_ETC_DIR="/etc/zabbix"# Web interface www-root directory
ZBX_FRONTEND_PATH="/usr/share/zabbix"# usage: file_env VAR [DEFAULT]# as example: file_env 'MYSQL_PASSWORD' 'zabbix'# (will allow for "$MYSQL_PASSWORD_FILE" to fill in the value of "$MYSQL_PASSWORD" from a file)# unsets the VAR_FILE afterwards and just leaving VAR# 读取文件内容并将内容赋值给变量VAR,用于敏感变量内容赋值,比如密码,数据库配置等。
file_env(){
local var="$1"
local fileVar="${var}_FILE"
local defaultValue="${2:-}"if["${!var:-}"]&&["${!fileVar:-}"];thenecho"**** Both variables $var and $fileVar are set (but are exclusive)"exit 1
fi
local val="$defaultValue"if["${!var:-}"];then
val="${!var}"echo"** Using ${var} variable from ENV"elif["${!fileVar:-}"];thenif[! -f "${!fileVar}"];thenecho"**** Secret file \"${!fileVar}\" is not found"exit 1
fi
val="$(<"${!fileVar}")"echo"** Using ${var} variable from secret file"fiexport"$var"="$val"
unset "$fileVar"}# 配置zabbix数据库,此部分适用于all in one模式的部署,生产中不建议使用
configure_db_mysql(){
["${DB_SERVER_HOST}"!="localhost"]&&returnecho"** Configuring local MySQL server"
MYSQL_ALLOW_EMPTY_PASSWORD=true
MYSQL_DATA_DIR="/var/lib/mysql"if[ -f "/etc/mysql/my.cnf"];then
MYSQL_CONF_FILE="/etc/mysql/my.cnf"elif[ -f "/etc/my.cnf.d/server.cnf"];then
MYSQL_CONF_FILE="/etc/my.cnf.d/server.cnf"
DB_SERVER_SOCKET="/var/lib/mysql/mysql.sock"elif[ -f "/etc/my.cnf.d/mariadb-server.cnf"];then
MYSQL_CONF_FILE="/etc/my.cnf.d/mariadb-server.cnf"
DB_SERVER_SOCKET="/var/run/mysqld/mysqld.sock"elseecho"**** Could not found MySQL configuration file"exit 1
fiif[ -f "/usr/bin/mysqld"];then
MYSQLD=/usr/bin/mysqld
elif[ -f "/usr/sbin/mysqld"];then
MYSQLD=/usr/sbin/mysqld
elif[ -f "/usr/libexec/mysqld"];then
MYSQLD=/usr/libexec/mysqld
elseecho"**** Could not found mysqld binary file"exit 1
fised -Ei 's/^(bind-address|log)/#&/'"$MYSQL_CONF_FILE"if[! -d "$MYSQL_DATA_DIR/mysql"];then[ -d "$MYSQL_DATA_DIR"]||mkdir -p "$MYSQL_DATA_DIR"chown -R mysql:mysql "$MYSQL_DATA_DIR"echo"** Installing initial MySQL database schemas"
mysql_install_db --user=mysql --datadir="$MYSQL_DATA_DIR" 2>&1
elseecho"**** MySQL data directory is not empty. Using already existing installation."chown -R mysql:mysql "$MYSQL_DATA_DIR"fimkdir -p /var/run/mysqld
ln -s /var/run/mysqld /run/mysqld
chown -R mysql:mysql /var/run/mysqld
chown -R mysql:mysql /run/mysqld
echo"** Starting MySQL server in background mode"nohup$MYSQLD --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin \
--user=mysql --log-output=none --pid-file=/var/lib/mysql/mysqld.pid \
--port=3306 --character-set-server=utf8 --collation-server=utf8_bin &}#准备系统参数,即将变量进行赋值,变量的赋值来源有两种,一种为容器启动时传进来的,另一种为默认值
prepare_system(){
local type=$1
local web_server=$2echo"** Preparing the system"#此函数主要用于appliance模式if["$type"!="appliance"];thenreturnfi
ZBX_ADD_AGENT=${
ZBX_ADD_AGENT:-"false"}
ZBX_ADD_JAVA_GATEWAY=${
ZBX_ADD_JAVA_GATEWAY:-"false"}
ZBX_ADD_SERVER=${
ZBX_ADD_SERVER:-"true"}["${ZBX_ADD_SERVER}"=="true"]&& ZBX_SERVER_HOST="localhost"["${ZBX_ADD_SERVER}"=="true"]&& ZBX_SERVER_PORT="10051"
ZBX_MAIN_DB=${
ZBX_MAIN_DB:-"mysql"}
ZBX_ADD_PROXY=${
ZBX_ADD_PROXY:-"false"}
ZBX_PROXY_DB=${
ZBX_PROXY_DB:-"sqlite3"}
ZBX_ADD_WEB=${
ZBX_ADD_WEB:-"true"}
ZBX_WEB_SERVER=${
ZBX_WEB_SERVER:-"nginx"}
DB_SERVER_HOST=${
DB_SERVER_HOST:-"localhost"}["${ZBX_ADD_JAVA_GATEWAY}"=="true"]&& ZBX_JAVAGATEWAY_ENABLE="true"["${ZBX_ADD_JAVA_GATEWAY}"=="true"]&& ZBX_JAVAGATEWAY="localhost"["${ZBX_ADD_JAVA_GATEWAY}"=="true"]&& ZBX_JAVAGATEWAYPORT="10052"["${ZBX_ADD_SERVER}"=="true"]&& configure_db_${ZBX_MAIN_DB}}#此函数用于对特殊字符进行处理,使用反斜杠\对字符进行转义,如变量为[test],处理后则为\[test\]
escape_spec_char(){
local var_value=$1
var_value="${var_value//\\/\\\\}"
var_value="${var_value//[$'\n']/}"
var_value="${var_value//\//\\/}"
var_value="${var_value//./\\.}"
var_value="${var_value//\*/\\*}"
var_value="${var_value//^/\\^}"
var_value="${var_value//\$/\\\$}"
var_value="${var_value//\&/\\\&}"
var_value="${var_value//\[/\\[}"
var_value="${var_value//\]/\\]}"echo"$var_value"}# 更新配置文件# 参数1:配置文件路径# 参数2:变量名称# 参数3:变量值# 参数4:是否为多实例# 在这函数里面,使用了sed字符流处理工具实现了对配置文件的更新和修改
update_config_var(){
local config_path=$1
local var_name=$2
local var_value=$3
local is_multiple=$4# 检查配置文件是否存在if[! -f "$config_path"];thenecho"**** Configuration file '$config_path' does not exist"returnfiecho -n "** Updating '$config_path' parameter \"$var_name\": '$var_value'... "# 如果没有传入第3个参数,即参数值,则将该参数配置从配置文件中进行移除# ie: before: VAR=test# after : # Remove configuration parameter definition in case of unset parameter valueif[ -z "$var_value"];then# 删除以变量名称为开头所在的行sed -i -e "/^$var_name=/d""$config_path"echo"removed"returnfi# 如果传入第3个参数为一对空的双引号"",则将参数后面的值抹去# ie: before: VAR=test# after : VAR=# Remove value from configuration parameter in case of double quoted parameter valueif["$var_value"=='""'];then# sed -i -e '/^A=/s/=.*/=/' test.conf# 将=后面的值全部替换为=sed -i -e "/^$var_name=/s/=.*/=/""$config_path"echo"undefined"returnfi# Use full path to a file for TLS related configuration parametersif[[$var_name=~ ^TLS.*File$ ]];then
var_value=$ZABBIX_USER_HOME_DIR/enc/$var_valuefi# Escaping characters in parameter value
var_value=$(escape_spec_char "$var_value")# 判断在参数文件中是否有该变量,如果有则进行更新if["$(grep -E "^$var_name=" $config_path)"]&&["$is_multiple"!="true"];thensed -i -e "/^$var_name=/s/=.*/=$var_value/""$config_path"echo"updated"# 判断在参数文件中,以[# 变量名称]的数量有多少个elif["$(grep -Ec "^# $var_name=" $config_path)" -gt 1 ];then# 在匹配的行之前插入变量值# ie: before # VAR=# after VAR=new_value# # VAR=sed -i -e "/^[#;] $var_name=$/i\\$var_name=$var_value""$config_path"echo"added first occurrence"else# 匹配在参数文件中,以# 或者, 变量名= 所在行下面新增一行变量=值# 这里的&为模式匹配保存下来的内容,后面加上换行符,意味着新增一行# ie:before # VAR=demo# after # VAR=demo# VAR=new_valuesed -i -e "/^[#;] $var_name=/s/.*/&\n$var_name=$var_value/""$config_path"echo"added"fi}
update_config_multiple_var(){
local config_path=$1
local var_name=$2
local var_value=$3
var_value="${var_value%\"}"
var_value="${var_value#\"}"
local IFS=,
local OPT_LIST=($var_value)for value in"${OPT_LIST[@]}";do
update_config_var $config_path$var_name$valuetruedone}# Check prerequisites for MySQL database# 检查Mysql参数并根据类型赋值相应的mysql变量参数
check_variables_mysql(){
local type=$1
DB_SERVER_HOST=${
DB_SERVER_HOST:-"mysql-server"}
DB_SERVER_PORT=${
DB_SERVER_PORT:-"3306"}
USE_DB_ROOT_USER=false
CREATE_ZBX_DB_USER=false