#!/bin/bash # -*- coding:utf-8 -*- ############################################################################# # Copyright (c): 2021, Huawei Tech. Co., Ltd. # FileName : install.sh # Version : V1.0.0 # Date : 2021-04-17 # Description : the script used to install the single cluster on one machine ######################################### function check_passwd() { passwd=$1 local -i num=0 if [ -n "$(echo $passwd | grep -E --color '^(.*[a-z]+).*$')" ] then num=$[ ${num} + 1 ] fi if [ -n "$(echo $passwd | grep -E --color '^(.*[A-Z]).*$')" ] then num=$[ ${num} + 1 ] fi password_sepcical_char=('~' '!' '@' '#' '$' '%' '^' '&' '(' ')' '_' '-' '*' '+' '=' '{' '[' ']' '}' '|' '\' ':' ';' '"' ',' "'" '.' '<' '.' '?' '/') for element in ${password_sepcical_char[@]} do compare_str="${element}" if [[ "${passwd}" =~ "${compare_str}" ]] then num=$[ ${num} + 1 ] break fi done if [ -n "$(echo $passwd | grep -E --color '^(.*[0-9]).*$')" ] then num=$[ ${num} + 1 ] fi if [ ${#passwd} -lt 8 ] || [ $num -lt 3 ] || [ ${#passwd} -gt 32 ] then return 1 fi return 0 } declare password="" read -t 1 password if [ "${password}" != "" ] then check_passwd "${password}" if [ $? -ne 0 ] then echo -e "\033[31mthe password can contain only 8 to 32 characters and at least three types of the following characters: uppercase letters, lowercase letters, digits, and special characters..\033[0m" exit 1 fi fi declare user=$(whoami) if [ X"$user" = X"root" ]; then echo "error: can not install gauss with root" exit 1 fi declare root_path=$(cd $(dirname $0);pwd) if [ -e "${root_path}/dependency" ] then export LD_LIBRARY_PATH="${root_path}"/dependency:$LD_LIBRARY_PATH fi declare data_path="" declare app_path="" declare env_file=~/.bashrc declare mode_type="single" declare -a localips declare -a localhosts declare -a remoteips declare -i port=5432 declare ssl="off" declare init_parameters="" declare init_show_parameters="" declare config_parameters="" declare password_check="" declare nodename="opengauss" declare applicationname="" declare action="start" declare mode="-Z single_node" declare -i replconninfo_flag=1 declare -i install_path_full_flag=1 declare -i data_full_flag=1 declare -i start=1 declare -i ulimit_flag=1 declare -i interactive_passwd_flag=1 declare log_path="" declare guc_file="" declare log_file="${root_path}/install.log" declare cert_path="" declare client_ip="" if [ -e "${log_file}" ] then cat /dev/null > "${log_file}" else touch "${log_file}" fi if [ $? -ne 0 ] then echo "error: failed to create the log file." exit 1 fi # obtain all IP addresses of the local host. declare -i ipindex=0 for localip in $(/usr/sbin/ip addr | awk '/^[0-9]+:/ {flag = !/docker|veth|br-|lo:/} flag && /inet(6)? [0-9a-fA-F:.]+\/[0-9]+/ {split($2, a, "/"); print a[1];}') do localips[ipindex]=${localip} ipindex=$[ ${ipindex} + 1 ] done if [ ${#localips[*]} -eq 0 ] then die "the ip address of the machine is not detected." fi function usage() { echo " Usage: $0 [OPTION] Arguments: -D|--data-path data path -R|--app-path app directory -P|--gsinit-parameter initializing database parameters -C|--dn-guc database configuration parameters -m|--mode database installation mode, only three modes are supported: single、primary、and standby, default single -l|--log-path global log configuration path -f|--guc-file global GUC configuration file -n|--nodename node name (the default value is same with mode) -h|--help show this help, then exit --env-sep-file detach environment variable files --start indicates whether to start the cluster. --ulimit indicates whether to set the maximum number of open files --cert-path SSL certificate path, if this parameter is used, SSL will be on. --ssl-client-ip client ip address, the parameter modification takes effect only when the SSL switch is turned on. " } function info() { echo "$1" >> "${log_file}" echo -e "\033[32minfo:\033[0m$1" } function log() { echo "$1" >> "${log_file}" echo "$1" } function die() { echo "$1" >> "${log_file}" echo -e "\033[31m$1\033[0m" exit 1 } function warn() { echo "$1" >> "${log_file}" echo -e "\033[33m$1\033[0m" } function security_check() { if [[ "$1" == *[\(\)\{\}\[\]\<\>\`\\\*\!\|\;\&\$\~\?]* ]];then die "$1 contain illegal characters." fi } function path_security_check() { if [[ "$1" == *[\(\)\{\}\[\]\<\>\`\\\ \*\!\|\;\&\$\~\?]* ]];then die "$1 contain illegal characters." fi } function hide_password() { tmppassword="" stty -echo if [ $1 -eq 0 ] then read -p "please input database password:" password else read -p "please retry input database password:" password_check fi stty echo } # check if it has read/write/execute permission. function check_red_permission() { if [ ! -r "$1" ] then die "the user does not have the read permission on the directory/file $1." fi } function check_write_permission() { if [ ! -w "$1" ] then die "the user does not have the write permission on the directory/file $1." fi } function check_execute_permission() { if [ ! -x "$1" ] then die "the user does not have the execute permission on the directory/file $1." fi } # check whether the path exists. function check_path() { if echo "$1"|grep -Eq "^/{1,}$"; then die "path cannot be / " fi path_security_check "$1" if [ -e "$1" ] then if [ -f "$1" ] then die "the path $1 already exists and it is a file." fi if [[ -n $(ls -A "$1") && "$2" = "install" ]] then install_path_full_flag=0 elif [[ -n $(ls -A "$1") && "$2" = "data" ]] then data_full_flag=0 fi else mkdir -p "$1" chmod 700 "$1" fi check_red_permission "$1" check_write_permission "$1" check_execute_permission "$1" } # check whether the IPV4 address is valid. function is_valid_ipv4() { local ip=$1 local ret=1 if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] then # use dots (.) to convert the data into an array to facilitate the following judgment. ip=(${ip//\./ }) [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] ret=$? fi return $ret } # check whether the IPV6 address is valid. function is_valid_ipv6() { parameter_ip=$1 if [[ "$1" =~ fe80.* ]] then if [ -z $(echo "$1" | grep %) ] then die "the local ipv6 address needs to be added with % and the network adapter name(such as fe80*%eth0)." fi parameter_ip=${parameter_ip%\%*} fi local ip=${parameter_ip} local ret=1 if [[ "$ip" =~ ([a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7}) ]] then ret=0 fi return $ret } # check whether the local host port is occupied # check whether the entered ip address is the same as the ip address of the host # identify the ip address of the remote host and add it to the configuration file later. function check_conf_paramters() { replconninfo=$(echo $1 | grep "replconninfo") port_flag=$(echo $1 | grep "port") if [ "${replconninfo}" != "" ] then replconninfo_flag=0 remote_port_flag=$(echo "$1" | grep "remoteport") if [ -z "${remote_port_flag}" ] then die "replconninfo need parameter of 'remoteport'." fi # prevent repeated port identification and remove remoteport. parameter=$(echo "$1" | sed 's/remoteport//g' | sed "s/remoteport//g" | sed "s#'##g" | sed 's#"##g') localhost_flag=$(echo "${parameter}" | grep "localhost") if [ "${localhost_flag}" = "" ] then die "replconninfo need parameter of 'localhost.'" fi remotehost_flag=$(echo "${parameter}" | grep "remotehost") if [ "${remotehost_flag}" = "" ] then die "replconninfo need parameter of 'remotehost'." fi localport_flag=$(echo "${parameter}" | grep "localport") if [ "${localport_flag}" = "" ] then die "replconninfo need parameter of 'localport'." fi # init parameters parameter=$(echo "$1" | sed "s/remoteport//g" | sed "s#'##g" | sed 's#"##g') parameter_array=(${parameter//=/ }) len=${#parameter_array[*]} if [[ "${localhost_flag}" != "" || "${localport_flag}" != "" || "${remote_port_flag}" != "" || "${remotehost_flag}" != "" ]] then index=0 while [ ${index} -lt $[ ${len} + 1 ] ] do key=${parameter_array[${index}]} if [ "${key}" = "localhost" ] then index=$[ ${index} + 1 ] value=${parameter_array[${index}]} check_value=${value} is_valid_ipv4 "$value" if [ $? -ne 0 ] then is_valid_ipv6 "$value" if [ $? -ne 0 ] then is_valid_ipv6 "$value" die "the local ip address ${value} is not standard." fi if [[ "$value" =~ fe80.* ]] then check_value=${check_value%\%*} fi fi res=$(echo "${localips[@]}" | grep -wq "${check_value}" && echo "yes" || echo "no") if [ "${res}" = "no" ] then die "the ip address of the network adapter is inconsistent with that of the host ${value}" else res=$(echo "${localhosts[@]}" | grep -wq "${check_value}" && echo "yes" || echo "no") if [ "${res}" = "no" ] then localhostscount=${#localhosts[*]} localhosts[localhostscount]=${value} fi fi elif [ "${key}" = "remotehost" ] then index=$[ ${index} + 1 ] value=${parameter_array[${index}]} is_valid_ipv4 "$value" if [ $? -ne 0 ] then is_valid_ipv6 "$value" if [ $? -ne 0 ] then die "the remote ip address ${value} is not standard." fi fi res=$(echo "${remoteips[@]}" | grep -wq "${value}" && echo "yes" || echo "no") if [ "${res}" = "no" ] then remoteipcount=${#remoteips[*]} remoteips[remoteipcount]=${value} fi elif [ "${key}" = "localport" ] then index=$[ ${index} + 1 ] value=${parameter_array[${index}]} if [[ ${value} -lt 1024 || ${value} -gt 65535 ]] then die "the port number must be between 1024 and 65535." fi netstat -tunl | grep -w "${value}" if [ $? -eq 0 ] then die "the port ${value} is already in use" fi elif [ "${key}" = "remoteport" ] then index=$[ ${index} + 1 ] value=${parameter_array[${index}]} if [[ ${value} -lt 1024 || ${value} -gt 65535 ]] then die "the port number must be between 1024 and 65535." fi netstat -tunl | grep -w "${value}" if [ $? -eq 0 ] then die "the port ${value} is already in use" fi fi index=$[ ${index} + 1 ] done fi elif [ "${port_flag}" != "" ] then parameter=$1 parameter_array=(${parameter//=/ }) if [ ${#parameter_array[*]} -eq 2 ] then value=${parameter_array[1]} if [[ ${value} -lt 1024 || ${value} -gt 65535 ]] then die "the port number must be between 1024 and 65535." fi netstat -tunl | grep -w "${value}" if [ $? -eq 0 ] then die "the port ${value} is already in use" fi port=${value} fi fi config_parameters="${config_parameters} -c \"$1\"" } # check whether the database password is normal and empty. function check_init_paramters() { parameter=$(echo "$1" | sed "s#'##g" | sed 's#"##g') interactive_passwd=$(echo "${parameter}" | grep "\-W") if [ "${interactive_passwd}" != "" ] then interactive_passwd_flag=0 fi passwd_flag=$(echo "${parameter}" | grep -E "\-w\s+|\-\-pwpasswd=") if [ "${passwd_flag}" != "" ] then pwpasswd_flag=$(echo "${parameter}" | grep -E "\-\-pwpasswd=") if [ "${pwpasswd_flag}" != "" ] then parameter=$(echo "${parameter}" | sed "s/--pwpasswd=/--pwpasswd /g") fi parameter_array=(${parameter// / }) len=${#parameter_array[*]} index=0 while [ ${index} -lt $[ ${len} + 1 ] ] do key=${parameter_array[${index}]} if [[ "${key}" = "-w" || "${key}" = "--pwpasswd" ]] then index=$[ ${index} + 1 ] password=${parameter_array[${index}]} check_passwd $password if [ $? -ne 0 ] then die "the password can contain only 8 to 32 characters and at least three types of the following characters: uppercase letters, lowercase letters, digits, and special characters." fi fi index=$[ ${index} + 1 ] done init_show_parameters="${init_show_parameters} ""-w ******" else init_show_parameters="${init_show_parameters} "$1 fi init_parameters="${init_parameters} "$1 } function check_os() { if [ ${ulimit_flag} -eq 0 ] then ulimit -SHn 1000000 if [ $? -ne 0 ] then echo "error: failed to set the maximum number of open files, an exception occurs when the ulimit -SHn 1000000 command is executed.." exit 1 fi sed -i "/.*ulimit\\s*-SHn/d" ${env_file} echo "ulimit -SHn 1000000" >> ${env_file} fi # check shm local shared_buffers=1073741824 # 1G local shmmax=$(cat /proc/sys/kernel/shmmax) env test ${shared_buffers} -gt ${shmmax} && echo "shared_buffers(1073741824) must be less than shmmax($shmmax), Please check it (vim /proc/sys/kernel/shmmax)." && exit 1 local shmall=$(cat /proc/sys/kernel/shmall) local pagesize=$(getconf PAGESIZE) if [ $((${shmall}/1024/1024/1024*${pagesize})) -ne 0 ]; then if [ $((${shared_buffers}/1024/1024/1024-${shmall}/1024/1024/1024*${pagesize})) -gt 0 ]; then die "the usage of the device [Shared_buffers] space(1073741824) cannot be greater than shmall*PAGESIZE($shmall*$pagesize), Please check it (vim /proc/sys/kernel/shmmall)." fi fi # check sem local -a sem local -i index=0 local max_connection=5000 local conn_floor for line in $(cat /proc/sys/kernel/sem) do sem[index]=${line} index=$[ ${index} + 1 ] done if [ ${sem[0]} -lt 17 ] then die "the maximum number of SEMMSL is not correct, please change it (/proc/sys/kernel/sem)), ensure that the value of first sem is greater than 17." fi let conn_floor=(${max_connection}+150)/16 if [ ${sem[3]} -lt ${conn_floor} ] then die "the maximum number of SEMMNI is not correct, please change it (/proc/sys/kernel/sem)), ensure that the value of fourth sem is greater than 320." fi let conn_floor=${conn_floor}*17 if [ ${sem[1]} -lt ${conn_floor} ] then die "the maximum number of SEMMNS is not correct, please change it (/proc/sys/kernel/sem)), ensure that the value of second sem is greater than 5500." fi info "[check install env and os setting success.]" } function check() { if [[ "${mode_type}" != "single" && ""${replconninfo_flag} -ne 0 ]] then die "the parameter -C|--dn-guc["replconninfo='value'"] can not be empty." fi } function permission_process_bin() { chmod 500 "$1" for bin_file in $(ls "$1") do if [ "${bin_file##*.}" = "conf" ];then chmod 400 "$1/${bin_file}" elif [ ! -L $1"/"${bin_file} ];then chmod 500 "$1/${bin_file}" fi done } function decompress() { cd $root_path # get OS distributed version. kernel="" if [ -f "/etc/euleros-release" ] then kernel=$(cat /etc/euleros-release | awk -F ' ' '{print $1}' | tr a-z A-Z) if [ "${kernel}" = "Euleros" ] then kernel="openEuler" fi elif [ -f "/etc/openEuler-release" ] then kernel=$(cat /etc/openEuler-release | awk -F ' ' '{print $1}') elif [ -f "/etc/centos-release" ] then kernel=$(cat /etc/centos-release | awk -F ' ' '{print $1}') else kernel=$(lsb_release -d | awk -F ' ' '{print $2}') fi log "kernel: ${kernel}" bin_res=$(ls | grep openGauss-Lite*.bin) if [ "${bin_res}" = "" ] then die "can not find suitable bin file, expected bin file is ${bin_res}" fi log "bin file: ${bin_res}" bin_name=$(echo "$bin_res" | sed 's/.bin//g') sha_res=$(ls -a | grep -E "${bin_name}.sha256") if [ "${sha_res}" = "" ] then die "can not find suitable verification file, expected bin file is ${bin_name}.sha256" fi log "verification file: ${sha_res}" sha256sum "${bin_name}.bin" | awk -F" " '{print $1}' > "${bin_name}-check.sha256" if [ $? -ne 0 ] then die "check integrality of bin file failed" fi sha_res=$(sha256sum -t ${bin_name}.sha256 | awk -F" " '{print $1}') check_res=$(sha256sum -t ${bin_name}-check.sha256 | awk -F" " '{print $1}') if [ "${sha_res}" != "${check_res}" ] then die "computed checksum did not match" fi rm -rf "${bin_name}-check.sha256" cp ${bin_res} ${app_path} && cp version.cfg ${app_path} if [ $? -ne 0 ] then die "copy binary files *.bin and version.cfg to install path error" fi cd ${app_path} tar -zxf ${bin_name}.bin if [ $? -ne 0 ] then die "decompress binary files (*.bin) error" fi permission_process_bin "${app_path}/bin" chmod 500 "${app_path}/lib" find "${app_path}/lib/" -type d | xargs chmod 500 find "${app_path}/lib/" -type f | xargs chmod 500 chmod 700 "${app_path}/share" find "${app_path}/share/" -type d | xargs chmod 700 find "${app_path}/share/" -type f | xargs chmod 600 chmod -R 500 "${app_path}/include" find "${app_path}/include/" -type d | xargs chmod 500 find "${app_path}/include/" -type f | xargs chmod 400 chmod -R 500 "${app_path}/etc" chmod 400 "${app_path}/version.cfg" rm -rf ./*.bin } function set_environment() { if [ "$2" = "app" ] then # set GAUSSHOME gausshome=$(cd ${app_path}; pwd) sed -i "/.*export\\s*GAUSSHOME=/d" ${env_file} echo "export GAUSSHOME=${gausshome}" >> ${env_file} # set PATH and LD_LIBRARY_PATH sed -i "/.*export\\s*PATH=/d" ${env_file} echo "export PATH=${gausshome}/bin:"'$PATH' >> ${env_file} log "export PATH=${gausshome}/bin:$PATH >> ${env_file}" sed -i "/.*export\\s*LD_LIBRARY_PATH=/d" ${env_file} echo "export LD_LIBRARY_PATH=${gausshome}/lib:"'$LD_LIBRARY_PATH' >> ${env_file} log "export LD_LIBRARY_PATH=${gausshome}/lib:$LD_LIBRARY_PATH >> ${env_file}" info "[set GAUSSHOME environment variables success.]" elif [ "$2" = "data" ] then # set GAUSSDATA gaussdata=$(cd ${data_path}; pwd) sed -i "/.*export\\s*GAUSSDATA=/d" ${env_file} echo "export GAUSSDATA=${gaussdata}" >> ${env_file} echo "export PGDATA=${gaussdata}" >> ${env_file} info "[set GAUSSDATA environment variables success.]" elif [ "$2" = "log" ] then # set GAUSSLOG gausslog=$(cd ${log_path}; pwd) sed -i "/.*export\\s*GAUSSLOG=/d" ${env_file} echo "export GAUSSLOG=${gausslog}" >> ${env_file} info "[set GAUSSLOG environment variables success.]" fi } function init_db() { cd ${app_path}/bin if [ ! -e gs_initdb ] then die "no gauss installation file is found in app-path. check the installation directory." fi info "cmd : gs_initdb -D ${data_path} --nodename=${nodename} ${init_show_parameters}" ./gs_initdb -D ${data_path} --nodename=${nodename} ${init_parameters} | tee -a ${log_file} if [ ${PIPESTATUS[0]} -ne 0 ] then die "[init primary datanode failed.]" else log "[init primary datanode success.]" fi } function config_db() { cd ${app_path}/bin if [ ! -e gs_guc ] then die "no gauss installation file is found in app-path. check the installation directory." fi cmd="./gs_guc set -D ${data_path} ${config_parameters} -c \"application_name='${applicationname}'\" " info "cmd : ${cmd}" eval ${cmd} | tee -a ${log_file} if [ ${PIPESTATUS[0]} -ne 0 ] then die "config datanode failed, pleae check whether the database is instantiated properly." fi listen_host_flag=$(echo ${config_parameters} | grep "listen_addresses") if [ "${listen_host_flag}" = "" ] then localhostscount=${#localhosts[*]} index=0 if [ ${localhostscount} -eq 0 ] then sed -i "/^#listen_addresses/c\listen_addresses = 'localhost,${localips[0]}'" ${data_path}/postgresql.conf log "sed -i /^#listen_addresses/c\listen_addresses = 'localhost,${localips[0]}' ${data_path}/postgresql.conf" else listen_addresses="" while [ ${index} -lt ${localhostscount} ] do listen_addresses="${listen_addresses}"",""${localhosts[${index}]}" index=$[ $index + 1 ] done sed -i "/^#listen_addresses/c\listen_addresses = 'localhost ${listen_addresses}'" ${data_path}/postgresql.conf log "sed -i /^#listen_addresses/c\listen_addresses = 'localhost ${listen_addresses}' ${data_path}/postgresql.conf" fi fi remote_read_mode_flag=$(echo ${config_parameters} | grep "remote_read_mode") if [ "${remote_read_mode_flag}" = "" ] then sed -i "/.*remote_read_mode = non_authentication/d" ${data_path}/postgresql.conf echo "remote_read_mode = non_authentication" | tee -a ${data_path}/postgresql.conf log "echo remote_read_mode = non_authentication | tee -a ${data_path}/postgresql.conf" fi mask_length=32 localhostscount=${#localhosts[*]} index=0 if [ ${localhostscount} -eq 0 ] then is_valid_ipv6 localips[0] if [ $? -eq 0 ] then mask_length=128 fi sed -i "/.*host\\s*all\\s*all\\s*${localips[0]}\/${mask_length}\\s*trust/d" ${data_path}/pg_hba.conf echo "host all all ${localips[0]}/${mask_length} trust" | tee -a ${data_path}/pg_hba.conf log "echo host all all ${localips[0]}/${mask_length} trust | tee -a ${data_path}/pg_hba.conf" else while [ ${index} -lt ${localhostscount} ] do is_valid_ipv6 ${localhosts[${index}]} if [ $? -eq 0 ] then mask_length=128 else mask_length=32 fi sed -i "/.*host\\s*all\\s*${user}\\s*${localhosts[${index}]}\/${mask_length}\\s*trust/d" ${data_path}/pg_hba.conf echo "host all ${user} ${localhosts[${index}]}/${mask_length} trust" | tee -a ${data_path}/pg_hba.conf log "echo host all ${user} ${localhosts[${index}]}/${mask_length} trust | tee -a ${data_path}/pg_hba.conf" index=$[ $index + 1 ] done fi if [ "${mode_type}" != "single" ] then remoteipcount=${#remoteips[*]} index=0 while [ ${index} -lt ${remoteipcount} ] do is_valid_ipv6 ${remoteips[${index}]} if [ $? -eq 0 ] then mask_length=128 else mask_length=32 fi sed -i "/.*host\\s*all\\s*${user}\\s*${remoteips[${index}]}\/${mask_length}\\s*trust/d" ${data_path}/pg_hba.conf echo "host all ${user} ${remoteips[${index}]}/${mask_length} trust" | tee -a ${data_path}/pg_hba.conf log "echo host all ${user} ${remoteips[${index}]}/${mask_length} trust | tee -a ${data_path}/pg_hba.conf" index=$[ $index + 1 ] done fi log "[config datanode success.]" } function guc_db() { cd ${app_path}/bin if [ ! -e gs_guc ] then die "no gauss installation file is found in app-path. check the installation directory." fi guc_config_parameters="" for line in $(cat ${guc_file} | sed '/^$/d') do guc_config_parameters="${guc_config_parameters}"" -c \"${line}\"" done cmd="./gs_guc set -D ${data_path} ${guc_config_parameters}" info "cmd : ${cmd}" eval ${cmd} | tee -a ${log_file} if [ ${PIPESTATUS[0]} -ne 0 ] then warn "guc config failed, you need to manually configure the GUC." else log "guc config success." fi } function cert_db() { cd ${app_path}/bin if [ ! -e gs_guc ] then die "no gauss installation file (gs_guc) is found in app-path, check whether OpenGauss has been properly installed in the installation directory." fi for filename in server.crt server.key cacert.pem server.key.cipher server.key.rand do if ! cp ${cert_path}/${filename} ${data_path} ; then die "copy ${cert_path}/${filename} to ${data_path} failed" fi done guc_config_parameters=" -c \"ssl=on\" -c \"ssl_ciphers='ALL'\" -c \"ssl_cert_file='server.crt'\" -c \"ssl_key_file='server.key'\" -c \"ssl_ca_file='cacert.pem'\" " cmd="./gs_guc set -D ${data_path} ${guc_config_parameters}" info "the command of guc config is : ${cmd}" eval ${cmd} | tee -a ${log_file} if [ ${PIPESTATUS[0]} -ne 0 ] then die "guc config failed, execute cmd ${cmd} failed." fi if [ "${client_ip}" != "" ] then is_valid_ipv4 "${client_ip}" if [ $? -ne 0 ] then is_valid_ipv6 "${client_ip}" if [ $? -ne 0 ] then die "the client ip address ${client_ip} is invalid." fi fi cmd="./gs_guc set -D ${data_path} \"-h hostssl all all ${client_ip}/32 cert\" " info "the command of setting client ip is : ${cmd}" eval ${cmd} | tee -a ${log_file} if [ ${PIPESTATUS[0]} -ne 0 ] then warn "failed to configure the client IP address." fi fi log "the ssl certificate of the database is configured successfully." } function start_db() { cd ${app_path}/bin if [ ! -e gs_ctl ] then die "no gauss installation file is found in app-path, check the installation directory." fi info "cmd: gs_ctl ${action} -D ${data_path} ${mode} | tee -a ${log_file}" ./gs_ctl ${action} -D ${data_path} ${mode} | tee -a ${log_file} if [ ${PIPESTATUS[0]} -ne 0 ] then die "start datanode failed, maybe the database not be properly installed. please refer to install.log for more detailed information." else log "start datanode success." sleep 5s eval "gs_ctl query -D ${data_path}" fi } while [ $# -gt 0 ] do case "$1" in -h|--help) usage exit 1 ;; -m|--mode) if [ "$2" = "" ] then die "the parameter '-m|--mode' cannot be empty." fi mode_type=$2 if [[ "${mode_type}" != "single" && "${mode_type}" != "primary" && "${mode_type}" != "standby" ]] then die "only three modes are supported: single、primary、and standby, default single" fi shift 2 ;; -n|--nodename) if [ "$2" = "" ] then die "the parameter '-n|--name' cannot be empty." fi security_check "$2" nodename=$2 shift 2 ;; -D|--data-path) if [ "$2" = "" ] then die "the parameter '-D|--data-path' cannot be empty." fi data_path=$2 if [ ${data_path:0:1} != "/" ] then data_path="$(pwd)/${data_path}" fi shift 2 ;; -R|--app-path) if [ "$2" = "" ] then die "the parameter '-R|--app-path' cannot be empty." fi app_path=$2 if [ ${app_path:0:1} != "/" ] then app_path="$(pwd)/${app_path}" fi shift 2 ;; -P|--gsinit-parameter) if [ "$2" = "" ] then die "the parameter '-P|--gsinit-parameter' cannot be empty." fi tmp_parameter=$(echo "$2" | sed "s#'##g" | sed 's#"##g') tmp_passwd_flag=$(echo "${tmp_parameter}" | grep -E "\-w\s+|\-\-pwpasswd=") if [ "${tmp_passwd_flag}" = "" ] then security_check "$2" fi check_init_paramters "$2" shift 2 ;; -l|--log-path) if [ "$2" = "" ] then die "the parameter '-l|--log-path' cannot be empty." fi log_path="$2" if [ ${log_path:0:1} != "/" ] then log_path="$(pwd)/${log_path}" fi shift 2 ;; -f|--guc-file) if [ "$2" = "" ] then die "the parameter '-f|--guc-file' cannot be empty." fi guc_file="$2" if [ ${guc_file:0:1} != "/" ] then guc_file="$(pwd)/${guc_file}" fi check_red_permission "${guc_file}" shift 2 ;; -C|--dn-guc) if [ "$2" = "" ] then die "the parameter '-C|--dn-guc' cannot be empty." fi security_check "$2" check_conf_paramters "$2" shift 2 ;; --env-sep-file) if [ "$2" = "" ] then die "the parameter '--env-sep-file' cannot be empty." fi env_file=$2 if [ ${env_file:0:1} != "/" ] then env_file="$(pwd)/${env_file}" fi shift 2 ;; --start) start=0 shift 1 ;; --ulimit) ulimit_flag=0 shift 1 ;; --cert-path) if [ "$2" = "" ] then die "the parameter '--cert-path' cannot be empty." fi cert_path=$2 if [ ${cert_path:0:1} != "/" ] then cert_path="$(pwd)/${cert_path}" fi shift 2 ;; --ssl-client-ip) if [ "$2" = "" ] then die "the parameter '--ssl-client-ip' cannot be empty." fi client_ip=$2 shift 2 ;; *) log "internal error: option processing error" 1>&2 log "please input right paramtenter, the following command may help you" log "sh install.sh --help or sh install.sh -h" exit 1 esac done function env_file_set() { if [ "${env_file}"X != ~/.bashrc"X" ] then if [ ! -e "${env_file}" ] then env_file_path=$(dirname ${env_file}) mkdir -p ${env_file_path} if [ $? -ne 0 ] then die "touch ${env_file} failed." fi touch "${env_file}" chmod 700 "${env_file}" if [ $? -ne 0 ] then die "an error occurred when assigning read/write/execute permission to the directory $1." fi fi check_red_permission "${env_file}" check_write_permission "${env_file}" check_execute_permission "${env_file}" sed -i "/.*export\\s*GAUSSENV=/d" "${env_file}" echo "export GAUSSENV=${env_file}" >> "${env_file}" fi } function app() { if [ "${app_path}" = "" ] then app_path=$(cat ${env_file} | grep -e ".*export\\s*GAUSSHOME="| awk -F "=" '{print $2}') fi if [ "${app_path}" != "" ] then check_path "${app_path}" "install" cd ${app_path} app_path=$(pwd | sed 's#[/][/]*#/#g') set_environment "${app_path}" "app" if [ ${install_path_full_flag} -eq 1 ] then decompress info "[begin decompressing binary files success.]" else info "[binary files already decompressed, pass.]" fi fi } function data() { if [ "${data_path}" = "" ] then data_path=$(cat ${env_file} | grep -e ".*export\\s*GAUSSDATA="| awk -F "=" '{print $2}') fi if [ "${data_path}" != "" ] then check_path "${data_path}" "data" cd ${data_path} data_path=$(pwd | sed 's#[/][/]*#/#g') set_environment "${data_path}" "data" fi } function cert() { if [ "${cert_path}" != "" ] then check_path "${cert_path}" "cert" if [ -z $(ls -A "${cert_path}" | grep server.crt) ] then die "no matching SSL certificate file(server.crt) is found. as a result, SSL may fail to be opened. Check ssl config carefully after the installation." else check_red_permission "${cert_path}/server.crt" fi if [ -z $(ls -A "${cert_path}" | grep server.key) ] then die "no matching SSL certificate file(server.key) is found. as a result, SSL may fail to be opened. Check ssl config carefully after the installation." fi if [ -z $(ls -A "${cert_path}" | grep cacert.pem) ] then die "no matching SSL certificate file(cacert.pem) is found. as a result, SSL may fail to be opened. Check ssl config carefully after the installation." fi fi } function log_file_set() { if [ "${log_path}" != "" ] then check_path "${log_path}" "log" cd ${log_path} log_path=$(pwd | sed 's#[/][/]*#/#g') data_contain_log_flag=$(echo ${data_path} | grep "${log_path}") if [ "${data_contain_log_flag}" != "" ] then die "log-path cannot be a subdirectory of data-path." fi set_environment ${log_path} log fi } function start() { if [ "${mode_type}" = "primary" ] then mode="-M primary" applicationname="master" elif [ "${mode_type}" = "standby" ] then mode="-b full" action="build" applicationname="slave" else mode="-Z single_node" applicationname="single" fi log "mode_type is ${mode_type} and mode is ${mode}, node name is ${nodename}" # check whether the app-path and data-path paths are contained. app_contain_data_flag=$(echo ${app_path} | grep "${data_path}") data_contain_app_flag=$(echo ${data_path} | grep "${app_path}") if [ "${app_contain_data_flag}" != "" ] then die "data-path cannot be a subdirectory of app-path." fi if [ "${data_contain_app_flag}" != "" ] then die "app-path cannot be a subdirectory of data-path." fi if [ ${data_full_flag} -ne 0 ] then if [ ${interactive_passwd_flag} -eq 1 ] then if [ "${password}" = "" ] then index=0 while [ "${password}" = "" ] do if [ ${index} -gt 2 ] then die "maximum number of retries exceeded" fi hide_password 0 echo -e "\n" hide_password 1 echo -e "\n" if [ "${password}" != "${password_check}" ] then info "the two passwords entered are inconsistent, please retry." index=$[ ${index} + 1 ] password="" continue fi check_passwd "${password}" if [ $? -ne 0 ] then die "install gaussdb failed, the password can contain only 8 to 32 characters and at least three types of the following characters: uppercase letters, lowercase letters, digits, and special characters." fi index=$[ ${index} + 1 ] done init_parameters="${init_parameters} -w ${password}" init_show_parameters="${init_show_parameters} ""-w ******" else check_passwd "${password}" if [ $? -ne 0 ] then die "install gaussdb failed, the password can contain only 8 to 32 characters and at least three types of the following characters: uppercase letters, lowercase letters, digits, and special characters." fi init_parameters="${init_parameters} -w ${password}" init_show_parameters="${init_show_parameters} ""-w ******" fi fi init_db data_full_flag=0 info "[install datanode success.]" fi if [ "${config_parameters}" != "" ] then config_db info "[config datanode success.]" fi if [ "$guc_file" = "" ] then if [ -e "${root_path}/opengauss_lite.conf" ] then guc_file="${root_path}/opengauss_lite.conf" fi fi if [ "${guc_file}" != "" ] then guc_db fi if [ "${cert_path}" != "" ] then cert_db fi if [ ${start} -eq 0 ] then start_db fi } function main() { check_os data if [ "${app_path}" != "" -a "${data_path}" != "" ] then if [ ${data_full_flag} -ne 0 ] then check fi fi env_file_set cert app log_file_set source ${env_file} if [ "${app_path}" != "" -a "${data_path}" != "" ] then start fi info "run cmd 'source ${env_file}' to make the environment variables take effect." } main exit 0