|
|
#!/usr/bin/env bash
|
|
|
#
|
|
|
# Author: Dmitry Razumov <asmeron@ublinux.com>
|
|
|
# Copyright (c) 2021-2025 UBLinux <support@ublinux.com>
|
|
|
#
|
|
|
# Initial script for Linux UBLinux
|
|
|
# This script are launching before starting init from initrd script
|
|
|
# Current dir allways must be set to root (/)
|
|
|
# All system path must be relative, except initrd dirs
|
|
|
|
|
|
ENABLED=yes
|
|
|
[[ ${ENABLED} == "yes" ]] || exit 0
|
|
|
DEBUGMODE=no
|
|
|
|
|
|
PATH=.:/:/usr/bin:/usr/local/bin:/usr/local/sbin
|
|
|
|
|
|
[[ -d /usr/lib/ublinux ]] && { ROOTFS= ; CMD_CHROOT= ; } || { [[ -d /sysroot ]] && ROOTFS="/sysroot" || ROOTFS="."; CMD_CHROOT="chroot ${ROOTFS}"; }
|
|
|
SOURCE=${ROOTFS}/usr/lib/ublinux/functions; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
|
|
|
SOURCE=${ROOTFS}/usr/lib/ublinux/default; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
|
|
|
debug_mode "$0" "$@"
|
|
|
|
|
|
SYSCONF="${ROOTFS}${SYSCONF}"
|
|
|
SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
|
|
|
SOURCE=${SYSCONF}/logging; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
|
|
|
|
|
|
## Настройка мониторинга и сбора системных событий и записи их в журналы для аудита
|
|
|
## AUDITD=disable|no|none|off<-># Отключить все созданные правила из конфигурации
|
|
|
## AUDITD[<id_name>[:<status>]]=<rule>[#<description>]
|
|
|
## <id_name> # Уникальное имя правила
|
|
|
## <status> # Статус правила, модет принимать значения: отсутствовать,enable,disable
|
|
|
## Отстутствует # Правило выключено или только комментарий
|
|
|
## enable # Правило включено
|
|
|
## disable # Правило выключено
|
|
|
## <rule> # Правило, без использование символа #
|
|
|
## <description> # Описание правила, начинается с символа #
|
|
|
#AUDITD[comment_1]="#Global settings"
|
|
|
#AUDITD[conf-d:enable]="-D #Remove any existing rules"
|
|
|
#AUDITD[conf-b:enable]="-b 8192 #Buffer Size. Feel free to increase this if the machine panic's"
|
|
|
#AUDITD[conf-f:enable]="-f 1 #Failure Mode. Possible values: 0 (silent), 1 (printk, print a failure message), 2 (panic, halt the system)"
|
|
|
#AUDITD[conf-i:disable]="-i #Ignore errors. e.g. caused by users or files not found in the local environment"
|
|
|
#AUDITD[comment_1221]="#Self Auditing ---------------------------------------------------------------------"
|
|
|
#AUDITD[comment_32423]="#Audit the audit logs"
|
|
|
#AUDITD[comment_23423]="#Successful and unsuccessful attempts to read information from the audit records"
|
|
|
#AUDITD[fs_auditlog_1]="-w /var/log/audit/ -p wra -k auditlog"
|
|
|
#AUDITD[fs_auditlog_2:disable]="-w /var/audit/ -p wra -k auditlog"
|
|
|
#AUDITD[event_chmod]="-a always,exit -F arch=x86_64 -S chmod,fchmod,fchmodat -F key=event_chmod"
|
|
|
#AUDITD[passwd_changes]="-w /etc/passwd -p wa -k passwd_changes"
|
|
|
exec_auditd(){
|
|
|
[[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift
|
|
|
[[ -n ${COMMAND} ]] || COMMAND="set="
|
|
|
local PARAM="$@"
|
|
|
local SERVICE_AUDITD="auditd.service"
|
|
|
local FILE_PATTERN_AUDITD_CONF="${ROOTFS}/etc/audit/rules.d/00-ubconfig.rules"
|
|
|
local SEPARATE_RULES_NAME_COMMENT=": "
|
|
|
local PREFIX_RULES_DISABLE="## "
|
|
|
if [[ ${AUDITD} == @(enable|yes|on) ]]; then
|
|
|
# Только для init
|
|
|
[[ -n ${ROOTFS} ]] && [[ -f ${ROOTFS}/lib/systemd/system/${SERVICE_AUDITD} ]] && [[ ! -e ${ROOTFS}/etc/systemd/system/multi-user.target.wants/${SERVICE_AUDITD} ]] \
|
|
|
&& ln -sf /usr/lib/systemd/system/${SERVICE_AUDITD} ${ROOTFS}/etc/systemd/system/multi-user.target.wants/${SERVICE_AUDITD}
|
|
|
elif [[ ${AUDITD} == @(disable|no|none|off) ]]; then
|
|
|
rm -f "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
[[ -n ${ROOTFS} ]] && [[ -e ${ROOTFS}/etc/systemd/system/multi-user.target.wants/${SERVICE_AUDITD} ]] && rm -f "${ROOTFS}/etc/systemd/system/multi-user.target.wants/${SERVICE_AUDITD}"
|
|
|
return 0
|
|
|
fi
|
|
|
[[ -d ${FILE_PATTERN_AUDITD_CONF%/*} ]] || mkdir -p ${FILE_PATTERN_AUDITD_CONF%/*}
|
|
|
[[ -f ${FILE_PATTERN_AUDITD_CONF} ]] || true > "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
if [[ -n ${PARAM} && ! ${PARAM} =~ ^"AUDITD="('enable'|'yes'|'on')?$ ]]; then
|
|
|
local SOURCE_AUDITD_RULES="${PARAM}"
|
|
|
elif [[ -n ${PARAM} && ${PARAM} =~ ^"AUDITD="('disable'|'no'|'none'|'off')?$ ]]; then
|
|
|
return 0
|
|
|
else
|
|
|
# Полное перезаполнение правил из конфигурации
|
|
|
SOURCE_AUDITD_RULES=$(grep -E "^[[:blank:]]*AUDITD\[" ${SYSCONF}/logging 2>/dev/null)
|
|
|
true > "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
fi
|
|
|
if [[ ${COMMAND} == @("set="|"set+="|"set++=") ]]; then
|
|
|
# т.к. важен порядок, то считываем последовательно из конфигурации
|
|
|
while IFS='=' read -u3 AUDITD_RULE_NAME AUDITD_RULE_VAR; do
|
|
|
[[ ${AUDITD_RULE_NAME} =~ ^[[:blank:]]*'AUDITD['([^:]+)':'?('enable'|'disable'|'yes'|'no'|'none'|'on'|'off')?']' ]] && AUDITD_RULE_NAME=${BASH_REMATCH[1]} && AUDITD_RULE_STATUS=${BASH_REMATCH[2]}
|
|
|
[[ ${AUDITD_RULE_NAME} == @("AUDITD"|"") ]] && return 0
|
|
|
[[ ${AUDITD_RULE_STATUS} == @(""|disable|no|none|off) ]] && AUDITD_RULE_STATUS="#" || AUDITD_RULE_STATUS=
|
|
|
[[ ${AUDITD_RULE_VAR} =~ ^[\"\']?([^#]*)'#'?([^\"]*)[\'\"]?$ ]] && AUDITD_RULE_VAR=${BASH_REMATCH[1]} && AUDITD_RULE_COMMENT=${BASH_REMATCH[2]}
|
|
|
[[ ${AUDITD_RULE_VAR} =~ ^[[:blank:]]*([^[:blank:]$]*)[[:blank:]]*$ ]] && AUDITD_RULE_VAR=${BASH_REMATCH[1]}
|
|
|
[[ -n ${AUDITD_RULE_COMMENT} ]] && echo "${PREFIX_RULES_DISABLE}${AUDITD_RULE_NAME}${SEPARATE_RULES_NAME_COMMENT}${AUDITD_RULE_COMMENT}" >> "${FILE_PATTERN_AUDITD_CONF}" \
|
|
|
|| echo "${PREFIX_RULES_DISABLE}${AUDITD_RULE_NAME}" >> "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
[[ -n ${AUDITD_RULE_VAR} ]] && echo "${AUDITD_RULE_STATUS}${AUDITD_RULE_VAR}" >> "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
done 3<<<${SOURCE_AUDITD_RULES}
|
|
|
elif [[ ${COMMAND} == @("set-="|"set--="|"remove") ]]; then
|
|
|
[[ -f ${FILE_PATTERN_AUDITD_CONF} ]] && while IFS='=' read -u3 AUDITD_RULE_NAME AUDITD_RULE_VAR; do
|
|
|
[[ ${AUDITD_RULE_NAME} =~ ^[[:blank:]]*'AUDITD['([^:]+)':'?('enable'|'disable'|'yes'|'no'|'none'|'on'|'off')?']' ]] && AUDITD_RULE_NAME=${BASH_REMATCH[1]} && AUDITD_RULE_STATUS=${BASH_REMATCH[2]}
|
|
|
# Уазан параметр не массив: AUDITD=
|
|
|
[[ ${AUDITD_RULE_NAME} == @("AUDITD"|"") ]] && return 0
|
|
|
[[ ${AUDITD_RULE_STATUS} == @(""|disable|no|none|off) ]] && AUDITD_RULE_STATUS="#" || AUDITD_RULE_STATUS=
|
|
|
[[ ${AUDITD_RULE_VAR} =~ ^[\"\']?([^#]*)'#'?([^\"]*)[\'\"]?$ ]] && AUDITD_RULE_VAR=${BASH_REMATCH[1]} && AUDITD_RULE_COMMENT=${BASH_REMATCH[2]}
|
|
|
[[ ${AUDITD_RULE_VAR} =~ ^[[:blank:]]*([^[:blank:]$]*)[[:blank:]]*$ ]] && AUDITD_RULE_VAR=${BASH_REMATCH[1]}
|
|
|
if [[ -n ${AUDITD_RULE_COMMENT} ]]; then
|
|
|
sed -E "/^$(ere_quote_sed "${PREFIX_RULES_DISABLE}${AUDITD_RULE_NAME}${SEPARATE_RULES_NAME_COMMENT}${AUDITD_RULE_COMMENT}")[[:blank:]]*$/d" -i "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
else
|
|
|
sed -E "/^$(ere_quote_sed "${PREFIX_RULES_DISABLE}${AUDITD_RULE_NAME}")[[:blank:]]*$/d" -i "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
fi
|
|
|
[[ -n ${AUDITD_RULE_VAR} ]] && sed -E "/^$(ere_quote_sed "${AUDITD_RULE_STATUS}${AUDITD_RULE_VAR}")[[:blank:]]*$/d" -i "${FILE_PATTERN_AUDITD_CONF}"
|
|
|
done 3<<<${SOURCE_AUDITD_RULES}
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
exec_auditd_live(){
|
|
|
[[ -z ${ROOTFS} ]] || return 0
|
|
|
local SERVICE_AUDIT_RULES="audit-rules.service"
|
|
|
local SERVICE_AUDITD="auditd.service"
|
|
|
if [[ -n ${AUDITD} ]]; then
|
|
|
# Если получен параметр AUDITD на включение или выключение, не массив, то
|
|
|
if [[ ${AUDITD} == @(enable|yes|on) ]]; then
|
|
|
if [[ $(pgrep -fc "exec_auditd_live") == 1 ]]; then
|
|
|
sleep 5
|
|
|
if systemctl --quiet is-active ${SERVICE_AUDITD} 2>/dev/null; then
|
|
|
systemctl --quiet reset-failed ${SERVICE_AUDITD} 2>/dev/null
|
|
|
systemctl --quiet restart ${SERVICE_AUDITD} 2>/dev/null
|
|
|
fi
|
|
|
ubconfig --quiet --target system set [system] SERVICES_ENABLE++="${SERVICE_AUDITD}"
|
|
|
fi
|
|
|
elif [[ ${AUDITD} == @(disable|no|none|off) ]]; then
|
|
|
pkill ${SERVICE_AUDITD%%.*}
|
|
|
ubconfig --quiet --target system set [system] SERVICES_ENABLE--="${SERVICE_AUDITD}" 2>/dev/null
|
|
|
fi
|
|
|
fi
|
|
|
return 0
|
|
|
}
|
|
|
|
|
|
## Настройка журналов
|
|
|
## https://www.freedesktop.org/software/systemd/man/journald.conf.html
|
|
|
## JOURNALD[<var>]=<value>
|
|
|
## <var> # Имя переменной настройки журнала
|
|
|
## Storage # Указывает, где хранить журнал. Доступны следующие параметры:
|
|
|
## # "volatile" - Журнал хранится в оперативной памяти, т.е. в каталоге /run/log/journal
|
|
|
## # "persistent" - Данные хранятся на диске, т.е. в каталоге /var/log/journal
|
|
|
## # "auto" - используется по-умолчанию
|
|
|
## # "none" - Журнал не ведётся
|
|
|
## Compress # Пороговое значение данных для сжатия и записи в ФС. Может принимать yes, no, цифра. Суффиксы, такие как K, M и G
|
|
|
## SplitMode # Определяет, следует ли разделять файлы журнала для каждого пользователя: «uid» или «none»
|
|
|
## RateLimitIntervalSec # Настраивает ограничение скорости, которое применяется ко всем сообщениям, интервал времени применения =30
|
|
|
## RateLimitBurst # Настраивает ограничение скорости, которое применяется ко всем сообщениям, лимит сообщений =10000
|
|
|
## SystemMaxUse # Указывает максимальное дисковое пространство, которое может использовать журнал в постоянном хранилище
|
|
|
## SystemKeepFree # Указывает объем места, которое журнал должен оставить свободным при добавлении записей журнала в постоянное хранилище
|
|
|
## SystemMaxFileSize # Определяет, до какого размера могут вырасти отдельные файлы журнала в постоянном хранилище перед ротацией
|
|
|
## RuntimeMaxUse # Указывает максимальное дисковое пространство, которое можно использовать в энергозависимом хранилище (в файловой системе /run)
|
|
|
## RuntimeKeepFree # Указывает объем пространства, которое будет выделено для других целей при записи данных в энергозависимое хранилище (в файловой системе /run)
|
|
|
## RuntimeMaxFileSize # Указывает объем места, которое отдельный файл журнала может занимать в энергозависимом хранилище (в файловой системе /run) перед ротацией
|
|
|
## ForwardToConsole # Перенаправить журнал на консоль, yes|no
|
|
|
## TTYPath # Измените используемый консольный TTY, если используется ForwardToConsole=yes. По умолчанию /dev/console.
|
|
|
## MaxLevelConsole # Тип сообщений перенаправляемые в журнал, варианты: emerg|alert|crit|err|warning|notice|info|debug или целочисленные значения в диапазоне 0–7
|
|
|
## <value> # Значение переменной настройки журнала
|
|
|
#JOURNALD[Storage]=persistent
|
|
|
#JOURNALD[Compress]=yes
|
|
|
#JOURNALD[SystemMaxUse]=8M
|
|
|
#JOURNALD[RuntimeMaxUse]=8M
|
|
|
exec_journald(){
|
|
|
[[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift
|
|
|
[[ -n ${COMMAND} ]] || COMMAND="set="
|
|
|
FILE_JOURNALD_CONF="${ROOTFS}/etc/systemd/journald.conf.d/00-ubconfig.conf"
|
|
|
local PARAM="$@"
|
|
|
if [[ -n ${PARAM} ]]; then
|
|
|
local JOURNALD=
|
|
|
declare -A JOURNALD=()
|
|
|
[[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}"
|
|
|
fi
|
|
|
[[ ! -f ${FILE_JOURNALD_CONF} ]] && mkdir -p "${FILE_JOURNALD_CONF%/*}" && touch ${FILE_JOURNALD_CONF}
|
|
|
[[ $(cat ${FILE_JOURNALD_CONF}) =~ "[Journal]" ]] || echo "[Journal]" > ${FILE_JOURNALD_CONF}
|
|
|
if [[ ${COMMAND} == @("set="|"set+="|"set++=") ]] && [[ ${#JOURNALD[@]} != 0 ]]; then
|
|
|
while IFS= read -u3 NAME_VAR; do
|
|
|
if [[ $(cat ${FILE_JOURNALD_CONF}) =~ "${NAME_VAR}=" ]]; then
|
|
|
sed "s/^${NAME_VAR}=.*/${NAME_VAR}=${JOURNALD[${NAME_VAR}]}/g" -i ${FILE_JOURNALD_CONF}
|
|
|
else
|
|
|
echo "${NAME_VAR}=${JOURNALD[${NAME_VAR}]}" >> ${FILE_JOURNALD_CONF}
|
|
|
fi
|
|
|
done 3< <(printf "%s\n" "${!JOURNALD[@]}")
|
|
|
elif [[ ${COMMAND} == @("set-="|"set--="|"remove") ]]; then
|
|
|
if [[ ${PARAM%%=*} =~ ^.*'['(.*)']' ]]; then
|
|
|
NAME_VAR=${BASH_REMATCH[1]}
|
|
|
sed "/${NAME_VAR}=/d" -i ${FILE_JOURNALD_CONF}
|
|
|
fi
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
exec_journald_live(){
|
|
|
[[ -z ${ROOTFS} ]] || return 0
|
|
|
SERVICE_NAME="systemd-journald.service"
|
|
|
if [[ $(pgrep -fc "exec_journald_live") == 1 ]]; then
|
|
|
sleep 5
|
|
|
systemctl reset-failed ${SERVICE_NAME} 2>/dev/null
|
|
|
systemctl --quiet restart ${SERVICE_NAME} 2>/dev/null
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
## Настройка дампа ядра
|
|
|
## https://www.freedesktop.org/software/systemd/man/latest/systemd-coredump.html
|
|
|
## SYSTEMD_COREDUMP[<var>]=<value>
|
|
|
## <var> # Имя переменной настройки журнала
|
|
|
## Storage # Указывает, где хранить дамп ядра. Доступны следующие параметры:
|
|
|
## journal # Дампы будут храниться в журнале и перезаписываться в соответствии со стандартными принципами ротации журналов
|
|
|
## external # Значение по умолчанию, дампы сохраняются в каталоге /var/lib/systemd/coredump/
|
|
|
## none # Дампы ядра записываются (включая обратную трассировку, если возможно), но не сохраняются
|
|
|
## Compress # Используется для сжатия дампов ядра. Принимает логический аргумент - *yes или no
|
|
|
## *yes # Дампы сжимаются при сохранении (значение по умолчанию)
|
|
|
## no # Дампы сохраняются без сжатия.
|
|
|
## ProcessSizeMax # Максимальный размер дампа процесса, который может быть сохранен. Если размер дампа превышает значение этого параметра, то дамп сохранен не будет. Суфиксы: B
|
|
|
## # Параметры Storage=none и ProcessSizeMax=0 отключает всю обработку дампа памяти, за исключением записи журнала
|
|
|
## ExternalSizeMax # Максимальный (сжатый или несжатый) размер дампа процесса, который будет сохранен на диске
|
|
|
## JournalSizeMax # Максимальный (сжатый или несжатый) размер дампа процесса, который будет сохранен в журнале системы
|
|
|
## MaxUse # Максимальный объем общего дискового пространства, который может быть использован для хранения дампов процессов. Суфиксы: B,K,M,G,T,P,E
|
|
|
## KeepFree # Минимальный объем свободного дискового пространства, который должен оставаться на диске при хранении дампов. Суфиксы: B,K,M,G,T,P,E
|
|
|
## <value> # Значение переменной настройки журнала
|
|
|
#SYSTEMD_COREDUMP[Storage]=none
|
|
|
#SYSTEMD_COREDUMP[ProcessSizeMax]=0
|
|
|
exec_systemd_coredump(){
|
|
|
[[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift
|
|
|
[[ -n ${COMMAND} ]] || COMMAND="set="
|
|
|
FILE_SYSTEMD_COREDUMP_CONF="${ROOTFS}/etc/systemd/coredump.conf.d/00-ubconfig.conf"
|
|
|
local PARAM="$@"
|
|
|
if [[ -n ${PARAM} ]]; then
|
|
|
local SYSTEMD_COREDUMP=
|
|
|
declare -A SYSTEMD_COREDUMP=()
|
|
|
[[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}"
|
|
|
fi
|
|
|
[[ ! -f ${FILE_SYSTEMD_COREDUMP_CONF} ]] && mkdir -p "${FILE_SYSTEMD_COREDUMP_CONF%/*}" && touch ${FILE_SYSTEMD_COREDUMP_CONF}
|
|
|
[[ $(cat ${FILE_SYSTEMD_COREDUMP_CONF}) =~ "[Coredump]" ]] || echo "[Coredump]" > ${FILE_SYSTEMD_COREDUMP_CONF}
|
|
|
if [[ ${COMMAND} == @("set="|"set+="|"set++=") ]] && [[ ${#SYSTEMD_COREDUMP[@]} != 0 ]]; then
|
|
|
while IFS= read -u3 NAME_VAR; do
|
|
|
if [[ $(cat ${FILE_SYSTEMD_COREDUMP_CONF}) =~ "${NAME_VAR}=" ]]; then
|
|
|
sed "s/^${NAME_VAR}=.*/${NAME_VAR}=${SYSTEMD_COREDUMP[${NAME_VAR}]}/g" -i ${FILE_SYSTEMD_COREDUMP_CONF}
|
|
|
else
|
|
|
echo "${NAME_VAR}=${SYSTEMD_COREDUMP[${NAME_VAR}]}" >> ${FILE_SYSTEMD_COREDUMP_CONF}
|
|
|
fi
|
|
|
done 3< <(printf "%s\n" "${!SYSTEMD_COREDUMP[@]}")
|
|
|
elif [[ ${COMMAND} == @("set-="|"set--="|"remove") ]]; then
|
|
|
if [[ ${PARAM%%=*} =~ ^.*'['(.*)']' ]]; then
|
|
|
NAME_VAR=${BASH_REMATCH[1]}
|
|
|
sed "/${NAME_VAR}=/d" -i ${FILE_SYSTEMD_COREDUMP_CONF}
|
|
|
fi
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
## Настройка ротации файлов логов утилитой logrotate
|
|
|
## https://man.archlinux.org/man/logrotate.conf.5
|
|
|
## LOGROTATE[<tag>]="<mask_file_1>,<mask_file_2>,<mask_file_n>:<setting_1>,<setting_2>,<setting_n>"
|
|
|
#LOGROTATE[samba]="/var/log/samba/log.smbd,/var/log/samba/log.nmbd,/var/log/samba/*.log:notifempty,missingok,copytruncate"
|
|
|
#LOGROTATE[chrony]="/var/log/chrony/*.log:missingok,nocreate,sharedscripts,postrotate,/usr/bin/chronyc cyclelogs > /dev/null 2>&1 || true,endscript"
|
|
|
#LOGROTATE[clamav]="/var/log/clamav/clamd.log,/var/log/clamav/freshclam.log,/var/log/clamav/clamav-milter.log:create 644 clamav clamav,sharedscripts,missingok,notifempty,postrotate,/bin/kill -HUP \`cat /run/clamav/clamd.pid 2>/dev/null\` 2> /dev/null || true,/bin/kill -HUP \`cat /run/clamav/freshclam.pid 2>/dev/null\` 2> /dev/null || true,/bin/kill -HUP \`cat /run/clamav/clamav-milter.pid 2>/dev/null\` 2> /dev/null || true,endscript"
|
|
|
exec_logrotate(){
|
|
|
[[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift
|
|
|
[[ -n ${COMMAND} ]] || COMMAND="set="
|
|
|
FILE_PATTERN_LOGROTATE_CONF="${ROOTFS}/etc/logrotate.d/ubconfig-"
|
|
|
local PARAM="$@"
|
|
|
if [[ -n ${PARAM} ]]; then
|
|
|
local LOGROTATE=
|
|
|
declare -A LOGROTATE=()
|
|
|
[[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}"
|
|
|
fi
|
|
|
[[ -d ${FILE_PATTERN_LOGROTATE_CONF%/*} ]] || mkdir -p ${PATH_LOGROTATE_CONF%/*}
|
|
|
if [[ ${COMMAND} == "set=" ]] && [[ ${#LOGROTATE[@]} != 0 ]]; then
|
|
|
while IFS= read -u3 NAME_FILE; do
|
|
|
FILES_LOG="${LOGROTATE[${NAME_FILE}]%%:*}"; FILES_LOG="${FILES_LOG//,/ }"
|
|
|
RULES_LOG="${LOGROTATE[${NAME_FILE}]#*:}"
|
|
|
TAB_COUNT='\t'
|
|
|
# Вставляем список файлов логов
|
|
|
echo "${FILES_LOG} {" > "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
# Вставляем правила для вращения логов
|
|
|
while IFS= read -r SELECT_RULES_LOG; do
|
|
|
[[ ${SELECT_RULES_LOG} == "endscript" ]] && TAB_COUNT='\t'
|
|
|
echo -e "${TAB_COUNT}${SELECT_RULES_LOG}" >> "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
[[ ${SELECT_RULES_LOG} == "postrotate" ]] && TAB_COUNT='\t\t'
|
|
|
done < <(tr ',' '\n' <<< ${RULES_LOG})
|
|
|
echo "}" >> "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
done 3< <(printf "%s\n" "${!LOGROTATE[@]}")
|
|
|
elif [[ ${COMMAND} == @("set+="|"set++=") ]] && [[ ${#LOGROTATE[@]} != 0 ]]; then
|
|
|
while IFS= read -u3 NAME_FILE; do
|
|
|
[[ -f ${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE} ]] || return 0
|
|
|
FILES_LOG="${LOGROTATE[${NAME_FILE}]%%:*}"
|
|
|
RULES_LOG="${LOGROTATE[${NAME_FILE}]#*:}"
|
|
|
[[ ${FILES_LOG} == ${RULES_LOG} ]] && unset RULES_LOG
|
|
|
FILES_LOG="${FILES_LOG//,/ }"
|
|
|
# Вставить в список файлов последним
|
|
|
[[ -n ${FILES_LOG} ]] && ESC_FILES_LOG=$(sed 's/[^a-zA-Z0-9=",_@#%&<> -]/\\&/g' <<< "${FILES_LOG}")
|
|
|
[[ -n ${FILES_LOG} ]] && [[ ! $(cat "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}") =~ ${FILES_LOG} ]] \
|
|
|
&& sed -E "0,/ \{/s/ \{/ ${ESC_FILES_LOG} \{/" -i "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
# Вставить в список правил последним
|
|
|
[[ -n ${RULES_LOG} ]] && ESC_RULES_LOG=$(sed 's/[^a-zA-Z0-9=",_@#%&<> -]/\\&/g' <<< "${RULES_LOG}")
|
|
|
[[ -n ${RULES_LOG} ]] && [[ ! $(cat "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}") =~ ${RULES_LOG} ]] \
|
|
|
&& sed -E "/^\}$/i\\\t${ESC_RULES_LOG}" -i "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
done 3< <(printf "%s\n" "${!LOGROTATE[@]}")
|
|
|
elif [[ ${COMMAND} == @("set-="|"set--=") ]]; then
|
|
|
while IFS= read -u3 NAME_FILE; do
|
|
|
FILES_LOG="${LOGROTATE[${NAME_FILE}]%%:*}"
|
|
|
RULES_LOG="${LOGROTATE[${NAME_FILE}]#*:}"
|
|
|
[[ ${FILES_LOG} == ${RULES_LOG} ]] && unset RULES_LOG
|
|
|
FILES_LOG="${FILES_LOG//,/ }"
|
|
|
# Если удаляемая часть относится к файлу, то просто вырезать, если к тексту, то удалить строку
|
|
|
[[ -n ${FILES_LOG} ]] && ESC_FILES_LOG=$(sed 's/[^a-zA-Z0-9=",_@#%&<> -]/\\&/g' <<< "${FILES_LOG}")
|
|
|
[[ -n ${FILES_LOG} ]] && [[ $(cat "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}") =~ ${FILES_LOG} ]] \
|
|
|
&& sed -E "0,/ \{/s/${ESC_FILES_LOG}//" -i "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
[[ -n ${RULES_LOG} ]] && ESC_RULES_LOG=$(sed 's/[^a-zA-Z0-9=",_@#%&<> -]/\\&/g' <<< "${RULES_LOG}")
|
|
|
[[ -n ${RULES_LOG} ]] && [[ $(cat "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}") =~ ${RULES_LOG} ]] \
|
|
|
&& sed "/${ESC_RULES_LOG}/d" -i "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
done 3< <(printf "%s\n" "${!LOGROTATE[@]}")
|
|
|
elif [[ ${COMMAND} == "remove" ]]; then
|
|
|
while IFS= read -u3 NAME_FILE; do
|
|
|
[[ -f ${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE} ]] || return 0
|
|
|
rm -f "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
done 3< <(printf "%s\n" "${!LOGROTATE[@]}")
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
# Применить ротцию принудительно на указанный файл
|
|
|
# $1 # Имя переменной с файлом, пример: LOGROTATE[clamav]
|
|
|
exec_logrotate_live(){
|
|
|
[[ -z ${ROOTFS} ]] || return 0
|
|
|
NAME_FILE=$1
|
|
|
[[ ${NAME_FILE%%=*} =~ ^.*'['(.*)']' ]] && NAME_FILE=${BASH_REMATCH[1]}
|
|
|
[[ -n ${NAME_FILE} ]] || return 0
|
|
|
FILE_PATTERN_LOGROTATE_CONF="${ROOTFS}/etc/logrotate.d/ubconfig-"
|
|
|
if [[ $(pgrep -fc "exec_logrotate_live") == 1 ]]; then
|
|
|
sleep 2
|
|
|
logrotate -f "${FILE_PATTERN_LOGROTATE_CONF}${NAME_FILE}"
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
################
|
|
|
##### MAIN #####
|
|
|
################
|
|
|
|
|
|
# Если файл подключен как ресурс с функциями, то выйти
|
|
|
return 0 2>/dev/null && return 0
|
|
|
if [[ -z $@ ]]; then
|
|
|
while read -r FUNCTION; do
|
|
|
$"${FUNCTION##* }"
|
|
|
done < <(declare -F | grep "declare -f exec_")
|
|
|
else
|
|
|
FUNCTION=
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
[[ -z ${1} ]] || { declare -f "${1}" &>/dev/null && FUNCTION+="; ${1}" || FUNCTION+=" '${1//\'/}'"; }
|
|
|
shift
|
|
|
done
|
|
|
eval ${FUNCTION#*; }
|
|
|
fi
|