#!/bin/bash # Copyright: 2023 Virtuozzo International GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. [ -n "${OSLIB_VERSION:-}" ] && return 0; OSLIB_VERSION="0.1"; include math; inherit tests output net; __FALSE=1; __TRUE=0; __NEED_REBOOT=0; $PROGRAM 'service'; # workaround variables inside the envinfo.lib {{{ SERVICE_CMD="${SERVICE}"; declare +r SERVICE; # }}} $PROGRAM 'ps'; $PROGRAM 'chkconfig'; $PROGRAM 'ip'; $PROGRAM 'grep'; $PROGRAM 'sed'; _FD_STDIN=0; _FD_STDOUT=1; _FD_STDERR=2; __AUNITS=(b kb mb gb tb); # $1 - array to encode # example call: # funcname $(encodeArr arrayName); function encodeArr() { echo "$(base64 -w 0 <<< $(declare -p $1))"; } # $1 - base64 to decode # example call: # eval $(decodeArr $1 varname); function decodeArr() { echo "$(base64 -d -i <<< $1 | $SED -re "s/(^declare\s+-a\s)([^=]+)=(.*)/\1$2=\3/")"; } # $1 value # $2 from # $3 to function convertUnits() { local value=${1:-0} op ifrom=$(indexOf "${__AUNITS[*]}" $(${SED} -e 's/\(.*\)/\L\1/' <<< ${2})) ito=$(indexOf "${__AUNITS[*]}" $(${SED} -e 's/\(.*\)/\L\1/' <<< ${3})); local result=${value}; [[ ${ifrom} < ${ito} ]] && { op='/'; } || { op='*'; ifrom=$(( ${ifrom}-${ito} )); ito=$(( ${ito} + ${ifrom} )); ifrom=$(( ${ito} - ${ifrom} )); } while [ "${ifrom}" -lt "${ito}" ] ; do isFunction floatEval && result=$(floatEval "${result} ${op} 1024") || eval "result=$(( ${result} ${op} 1024 ))"; ifrom=$((${ifrom} + 1)); done echo ${result}; } function enableService() { local name=${1} level=${2:-3} doStart=${3:-${__TRUE}}; [[ ${doStart} == ${__TRUE} ]] && startService ${name}; ${CHKCONFIG} --level ${level} ${name} on; return ${?}; } # $1 - service name function startService() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} start; result=$?; sleep 1; return ${result}; } # $1 - service name function startServiceSilent() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} start >>$ACTIONS_LOG 2>&1; result=$?; sleep 1; return ${result}; } function stopService() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} stop; result=$?; sleep 1; return ${result}; }; # $1 - service name function stopServiceSilent() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} stop >>$ACTIONS_LOG 2>&1; result=$?; sleep 1; return ${result}; } function reloadService() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} reload; return ${?}; } function reloadServiceSilent() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} reload >>$ACTIONS_LOG 2>&1; return ${?}; } function restartServiceSilent() { local name=${1}; ${SUDO_COMMAND} ${SERVICE_CMD} ${name} restart >>$ACTIONS_LOG 2>&1; return ${?}; } # $1 - process name function getPID() { local procname=${1}; echo $(${PS} ax | ${GREP} ${procname} | ${GREP} -v grep | ${SED} -e 's/\([0-9]\+\).*/\1/'); } function getMemory() { local memtype=${1:-MemTotal} units=${2:-kb} result; result=$(${SED} -ne "/${memtype}:/{s/${memtype}:\s\+\([0-9]\+\).*/\1/i;p};h" /proc/meminfo ); echo $(convertUnits ${result} kb ${units} ); } # listFDs() # print list of opened file discriptors function listFDs() { local label=${1:-'Opened fds:'} local pid=${2:-$$} echo $(ls /proc/$$/fd | sort -n | awk 'BEGIN{printf("%s ", "'"${label}"'")} {printf("%s ", $1)}'); } # closeFD() # param: 1 - file descriptor to close function closeFD() { local fd=$1; eval "exec ${fd}>&-;exec ${fd}<&-"; } function editConfigProperty() { local file=${1} propertyName=${2} propertyValue=${3:-""}; [[ -a "${file}" ]] && ${GREP} -Pq '^${propertyName}\s*=.*' ${file} && { addProperty ${file} ${propertyName} ${propertyValue}; return $?; }; ${SED} -rie "s/(^${propertyName}\s*=\"?)([^\"]+)(\"?)$/\1${propertyValue}\3/" ${file}; return ${?}; } function addConfigProperty() { local file=${1} propertyName=${2} propertyValue=${3:-""}; [[ -a "${file}" ]] && ${GREP} -Pq '^${propertyName}\s*=.*' ${file} && { editProperty ${file} ${propertyName} ${propertyValue}; return $?; }; echo "${propertyName}=\"${propertyValue}\"" >> ${file}; return ${?}; } function getConfigProperty() { local file=${1} propertyName=${2}; echo $(${SED} -rne "/^${propertyName}\s*=/{s/^${propertyName}\s*=\"?([^\"]+)\"?/\1/;p};" ${file}); } function disableSelinux() { local file='/etc/sysconfig/selinux'; local state=$(getConfigProperty ${file} 'SELINUX'); [[ ${state} != 'disabled' ]] && editConfigProperty ${file} 'SELINUX' 'disabled' && editConfigProperty ${file} 'SELINUXTYPE' 'targeted' && __NEED_REBOOT=${__TRUE} return ${?}; } function enableSelinux() { local file='/etc/sysconfig/selinux'; local state=$(getConfigProperty ${file} 'SELINUX'); [[ ${state} == 'disabled' ]] && editConfigProperty ${file} 'SELINUX' 'permissive' && editConfigProperty ${file} 'SELINUXTYPE' 'targeted' && __NEED_REBOOT=${__TRUE}; return ${?}; } function needReboot() { return ${__NEED_REBOOT}; } function __getAddr() { : ${1:?"Missing param: interface"}; : ${2:?"Missing param: variable name"}; : ${3:-"-4"}; local dev=$1 name=$2 af=$3 alist; alist=$($IP $af addr show dev $dev 2>/dev/null | $SED -rne '/inet/{s/.*inet6* //;s/\/.*//;s/peer.*//;p}'); [ -z "$alist" ] && { eval "$name=''"; return 1; } eval "${name}_list=\"$alist\""; return $?; } function __getNet() { local dev=$1 name=$2 af=$3 alist; alist=$($IP route list dev $dev | $SED 's/ .*//;/default/d'); [ -z "$alist" ] && { eval "$name=''" return $?; } eval "${name}_list=\"$alist\""; return $?; } function getIfaceWild() { : ${1:?"Missing param: wildcard"}; local mask=$1; echo $($IP link show | $SED -rne "/^[0-9]+:\s+${mask}:/{s/.*:\s+(\S+):.*/\1/g;p}"); return $? } function getAddr() { __getAddr $1 $2 "-4"; } function getAddr6() { __getAddr $1 $2 "-6"; } function getNet() { __getNet $1 $2 "-4"; } function getNet6() { __getNet $1 $2 "-6"; } #function getNSAddr() { # echo $($SED -rne 's/nameserver\s+(.*)/\1/;/(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/p' /etc/resolv.conf); # return 0; #} #function getLocalNSAddr() { # local NS=($(getNSAddr)) locNS=(); # for i in ${NS[@]} ; do # isLANIP $i && locNS=(${locNS[@]} $i); # done; # [ -n "${locNS}" ] && { echo "${locNS[@]}" | $SED -re 's/\s+/\n/g' | uniq ; return 0; }; # return 1; #} function getHostIP() { : ${1:?"Missing param: hostname"}; echo $(host ${1} | $SED '/alias for/d' | $SED -re '/NXDOMAIN/d;s/.+\s+(([0-9]{1,3}\.){3}[0-9]{1,3})/\1/' | head -n 1); } function getOSVersion() { : ${1:?"Missing param: issue_string"} local issue_string=$1 local OS_version=$($GREP -h VERSION_ID <<< "$issue_string" 2>/dev/null | $SED -nre 's/.*=\"?([0-9.]*).*/\1/;p;n' | head -n 1) if [ -z "$OS_version" ] ; then OS_version=$($GREP -h DISTRIB_RELEASE <<< "$issue_string" 2>/dev/null | $SED -nre 's/.*=\s?\"?([0-9.]*).*/\1/;p;n' | head -n 1) if [ -z "$OS_version" ] ; then if $GREP -hqi "jessie" <<< "$issue_string" 2>/dev/null ; then OS_version="8" elif $GREP -hqi "stretch" <<< "$issue_string" 2>/dev/null ; then OS_version="9" elif $GREP -hqi "buster" <<< "$issue_string" 2>/dev/null ; then OS_version="10" fi if [ -z "$OS_version" ] ; then OS_version=$($GREP -m 1 -h "CentOS release" <<< "$issue_string" 2>/dev/null | $SED -nre 's/[a-zA-Z ]*\s([0-9.]*).*/\1/;p;n') fi if [ -z "$OS_version" ] ; then OS_version=$($GREP -m 1 -hP "Ubuntu|Debian" <<< "$issue_string" 2>/dev/null | $SED -nre 's/[a-zA-Z\/ ]*\s([0-9.]*).*/\1/;p;n') fi if [ -z "$OS_version" ] ; then OS_version=$($GREP -m 1 -h "Alpine" <<< "$issue_string" 2>/dev/null | $SED -nre 's/[a-zA-Z\/ ]*\s([0-9]*).*/\1/;p;n') $GREP -q "Alpine" <<< "$issue_string" && OS_version=3 fi if [ -z "$OS_version" ] ; then #Oracle Linux Server release 6.6 OS_version=$($GREP -m 1 -h "release" <<< "$issue_string" 2>/dev/null | $SED -nre 's/[a-zA-Z ]*\s([0-9.]*).*/\1/;p;n') fi fi fi echo $OS_version } function detectOS() { : ${1:?"Missing param: issue_string"}; local issue_string=$1 [ -z "$_OS" ] && $GREP -iq "almalinux" <<< $issue_string && _OS="almalinux" [ -z "$_OS" ] && $GREP -iq "vzlinux\|virtuozzo" <<< $issue_string && _OS="vzlinux" [ -z "$_OS" ] && $GREP -iq "kali" <<< $issue_string && _OS="kali" [ -z "$_OS" ] && $GREP -iq "ubuntu\|mint" <<< $issue_string && _OS="ubuntu" [ -z "$_OS" ] && $GREP -iq "debian" <<< $issue_string && _OS="debian" [ -z "$_OS" ] && $GREP -iq "centos\|rhel" <<< $issue_string && _OS="centos" [ -z "$_OS" ] && $GREP -iq "Oracle Linux Server" <<< $issue_string && _OS="centos" [ -z "$_OS" ] && $GREP -iq "fedora" <<< $issue_string && _OS="fedora" [ -z "$_OS" ] && $GREP -iq "redhat" <<< $issue_string && _OS="centos" [ -z "$_OS" ] && $GREP -iq "suse" <<< $issue_string && _OS="suse" [ -z "$_OS" ] && $GREP -iq "alpine" <<< $issue_string && _OS="alpine" echo $_OS } function installPackageCmd() { : ${1:?"Missing param: OS"}; local OS=$1; shift local pmaction=$1; shift local isCertified="" if [ ! -z "${1##*[!0-9]*}" ]; then isCertified=$1; shift fi local _apk_wait_timeout=${APK_WAIT_TIMEOUT:="10"} local proxy_env="export http_proxy=\"$(printenv http_proxy)\"; export https_proxy=\"$(printenv https_proxy)\"; export ftp_proxy=\"$(printenv ftp_proxy)\"; export no_proxy=\"$(printenv no_proxy)\""; for arg do PKGS="$arg $PKGS"; done case $OS in suse) PM="$proxy_env; zypper --quiet --non-interactive" ;; debian|ubuntu|kali) PM="$proxy_env; DEBIAN_FRONTEND=noninteractive apt-get -y --allow-unauthenticated -o Dpkg::Options::=\"--force-confold\"" ;; centos|redhat|fedora|vzlinux) PM="$proxy_env; yum -y" ;; almalinux) if [[ "$isCertified" -gt 0 ]]; then PM="$proxy_env; microdnf -y" else PM="$proxy_env; yum -y" fi ;; alpine) PM="$proxy_env; apk --wait $_apk_wait_timeout" case $pmaction in install) pmaction="add -f" ;; remove) pmaction="del -f" esac ;; esac echo "$PM $pmaction $PKGS" } function checkPackageCmd() { : ${1:?"Missing param: OS"}; local OS=$1; shift local _apk_wait_timeout=${APK_WAIT_TIMEOUT:="10"} local res="" case $OS in debian|ubuntu|kali) ltpl='dpkg -s %s >/dev/null 2>&1 || echo "%s" ;' ;; centos|redhat|fedora|suse|almalinux) ltpl='rpm -q %s >/dev/null 2>&1 || echo "%s" ;' ;; alpine) ltpl='p="%s";if apk | grep -q list ; then [ -n "$(apk --wait '$_apk_wait_timeout' list -I $p)" ] || echo $p ; else [ -z "$(apk --wait '$_apk_wait_timeout' version -q $p)" ] && echo %s; fi ;' ;; esac for arg do printf -v cmd "$ltpl" "$arg" "$arg" res="$res $cmd" done echo $res } function getExportedDirList() { [ ! -f "$1" ] && return 1 OIFS=$IFS;IFS=$'\n' adir=("${adir[@]}" $(sed -rne 's/^[ \t]*//' -e '/^#/d' -e '/^"/d' -e 's/([^ ]+)\s+.*/\1/' -e '/^$/d' -e p "$1")) adir=("${adir[@]}" $(sed -rne 's/^[ \t]*//' -e '/^#/d' -e '/^[^"]/d' -e 's/"(.*)"\s+.*/"\1"/' -e '/^$/d' -e p "$1")) IFS=$OIFS for a in "${adir[@]}"; do b="${a/#\"/}" b=${b/%\"/} echo "$b" done return 0 } function isShareExistsOnDisk() { [ -d "$1" ] } # $1 - share name # $2 - exports file function LookupShare() { [ ! -f "$2" ] && return 1 [[ "x${1:$((${#1}-1)):1}" == "x/" ]] && shareName=${1/%\//} || shareName=$1 dpath="^\"?($(sed -re 's/\//\\\//g' <<< $(sed -re 's/\^/\\^/g' -e 's/\$/\\$/g' -e 's/(\+\{|\}|\[|\]|\(|\))/\\\1/g' -e 's/\s/(\\\\040|\\s)/g' <<< "$shareName")))\/?\"?\s+"; [[ "$dpath" != "${dpath/\\\\040/}" ]] && brf="\3" || brf="\2" opts=() while read l ; do eval "$l"; opts=("${opts[@]}" $soptions) done <<< $(sed -re '/'$dpath'/!d' -e 's/'$dpath'(.*)/sname="\1";soptions="'$brf'"/' "$2") echo ${opts[*]} [[ ${#opts} -gt 0 ]] && return 0; } # $1 - share name # $2 - exports file # $3 - share prefix function isValidShare() { [ ! -f "$2" ] && return 1 if isContainerRunning ${CTID}; then vzctl exec2 ${CTID} "[ -d \"$1\" ]" || return 1; else isShareExistsOnDisk $3$1 || return 1; fi local opts=$(LookupShare "$1" "$2") [[ -z "$opts" ]] && return 1 return 0 } getRealExternalIp(){ local extip local services=( 'http://ifconfig.co' 'http://ifconfig.io' 'http://ipecho.net/plain' 'http://ipinfo.io/ip' ) for i in ${services[@]}; do extip=$(curl -4 -m 3 --connect-timeout 2 -Lkq --silent "$i") [[ ! -z "$extip" ]] && isValidIP "$extip" && { echo "$extip"; return 0; } done which dig &>/dev/null || yum -y install bind-utils &>>${JEM_CALLS_LOG} extip=$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | tr -d \") [[ ! -z "$extip" ]] && isValidIP "$extip" && { echo "$extip"; return 0; } { writeJSONResponseErr "result=>4212" "message=>Failed to get real external IP" ; return 99; } } getOutgoingIp(){ local EXTERNAL_IP=$(ip route get 1 | sed -nre 's/.*src\s(.*)\s/\1/p') [[ ! -z "$EXTERNAL_IP" ]] && isValidIP "$EXTERNAL_IP" && { echo "$EXTERNAL_IP"; return 0; } { writeJSONResponseErr "result=>4212" "message=>Failed to get external IP" ; return 99; } } detectFirewallBackend() { if [ -z "$DISTRIBUTION_NAME" ] ; then DISTRIBUTION_NAME=$(detectOS "$1") fi if [ -z "$DISTRIBUTION_VERSION" ] ; then DISTRIBUTION_VERSION=$(getOSVersion "$1") fi DISTRIBUTION_VERSION=${DISTRIBUTION_VERSION%%.*} if [ "x${DISTRIBUTION_NAME,,}" == "xalmalinux" -a "$DISTRIBUTION_VERSION" -ge 9 ] ; then echo "nftables" return 0 fi vzexecRun "which nft" if [ ! -z "$(vzexecGetLastStdOut)" ] ; then vzexecRun "nft list ruleset" if [ ! -z "$(vzexecGetLastStdOut)" ] ; then echo "nftables" return 0 fi fi echo "iptables" return 0 }