#!/usr/bin/env bash # # Author: Dmitry Razumov # Copyright (c) 2021-2025 UBLinux # # Extended pattern matching: https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching shopt -s extglob ENABLED=yes [[ ${ENABLED} == "yes" ]] || exit 0 DEBUGMODE=no unset ROOTFS; [[ -d /usr/lib/ublinux ]] || 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}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null ## Синхронизация пользователей системы /etc/passwd и их параметры /etc/shadow с глобальной конфигурацией ## USERADD_SYNC='boot,shutdown,shutdown@all,shutdown@users,shutdown@systems,shutdown@-,shutdown@' ## boot # При загрузке системы принудительно применить глобальную конфигурацию на пользователя ## shutdown # Аналогичен shutdown@users + shutdown@systems ## shutdown@all # При завершении работы системы синхронизировать всех пользователей в системе с глобальной конфигурацией ## shutdown@users # При завершении работы системы синхронизировать пользователей 1000<=UID<=6000 в системе с глобальной конфигурацией ## shutdown@systems # При завершении работы системы синхронизировать системных пользователей 500<=UID<=999 в системе с глобальной конфигурацией ## shutdown@- # При завершении работы системы синхронизировать диапазон UID пользователей в системе с глобальной конфигурацией ## shutdown@ # При завершении работы системы синхронизировать UID пользователя в системе с глобальной конфигурацией ## USERADD_SYNC=boot,shutdown ## ## USERADD_SYNC[]='boot,shutdown' ## # Имя пользователя, необязательное поле. Если не указано, то применяется для всех пользователей ## boot # При загрузке системы принудительно применить глобальную конфигурацию на пользователя ## shutdown # При завершении работы системы синхронизировать указанного пользователя в системе с глобальной конфигурацией ## USERADD_SYNC[superadmin]=boot,shutdown exec_useradd_sync(){ remove_ubconfig(){ # Удалить пользователей из глобальной конфигурации local PARAM="$1" local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs" if [[ ${PARAM} == '@all' ]]; then # Удалить всех пользователей из глобальной конфигурации ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[*] USERSHADOW[*] elif [[ ${PARAM} == '@users' ]]; then # Удалить пользователей 1000<=UID<=6000 из глобальной конфигурации # Все пользователи кроме системных local UID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MIN[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}") local UID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MAX[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}") [[ -n ${!USERADD[@]} ]] && while IFS= read -u3 SELECT_USER; do IFS=':' read -u4 SELECT_GECOS SELECT_UID NULL 4<<< ${USERADD[${SELECT_USER}]} if [[ ${SELECT_UID} == @(""|"x"|"X") ]] || [[ ${SELECT_UID} -ge ${UID_MIN} && ${SELECT_UID} -le ${UID_MAX} ]]; then ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[${SELECT_USER}] USERSHADOW[${SELECT_USER}] fi done 3< <(printf "%s\n" "${!USERADD[@]}") elif [[ ${PARAM} == '@systems' ]]; then # Удалить пользователей 500<=UID<=999 из глобальной конфигурации # Пользователи системные local UID_MIN_SYS=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MIN[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}") local UID_MAX_SYS=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MAX[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}") [[ -n ${!USERADD[@]} ]] && while IFS= read -u3 SELECT_USER; do IFS=':' read -u4 SELECT_GECOS SELECT_UID NULL 4<<< ${USERADD[${SELECT_USER}]} if [[ ${SELECT_UID} != @(""|"x"|"X") && ${SELECT_UID} -ge ${UID_MIN_SYS} && ${SELECT_UID} -le ${UID_MAX_SYS} ]]; then ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[${SELECT_USER}] USERSHADOW[${SELECT_USER}] fi done 3< <(printf "%s\n" "${!USERADD[@]}") elif [[ ${PARAM} =~ ^([[:digit:]]+)'-'*([[:digit:]]*)$ ]]; then # Удалить пользователей X<=UID<=Y из глобальной конфигурации local UID_MIN=${BASH_REMATCH[1]} local UID_MAX=${BASH_REMATCH[2]} [[ -n ${UID_MAX} ]] || UID_MAX=${UID_MIN} [[ -n ${!USERADD[@]} ]] && while IFS= read -u3 SELECT_USER; do IFS=':' read -u4 SELECT_GECOS SELECT_UID NULL 4<<< ${USERADD[${SELECT_USER}]} if [[ ${SELECT_UID} != @(""|"x"|"X") && ${SELECT_UID} -ge ${UID_MIN} && ${SELECT_UID} -le ${UID_MAX} ]]; then ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[${SELECT_USER}] USERSHADOW[${SELECT_USER}] fi done 3< <(printf "%s\n" "${!USERADD[@]}") else # Входящий параметр - имя пользователя ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] USERADD[${PARAM}] USERSHADOW[${PARAM}] fi } set_ubconfig(){ local PARAM="$1" local GET_USERADD=$(get_conf_useradd_from_system "${PARAM}") if [[ ${GET_USERADD} != "" ]]; then eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] ${GET_USERADD} local GET_USERSHADOW=$(get_conf_usershadow_from_system ${PARAM}) # TODO: Если задан диапазон пользователей, пример 0-999, то GET_USERSHADOW будет содержать всех пользователей в этом диапазоте # А нужно выбрать только пользователей которые содержатся в GET_USERADD if [[ ${GET_USERSHADOW} != "" ]]; then eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] ${GET_USERSHADOW} fi fi } [[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift [[ -n ${COMMAND} ]] || COMMAND="set=" local PARAM="$@" if [[ -n ${PARAM} ]]; then local USERADD_SYNC= declare -A USERADD_SYNC=() [[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}" fi while IFS= read -u3 SELECT_USERADD_SYNC; do if [[ ${SELECT_USERADD_SYNC} == 'shutdown@all' ]]; then remove_ubconfig "@all" set_ubconfig "@all" elif [[ ${SELECT_USERADD_SYNC} == 'shutdown@users' ]]; then remove_ubconfig "@users" set_ubconfig "@users" elif [[ ${SELECT_USERADD_SYNC} == 'shutdown@systems' ]]; then remove_ubconfig "@systems" set_ubconfig "@systems" elif [[ ${SELECT_USERADD_SYNC} == 'shutdown' ]]; then remove_ubconfig "@users" remove_ubconfig "@systems" set_ubconfig elif [[ ${SELECT_USERADD_SYNC} =~ ^'shutdown@'(([[:digit:]]+)'-'*([[:digit:]]*))$ ]]; then local LIST_USERS="${BASH_REMATCH[1]}" remove_ubconfig "${LIST_USERS}" set_ubconfig "${LIST_USERS}" fi done 3<<< "${USERADD_SYNC//@(,|;)/$'\n'}" if [[ "$(declare -p USERADD_SYNC 2>/dev/null)" == "declare -A"* ]]; then [[ -n ${!USERADD_SYNC[@]} ]] && while IFS= read -u3 SELECT_USER; do # В массиве 0 запись игнорируем, т.к. это параметр не ассоциативного массива if [[ ${SELECT_USER} != 0 && ${USERADD_SYNC[${SELECT_USER}]} =~ 'shutdown' ]]; then remove_ubconfig "${SELECT_USER}" set_ubconfig "${SELECT_USER}" fi done 3< <(printf "%s\n" "${!USERADD_SYNC[@]}") fi } ## Синхронизация группы системы /etc/groups и их параметры /etc/gshadow с глобальной конфигурацией ## GROUPADD_SYNC='shutdown,shutdown@all,shutdown@users,shutdown@systems,shutdown@-,shutdown@' ## shutdown # Аналогичен shutdown@users + shutdown@systems ## shutdown@all # При завершении работы системы синхронизировать все группы в системе с глобальной конфигурацией ## shutdown@groups # При завершении работы системы синхронизировать группы 1000<=GID<=6000 в системе с глобальной конфигурацией ## shutdown@systems # При завершении работы системы синхронизировать системные группы 500<=GID<=999 в системе с глобальной конфигурацией ## shutdown@- # При завершении работы системы синхронизировать диапазон GID групп в системе с глобальной конфигурацией ## shutdown@ # При завершении работы системы синхронизировать GID группы в системе с глобальной конфигурацией ## GROUPADD_SYNC=shutdown ## ## GROUPADD_SYNC[group_name]='shutdown' ## group_name # Имя группы, необязательное поле. Если не указано, то применяется для всех групп ## shutdown # При завершении работы системы синхронизировать указанную группу в системе с глобальной конфигурацией ## GROUPADD_SYNC[users]='shutdown' exec_groupadd_sync(){ set_ubconfig(){ local PARAM="$1" local GET_GROUPADD=$(get_conf_groupadd_from_system "${PARAM}") if [[ ${GET_GROUPADD} != "" ]]; then eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] ${GET_GROUPADD} eval ${ROOTFS}/usr/bin/ubconfig --quiet --target global set [users] ${GET_GROUPADD} fi } [[ $1 == @("set="|"set+="|"set++="|"set-="|"set--="|"remove") ]] && COMMAND=$1 && shift [[ -n ${COMMAND} ]] || COMMAND="set=" local PARAM="$@" if [[ -n ${PARAM} ]]; then local GROUPADD_SYNC= declare -A GROUPADD_SYNC=() [[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}" fi # Если синхронизируем группы по шаблону, то удалим все группы из глобальной конфигурации if [[ ${USERADD_SYNC} =~ 'shutdown' ]]; then ${ROOTFS}/usr/bin/ubconfig --quiet --target global remove [users] GROUPADD[*] fi while IFS= read -u3 SELECT_GROUPADD_SYNC; do if [[ ${SELECT_GROUPADD_SYNC} == 'shutdown@all' ]]; then set_ubconfig "@all" elif [[ ${SELECT_GROUPADD_SYNC} == 'shutdown@groups' ]]; then set_ubconfig "@groups" elif [[ ${SELECT_GROUPADD_SYNC} == 'shutdown@systems' ]]; then set_ubconfig "@systems" elif [[ ${SELECT_GROUPADD_SYNC} =~ ^'shutdown@'(([[:digit:]]+)'-'*([[:digit:]]*))$ ]]; then set_ubconfig "${BASH_REMATCH[1]}" elif [[ ${SELECT_GROUPADD_SYNC} == 'shutdown' ]]; then set_ubconfig fi done 3<<< "${GROUPADD_SYNC//@(,|;)/$'\n'}" if [[ "$(declare -p GROUPADD_SYNC 2>/dev/null)" == "declare -A"* ]]; then while IFS= read -u3 SELECT_GROUP; do # В массиве 0 запись игнорируем, т.к. это параметр не ассоциативного массива if [[ ${SELECT_GROUP} != 0 && ${GROUPADD_SYNC[${SELECT_GROUP}]} =~ 'shutdown' ]]; then set_ubconfig "${SELECT_GROUP}" fi done 3< <(printf "%s\n" "${!GROUPADD_SYNC[@]}") 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