пятница, 20 января 2017 г.

BASH: Скрипт автоматизированной архивации каталогов баз данных 1С через samba


Думаю многим Администраторам приходится решать задачи по автоматизации различных архивов баз данных или прочих "данных" и данный скрипт поможет упростить по крайней какую то часть рутины. Собственно скрипт писался для копирования и архивации баз данных 1C с сервера Windows на сервере Linux, для дальнейшего использования программистами уже из архива. Скрипт делает архив каждый день, каждую неделю и удаляет ежедневные, каждый месяц - удаляет дневные и недельные. Есть возможность принудительно вызывать как недельную так и месячную архивацию. Все параметры с комментариями задаются в начале скрипта. В работе скрипт подключается к сетевому диску Windows/Linux через службу samba копирует указанные каталоги во временный каталог, после чего сжимает их с указанными именами архивов (привязаны к именам каталогов баз) с добавлением текущей даты архивации.
В скрипте есть параметр "входа" - это если после подключения сетевого диска необходимо еще и зайти в какой то специальный каталог и только потом можно копировать каталог базы. Такое например бывает если место расположения баз различное как по ресурсам так и по путям "входа".
Ниже код скрипта на языке Bash.
_________________________________________________________________________________
#!/bin/bash
## It is a system script for 1c database backups 
## author (c) by koshuba v.o. - open technologies
## licence MIT 2016
export LANG=ru_RU.UTF-8
## 
option=$1
rdate=$(date +%c);
arh_date=$(date +%d_%m_%y);
log_arh="/var/log/syslog";

## values read devices & index array values

host_smb="10.10.10.4";                                           #: хост подключения
login_smb=( '"Администратор" "mypass"' );            #: логин и пароль к ресурсу
name_db=( "Base1" "Base2" "Base3" "Base4" );             #: имена каталогов баз данных
name_arh=( "base1_" "base2_" "base3_" "base4_" );     #: имена суточных архивов + дата на момент архивации
path_mnt="/mnt/read_smb";                                    #: директория для монтирования ресурса
path_main_arh="/arhbase";                                     #: основной каталог архивов
path_arh=( "day" "week" "month" );                        #: отдельные каталоги суточных, недельных и месячных архивов
path_tmp="/home/temp";                                          #: временная папка для архивации баз
path_in_cd=( "" );                                                      #: путь входа для копирования
policy=( "user:sambashare" )                                   #: права на архивы


## values for db arhives

read_smb=( "E$"  "$F");       #: ресурс где находятся базы данных - индексы ниже привязаны к нему
## <>
link_db=( '"0" "1"'  '"2" "3"' );                                                #: индексы имен каталогов с базами
link_arh=( '"0" "1"'  '"2" "3"' );                                               #: индексы имен архивов для сжатия
link_policy=( '"0" "0"'  '"0" "0"' )                                            #: индексы права на архивы
link_in_cd=( '"0" "0"'  '"0" "0"' )                                             #: индексы входа в каталог баз
link_login_smb=( '"0" "0"'  '"0" "0"' );                                    #: индексы логин и пароль к ресурсу                                          
                                                                                                                                                             
## tmp                                                                                                                                                       
tmp_smb="";                                                           #: текущий share для чтения                        
tmp_db=();                                                               #: текущий список каталогов баз                  
tmp_login=();                                                           #: текущий логин к ресурсу                           
tmp_nmdb=();                                                          #: текущий список имен архивов                 
tmp_pl=();                                                                #: текущие политики                                      
tmp_in_cd=();                                                          #: текущий каталог входа к базам                                             
                                                                                                                                                             
## defaults                                                                                                                                                 
reports=();                                                                #: массив для сообщений                               
event_type="";                       #: тип события для выполнения операции, за день, за неделю и.т.д.            
                                                                                                                                                             
## functions & operations                                                                                                                                    
## develop mode ...                                                                                                                                          
operation_day=( "checkLock" "mountSmb" "arhDb" "umountSmb" "lockOff" );                                        
operation_week=( "checkLock" "mountSmb" "arhDb" "umountSmb" "clearArh" "lockOff" );                    
operation_month=( "checkLock" "mountSmb" "arhDb" "umountSmb" "clearArh" "lockOff" );                   
operation_help=( "printInfo" );                                                                                                                    
execute_func=();                                                                                                                                             
## logic executor values
iFs=();
logic=();
value_in="";
lEnd=1;

##..............................................................................

## -@F logic executor
function eXlogic() {
lEnd=1;
if [[ ${#iFs[@]} -eq 0 ]]||[[ ${#iFs[@]} != ${#logic[@]} ]]
    then echo "exit";
         exit 0;
fi

local exfunc=();

for ((lg_index=0; lg_index != ${#iFs[@]}; lg_index++))
 do
    ## !! debug operation...
    ## echo "eXlogic = execution: function ${iFs[$lg_index]} : index=$lg_index";
    local lg=$(echo $((${iFs[$lg_index]})) );
    local exfunc=( ${logic[$lg_index]} );
    local runfunc=$(echo ${exfunc[$lg]}| sed 's/\"//g');
    $runfunc;
    if [[ $lEnd == 0 ]] 
        then lg_index=$((${#iFs[@]}-1)); 
    fi
done
iFs=();
logic=();
value_in="";
}

##..............................................................................

## -@F function check lock file
function checkLock() {
if [ ! -f /tmp/run-arh.lok ]
    then 
        echo >/tmp/run-arh.lok;
    else
        reports=();
        reports[${#reports[@]}]="обнаружен признак занятости, архивация баз по событию < $event_type > - не выполнена!";
        makeErr;
fi

}


##..............................................................................

## -@F function check lock file
function lockOff() {
rm -f /tmp/run-arh.lok;
reports=();
reports[${#reports[@]}]="архивация баз по событию < $event_type > - выполнена успешно."
writeToLog;
}

##.............................................................................

## -@F function mount share
function mountSmb(){

if [ ! -d $path_mnt ]

    then
        mkdir -p $path_mnt;
fi

this_login=( ${login_smb[$(echo ${tmp_login[0]}| sed 's/\"//g')]} );

## проверка на смонтированный ресурс, если есть - выход с ошибкой!
        test_mount=$(df -h|grep $host_smb|wc -m);

        if [ $test_mount != 0 ]

            then
                reports=();
                reports[${#reports[@]}]="обнаружен примонтированный ресурс, архивация баз по событию < $event_type > - не выполнена!";
                makeErr;
            else
            mount -t cifs //$host_smb/$tmp_smb $path_mnt -o gid=1000,uid=1000,file_mode=0666,dir_mode=0777,user=$(echo ${this_login[0]}| sed 's/\"//g'),pass=$(echo ${this_login[1]}| sed 's/\"//g');
        fi


##.............................................................................

## -@F function umount share
function umountSmb(){
## проверка на смонтированный ресурс, если есть - откючаем...
        test_mount=$(df -h|grep $host_smb|wc -m);
        if [ $test_mount = 0 ]
            then
                reports=();
                reports[${#reports[@]}]=" не обнаружен примонтированный ресурс, по событию < $event_type > - прекращена!";
                makeErr;
            else
            umount $path_mnt;
        fi
}

##................................................................................

## -@F function copy end archive bases
function arhDb(){

local path_arh_in="";


iFs=(   "$(echo -n $event_type|sed 's/day//g'|wc -m) == 0"

        "$(echo -n $event_type|sed 's/week//g'|wc -m) == 0"
        "$(echo -n $event_type|sed 's/month//g'|wc -m) == 0" );

logic=( '"" "arhDay"'

        '"" "arhWeek"'
        '"errArh" "arhMonth"'
        );

    function arhDay() {

    lEnd=0;
    path_arh_in=$path_main_arh/${path_arh[0]};
    makeArh;
    }

    function arhWeek() {

    lEnd=0;
    path_arh_in=$path_main_arh/${path_arh[1]};
    makeArh;
    }

    function arhMonth(){

    lEnd=0;
    path_arh_in=$path_main_arh/${path_arh[2]};
    makeArh;
    }


    function makeArh() {

##
    for ((index_make=0; index_make != ${#tmp_db[@]}; index_make++))
        do
    # текущий каталог входа к базам
    local in_cd="${path_in_cd[$(echo ${tmp_in_cd[$index_make]}| sed 's/\"//g')]}";

    # получаем имя базы для копирования

    local in_db="${name_db[$(echo ${tmp_db[$index_make]}| sed 's/\"//g')]}";
    # копируем данную базу во временный каталог
    if [ ! -d $path_tmp ]
        then
        mkdir -p $path_tmp
        chmod -R 0666 $path_tmp;
        chmod -R ugo+X $path_tmp;
    fi
    if [ ! -d $path_tmp/$in_db ]
        then
        mkdir -p $path_tmp/$in_db
        chmod -R 0666 $path_tmp/$in_db;
        chmod -R ugo+X $path_tmp/$in_db;
    fi
    cd $path_mnt/$in_cd;
    ##cp -f -R $in_db $path_tmp;
    ## исключаем блокированные файлы базы 1с
    find $in_db -type 'f' | grep -v .cfl|grep -v .cgr| xargs -n 1 -I % cp -f -R --parents  "%" $path_tmp;
    cd
    #............................................
    # получаем имя архива для данной базы
    local arh_dbname="$path_arh_in/${name_arh[$(echo ${tmp_nmdb[$index_make]}| sed 's/\"//g')]}$arh_date.7z";
    if [ ! -d $path_arh_in ]
        then
        mkdir -p $path_arh_in;
        chmod -R 0666 $path_arh_in;
        chmod -R ugo+X $path_arh_in;
    fi
    # архивируем базу в заданный каталог..
    cd $path_tmp && 7z -t7z -mx=9 -r -ssc a $arh_dbname $in_db $2>/dev/null;
    cd
    # устанавливаем права на базы
    chown -R ${policy[$(echo ${tmp_pl[$index_make]}| sed 's/\"//g')]} $arh_dbname ;
    #............................................
    # удаляем временную копию текущей базы
    rm -f -R $path_tmp/$in_db;
    #............................................
    done
    }

    function errArh(){

    lEnd=0;
    reports=();
    reports[${#reports[@]}]="архивация по событию < $event_type > не выполнена...";
    printInfo;
    }

eXlogic;

}

##................................................................................

function clearArh() {
local path_arh_clr="";

iFs=(   "$(echo -n $event_type|sed 's/week//g'|wc -m) == 0"

        "$(echo -n $event_type|sed 's/month//g'|wc -m) == 0" );

logic=( '"" "clearDay"'

        '"errClear" "clearWeek"'
        );

    function clearDay() {

    lEnd=0;
    path_arh_clr=$path_main_arh/${path_arh[0]};
    clrOldDb;
    # удаляем архивы по имени +маска
    }

    function clearWeek() {

    lEnd=0;
    path_arh_clr=$path_main_arh/${path_arh[0]};
    clrOldDb;
    path_arh_clr=$path_main_arh/${path_arh[1]};
    clrOldDb;
    # удаляем архивы по имени +маска
    }

    function errClear(){

    lEnd=0;
    reports=();
    reports[${#reports[@]}]="удаление по событию < $event_type > не выполнено...";
    writeToLog;
    printInfo;
    # обработка ошибок если есть...
    }

function clrOldDb() {

for ((index_clr=0; index_clr != ${#tmp_db[@]}; index_clr++))
        do
    # получаем имя базы для удаления
    local clr_db="${name_arh[$(echo ${tmp_db[$index_clr]}| sed 's/\"//g')]}";
    rm -f $path_arh_clr/$clr_db*;
done
}

eXlogic;

}


##................................................................................

##--@F make all errors
function makeErr() {
        reports[${#reports[@]}]="операция по событию < $event_type > не выполнена!";
 printInfo;
 writeToLog;
 exit 0;
 exit 1;
}

##................................................................................

##--@F make all messages
function printInfo() {
value_in="$option";
iFs=(   "$(echo -n $value_in|wc -m) == 0"
        "$(echo -n $value_in|sed 's/--help//g'|wc -m) == 0" 
        "$(echo -n ${#reports[@]}) == 0" );

logic=( '"" "pInone"'

        '"" "pIhelp"'
        '"pIdf" "pInone"' );


function pInone() {

    lEnd=0;
    clear
    echo
    ##echo "psec:$(($(date +%s%3N)-$settime))";
    exit 0;
}

function pIhelp() {

    lEnd=0;
    clear
    reports=();
    reports[${#reports[@]}]="Архивация за один день: --d"; 
    reports[${#reports[@]}]="Архивация на конец недели (удалаются все архивы за день и содается архив на конец недели): --w";
    reports[${#reports[@]}]="Архивация на конец месяца (удалаются все архивы за день и за неделю затем содается архив на конец месяца): --m";
    pIdf;
    exit 0;
}

## default function last eXlogic..

function pIdf() {
    for ((rpt_index=0; rpt_index != ${#reports[@]}; rpt_index++))
        do
    echo   "${reports[$rpt_index]}";
    done
    exit 0;
    }
eXlogic;
}

##................................................................................

##--@F make all messages to log file
function writeToLog() {
for ((wrl_index=0; wrl_index != ${#reports[@]}; wrl_index++))
        do
    echo "$rdate - arh_db_zraid: ${reports[$wrl_index]}" >> $log_arh;
done
}

##................................................................................

##--@F executor
## обработчик операций..
function executor() {

if [[ ${#execute_func[@]} -eq 0 ]] 

    then echo "exit";
         exit 0; 
fi
for ((ex_index=0; ex_index != ${#execute_func[@]}; ex_index++))
 do
    ## !! debug operation...
    ## echo "execution: function ${execute_func[ex_index]}"
 ${execute_func[ex_index]};
done
}

##................................................................................

## обработка вызовов операций в зависимости от количества указанных ресурсов для чтения баз
function agent() {
for ((step_i=0; step_i != ${#read_smb[@]}; step_i++))
 do
tmp_smb=${read_smb[$step_i]};
tmp_db=( ${link_db[$step_i]} );
tmp_nmdb=( ${link_arh[$step_i]} );
tmp_pl=( ${link_policy[$step_i]} );
tmp_in_cd=( ${link_in_cd[$step_i]} );
tmp_login=( ${link_login_smb[$step_i]} );
executor
done
}


## events

case "$option" in

## the arhive day bases

"--d" | "--d" )
testday=$(date +%d|grep 01|wc -m);
    if [ "$testday" != 0 ]
        then
        event_type="month";
        execute_func=( ${operation_month[@]} );
        agent;
    #иначе делаем ежедневный архив
        else
        event_type="day";
        execute_func=( ${operation_day[@]} );
        agent;
    fi
exit 0
;;

## the arhive week bases

"--w" | "--w" )
testday=$(date +%d|grep 01|wc -m);
    if [ "$testday" != 0 ]
        then
        event_type="month";
        execute_func=( ${operation_month[@]} );
        agent;
    #иначе делаем еженедельный архив
        else
        event_type="week";
        execute_func=( ${operation_week[@]} );
        agent;
    fi
exit 0
;;

## the arhive month bases

"--m" | "--m" )
event_type="month";
execute_func=( ${operation_month[@]} );
agent;
exit 0
;;

## help

"--help" | "--help" )
execute_func=( ${operation_help[@]} );
executor
exit 0
;;

* )

# selecting defaults.
option="--help";
execute_func=( ${operation_help[@]} );
executor
exit 1
;;
esac

Просто скачать можно здесь: https://github.com/vixfree/arhbases

суббота, 14 января 2017 г.

Linux - автоматически изменяемый пароль по заранее заданному алгоритму на пользователя


Не секрет для любого администратора, что практически постоянно на ваш любимый сервер, кто то "стучится" пытаясь получить доступ например по ssh. Безусловно существует масса специализированных пакетов для защиты от такого рода атак, например не безызвестный fail2ban. Но всегда есть доля "паранойи" в таких случаях и я например не являюсь исключением. Поэтому и написал скрипт, который постоянно автоматически генерирует новый пароль для заданного пользователя или пользователей по только вам известному алгоритму.
Как правило все пароли имеют какие то знакомые слова или словосочетания, но если внедрить в такой пароль некое число или числа появляющиеся там в определенный промежуток времени и каждый раз разные, то подбор значительно усложняется, что явно неудобно тем кто ищет вход к Вам...  Алгоритм как правило удобно привязывать ко времени, а вот результат расчета можно импровизировать как вам угодно, вплоть до неких внешних данных о которых можете знать только вы. Я покажу тут скрипт, который рабочий, на языке bash. Алгоритм в нем расчета пароля максимально простой, если вам необходимо усложнить, то просто измените получение пароля как вы посчитаете необходимым. После этого вставьте исполнение в службу crontab и все, в заданный вами период времени пароль будет меняться автоматически...

Пример скрипта:

 #!/bin/bash
 ## the automatic password generation script 
 tdate=$(echo $(($(date +%d)+$(date +%H)))); 
 newpass=( "$tdate""mynewpass1\n"
          "$tdate""mynewpass2\n" );
 logins=( "user1"
          "user2" );
 for ((gen_i=0; gen_i != ${#logins[@]}; gen_i++))
  do
 echo -e ${newpass[$gen_i]}${newpass[$gen_i]}| passwd -q ${logins[$gen_i]} 2>/dev/null;
 done
В скрипте суммируется дата и час, после чего значение ставится перед заданным словосочетанием получается новый пароль каждый час из числа и слова. Можно комбинировать множеством значений числа прибавляя еще какие нибудь числа и вставляя в разные участки вашего пароля...