суббота, 14 декабря 2019 г.

Бэкап на коленке: утилита expect

Задача: несколько серверов и один комп-архиватор, на котором нужно делать бекап "избранных" файлов. На каждом сервере создаем юзера archiver (ну или какой вам нравиться). В домашнем каталоге у него (на каждом  же сервере) создаем папочку  backup (ну или какое название вам нравиться другое). Также создаем скрипт, который кроном запускается с нужной периодичностью и пакует в эту папку нужный вам контент.
На компе-архиваторе создаем папку backups с подкаталогами у которых имена сопадают  с именами архивируемых серверов. Далее устанавливаем утилиту expect на компе-архиваторе и пишем скрипт такого содержания:

#!/usr/bin/expect -f
set ret [ catch {

array set user {
        server_1        archiver
        server_2        archiver
# etc
        server_n         archiver
}

#можно и без этого абзаца, но вдруг find на серверах находится в разных местах
array set find {
        server_1          /usr/bin/find
        server_2          /usr/bin/find
# etc
        server_n         /usr/bin/find
}

array set ips_passwords {
        server_1          password1 
        server_2          password2 
# etc
        server_n          passwordn
}

set timeout -1

send_user "backup is starting!...\n"
foreach keyip [array name ips_passwords] {
        #
        #Копируем периодические бэкапы на наш комп-архиватор
        spawn /usr/bin/scp $user($keyip)@$keyip:/home/$user($keyip)/backup/* /home/backuper/backups/$keyip
        match_max 100000
        expect  "*?assword*:"
        send -- "$ips_passwords($keyip)\r"
        send -- "\r"   
        expect eof
        #
        #Со следующим абзацем поосторожней. Удаляет в директории, где храняться
        #наши бэкапы файлы старше 5 дней.
        spawn /usr/bin/ssh $user($keyip)@$keyip $find($keyip) /home/$user($keyip)/backup -ctime +5 -exec /bin/rm \{\} \\\;
        match_max 100000
        expect "*?assword*:*"
        send -- "$ips_passwords($keyip)\r"
        send -- "\r"
        expect eof
}
send_user "backup had finished succesfully!\n"

} result ]

set fh [open /home/backuper/Desktop/expect-works w]
puts $fh "Code $ret, Message/Result $::result \n"
close $fh


Нюанс. Сделайте, если еще не делали, логин юзером archiver с вашего компа-архиватора через ssh на каждый сервер. Эту ситуацию (первая сессия ssh archiver@server_x) можно отработать и в скрипте, но тогда код усложниться. А нам нужна проcтота. Не так ли?

среда, 4 декабря 2019 г.

Работа с com портом из командной строки Linux

Вывод параметров порта в читаемом виде:
#stty -a -F /dev/ttyUSB0
Переключение в raw режим:
#stty -F /dev/ttyUSB0 raw -echo -echoe -echok
Послать команду:
#echo "HELLO" > /dev/ttyUSB0
#echo  -ne '\x23\x02\x01\x00\x50\x01\r' > /dev/ttyUSB0
Прочитать данные:
#cat /dev/ttyUSB0
Сохранить параметры порта для последующего восстановления:
#stty -g -F /dev/ttyUSB0 > save.txt
#stty --save /dev/ttyUSB0 > save.txt
Считываем сохраненные параметры:
#stty -F /dev/ttyUSB0 `cat save.txt`
Устанавливаем скорость 115200 бод, 8 битов данных, стоп бит, без проверки четности (режим 8N1):
#stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb


среда, 23 октября 2019 г.

Вызов команд Gnuplot из программы С++

    Gnuplot, как известно, интерактивная программа. Также в ней существует возможность создавать скрипты, которые можно запускать с командного интепретатора операционной системы. Иногда бывает удобно "заворачивать" эти команды в программу с/с++. Далее в тексте приведены две таких программы. Кто умеет пользоваться Gnuplot-ом без труда сможет изменить их текст для своих нужд. Первая програма выполняет стандартную задачу постройки 2D-графиков, а вторая строит "карту" из данных, представленых матрицей. В обоих случаях вывод происходит не окно, а в отдельный jpeg файл.
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
using namespace std;

int main(){
    FILE* gnuplotpipe;
    string command;
    gnuplotpipe = popen("gnuplot -persist","w");
    if(!gnuplotpipe)
        cerr<<("there are no gnuplot");

command =
    "set terminal jpeg size 3400,2300 font 'Times New Roman-bold,48';"
    "set output 'graphic.jpg';"
    "plot "
    "'data1.dat' u 1:2 w l t '1', "
    "'data2.dat' u 1:2 w l t '2', "
    "'data3.dat' u 1:2 w l t '3'; ";

    fprintf(gnuplotpipe,"%s",command.c_str());
    fflush(gnuplotpipe);


    fprintf(gnuplotpipe, "exit\n");
    pclose(gnuplotpipe);
    return 0;
}


#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
using namespace std;
int main(){
    FILE* gnuplotpipe;
    string command;
    gnuplotpipe = popen("gnuplot -persist","w");
    if(!gnuplotpipe)
        cerr<<("there are no gnuplot");

command =
    "set terminal jpeg size 3400,2300 font 'Times New Roman-bold,48';"
    "set output 'graphic.jpg';"

    "set pm3d map;"
    "set pm3d at b;"
    "set pm3d interpolate 0,1;"
    "set pm3d corners2color c1;"
    "set palette defined (0 \"blue\", 10 \"cyan\", 30 \"green\", 45 \"yellow\", 70 \"orange\", 100 \"red\");"
    "set cbrange [0:1];"
    "set ticslevel 0;"
    "splot \"matrixData.dat\" matrix;";

    fprintf(gnuplotpipe,"%s",command.c_str());
    fflush(gnuplotpipe);


    fprintf(gnuplotpipe, "exit\n");
    pclose(gnuplotpipe);
    return 0;
}