LINUX.ORG.RU

PyBackuper. Бекапим на Yandex-Диск.

 , , ,


0

1

Открываю проект в open-source

Тестируется и эксплуатируется в настоящий момент на Windows для MS SQL

Предназначение: хранение всех файлов бекапов на Yandex-диске в каталогах, названных согласно текущих (на момент отправки) даты и времени, автоматическая чистка старых файлов на Yandex-диске.

Утилита может работать в двух режимах:
1. Режим слежения
2. Режим ручного запуска

В режиме слежения утилита следит за изменениями файлов в указанных в настройках каталогах и отправляет их в Yandex-диск. Доступ к аккаунту Yandex-диск также указывается в настройках. Перед отправкой файла происходит чистка старых каталогов на Yandex-диске.

В режиме ручного запуска утилита копирует определенный пользователем бекап на Yandex-диск.

При появлении файла в одном из отслеживаемых каталогов утилита, запущенная службой в режиме backuper.py watcher -s с помощью nssm, происходит создание каталога вида YYYYMMDD / HHmm на Yandex-диске (корень возможно указать в настройках). В этот каталог копируется найденный файл. В настройках указано максимальное хранение файлов 250 дней. Перед копированием каждого файла происходит удаление каталогов YYYYMMDD старше 250 дней.

PS. Буду рад предложениям.

>>> GitHub

★★★★★

Проверено: Pinkbyte ()
Последнее исправление: Pinkbyte (всего исправлений: 2)

Тестируется и эксплуатируется в настоящий момент на Windows

А почему не на Линуксе?

Odalist ★★★★★
()
Ответ на: комментарий от Odalist

Потому что делалось для бекапирования 1С-баз, которые работают на MS SQL на WinServer, увы. Но ничего вин-специфического вроде бы нет.

bvn13 ★★★★★
() автор топика

Что-то непонятно, чем оно отличается от штатного клиента яндекса.

А поддержка других хранилищ планируется?

Aceler ★★★★★
()
Ответ на: комментарий от Aceler

Что-то непонятно, чем оно отличается от штатного клиента яндекса.

Шатный подключает диск как папку, светит ей в файловую систему, предоставляя потенциальный доступ всем и вся.

А поддержка других хранилищ планируется?

реквестируй

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от Odalist

В режиме слежки за каталогом указывается маска файлов, которые подлежат отправки в ЯДиск, поэтому не стоит зацикливаться на словах «1С», «MS», «Win»

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

предоставляя потенциальный доступ всем и вся.

Ну уж как настроишь права на папку. YD запускается от непривилегированного пользователя.

Я так понимаю, сей бекапер не хранит данные локально, а посланное удаляет? Тогда понятно.

Aceler ★★★★★
()

В общем, я убрал то, что касается MS SQL, потому что это не важно и офтопик, в остальном нигде не наврал?

Aceler ★★★★★
()
Ответ на: комментарий от bvn13

Иными словами, будет ли оно работать на сервере с Linux? Я так понял, nssm используется только для запуска скрипта как сервиса.

Aceler ★★★★★
()
Ответ на: комментарий от Aceler

да, только для работы как службы винды. в Linux запустить нужно как python backuper watcher -s

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

Я тут как то на ЛОРе пытался выяснить почему duplicity не пашет через прокси в частности с Яндекс диском, так мне написали что бекапы хранить на я.д. запрещено лицензионным соглашением ...

mx__ ★★★★★
()
Ответ на: комментарий от mx__

мне написали тут как то на ЛОРе

Ну если на ЛОРе написали, то это истина в последней инстанции.

fornlr ★★★★★
()

webdav же пипец какой медленный

InterVi ★★★★
()

погоди-ка

from pymssql import _mssql
нафиг тогда тут это поделие рекламировать, если оно только для M$? не думаю что тут много кто использует их БД

А ещё, хорошие кодеры всегда указывают версию питона хотя бы в стартовом файле.

InterVi ★★★★
()

Чем оно лучше rclone?

Gary ★★★★★
()
Ответ на: комментарий от InterVi

mssql там только для запуска хранимки выгрузки бекапа.

bvn13 ★★★★★
() автор топика

backupninja

anonymous
()

ну или вот, вариации на тему

#!/bin/bash

#
# article: http://neblog.info/skript-bekapa-na-yandeks-disk
#

# REST API: https://tech.yandex.ru/disk/api/reference/upload-docpage/

TOKEN=""
# NB: slash ending 
UPLOADING_PATH="/"

function parse_json()
{
    local output
    regex="(\"$1\":[\"]?)([^\",\}]+)([\"]?)"
    [[ $2 =~ $regex ]] && output=${BASH_REMATCH[2]}
    echo $output
}

function check_error()
{
    echo $(parse_json 'error' "${1}")
}

function file_upload()
{
    local path="path=${UPLOADING_PATH}${1}"
    local param="overwrite=true"
    local url="https://cloud-api.yandex.net:443/v1/disk/resources/upload"
    local json_out=`curl -s -H "Authorization: OAuth ${TOKEN}" -G ${url} --data-urlencode "${path}" --data "${param}"`
    
    local json_error=$(check_error "${json_out}")  
      
    if [[ $json_error == '' ]]; then
    	url=$(parse_json 'href' ${json_out})
    	
    	json_out=`curl -s -T ${1} -H "Authorization: OAuth ${TOKEN}" ${url}`
        json_error=$(check_error "$json_out")
        
        if [[ $json_error == '' ]]; then
            return 0;
        else 
            echo $json_error
            return 1; 
        fi
    else
        echo $json_error
        return 1  
    fi
}

function file_publish()
{
	local path="path=${UPLOADING_PATH}${1}"
    local url="https://cloud-api.yandex.net/v1/disk/resources/publish"
	local json_out=`curl -s -X PUT -H "Authorization: OAuth ${TOKEN}" -G ${url} --data-urlencode "${path}"`
	
	local json_error=$(check_error "${json_out}")  
      
    if [[ $json_error == '' ]]; then
        url=$(parse_json 'href' $json_out)
        json_out=`curl -s -H "Authorization: OAuth ${TOKEN}" ${url}`
        json_error=$(check_error "$json_out")
        
	    if [[ $json_error != '' ]];
	    then
		    echo $json_error
	    else
            echo $(parse_json 'public_url' $json_out)
            return 0
	    fi

	else
        echo $json_error
        return 1  
    fi
}

function file_delete()
{
	local path="path=${UPLOADING_PATH}${1}"
	local param="permanently=true"
    local url="https://cloud-api.yandex.net/v1/disk/resources"
	local json_out=`curl -s -X DELETE -H "Authorization: OAuth ${TOKEN}" -G ${url} --data-urlencode "${path}" --data "${param}"`
	
	json_error=$(check_error "$json_out")
	
	if [[ $json_error != '' ]];
	then
		echo "json_error: $json_error"
		return 1
	else
		return 0
	fi
}

function files_list() 
{
    local path="path=${UPLOADING_PATH}"
	local param="sort=created&limit=100"
    local url="https://cloud-api.yandex.net/v1/disk/resources"

    curl -s -H "Authorization: OAuth $TOKEN" -G ${url} --data-urlencode "${path}" --data "${param}" | tr "{},[]" "\n" | grep "name[[:graph:]]${1}" | cut -d: -f 2 | tr -d '"'
}

function usage
{
cat <<EOF
USAGE: $0 OPTIONS
OPTIONS:
  -h  Show this message
  -l  List of files
  -m  Mask of list files
  -f  <filename>  Specify filename
  -u  upload this file
  -p  publish this file
  -d  delete this file
EOF
}


# --------------- OPTIONS -------------
while getopts ":hlm:f:udp" opt; do
    case $opt in
	\?)
	    echo "Invalid option: -$OPTARG. $0 -h for help" >&2
	    exit 1
	    ;;
	:)
	    echo "Option -$OPTARG requires an argument." >&2
	    exit 1
	    ;;
	h)
	    usage
	    exit 1
	    ;;
	l)
		list=true;
		;;
	m)  
		mask="$(echo ${OPTARG} | tr -d '\\')"
		#echo "${mask}"
		#exit 1
		;;
	f)
	    filename=${OPTARG}

	    if [ ! -f ${filename} ];
	    then
		    echo "File not found: ${filename}" >&2
		    exit 1
	    fi
	    ;;
	u)
	    upload=true
	    ;;
	p)
        publish=true
        ;;
	d)
	    delete=true
	    ;;
    esac
done

# --------------- MAIN ----------------
if [[ "true" == ${list} ]]; then
	files_list ${mask}
fi

if [[ "true" == ${upload} ]]; then
	if [[ -z ${filename} ]]; then
	    usage
	    exit 1
	fi

	rc=$(file_upload ${filename}) || {
	    echo "json_error: $rc" >&2
	    exit 1
	}
fi

if [[ "true" == ${publish} ]]; then
	if [[ -z ${filename} ]]; then
	    usage
	    exit 1
	fi

	rc=$(file_publish ${filename}) && {
		echo "$rc" >&1
	} || {
	    echo "json_error: $rc" >&2
	    exit 1
	}
fi

if [[ "true" == ${delete} ]]; then
	if [[ -z ${filename} ]]; then
	    usage
	    exit 1
	fi

	rc=$(file_delete ${filename}) || {
	    echo "json_error: $rc" >&2
	    exit 1
	}
fi

exit 0
вообще, непонятно, зачем логику бекапа совмещать с процедурой выгрузки бекапа.

У большинства пользователей будут разные задачи, поэтому логика бекапа тоже за редким исключением будет своя. Т.е. пмсм для nixway должны быть как минимум две утилиты/скрипта: для загрузки и для формирования файла бекапа...

zudwa
()
Ответ на: комментарий от pekmop1024

Он как раз используется в этих скриптах. Но он пипец медленный, у меня скорость выше 200кб/с не поднималась.

InterVi ★★★★
()
Ответ на: комментарий от InterVi

Ну, тебе ещё и скорость на шару :-)
Для тех объемов, что даёт Яндекс, скорости не нужны. А для тех, для которых нужны - уже платный яндекс.

pekmop1024 ★★★★★
()
Ответ на: комментарий от bvn13

Шатный подключает диск как папку, светит ей в файловую систему, предоставляя потенциальный доступ всем и вся.

Эм, а как правильно должно быть?)

Xant1k ★★
()

Прикрути возможность шифрования бекапов, тогда будет интереснее. Это ж общественное облако, держать там базы не боясь, что угонят аккаунт, довольно наивно.

autonomous ★★★★★
()
Ответ на: комментарий от bvn13

реквестируй

А тем, кто пленных брать не собирается?

anonymous
()
Ответ на: комментарий от InterVi

Если использовать официальное приложение яндекса, там 2мб/с будет точно.

Интересно, почему? Другой протокол, не webdav?

Harliff ★★★★★
()

https://github.com/bvn13/PyBackuper/blob/master/backuper/dirwatcher.py#L20

def isFileAvailable(self, filename) :
...
                os.rename(filename, filename)
...
return False
у меня вопрос: тебе не кажется, довольно странной такая практика проверки?
возможно, в языке есть другие инструменты для этого? возможно что-то ассоциируемое с доступом?
да и в конце концов назови это isFileRenameble

system-root ★★★★★
()
Ответ на: комментарий от Harliff

Другой. А еще в их вебдаве patch не поддерживается и большие файлы целиком обновлять надо. А ЯД-клиент умеет patch :(

jerry_ru
()
Ответ на: комментарий от Xant1k

Это как бы разные инструменты.

Что яндекс синкает папку и отправляет на сервак, что syncthing - разницы никакой. Ну да, сервак надо свой, но сервак в данном случае - понятие довольно условное, правильнее говорить «клиент». Абсолютно не понимаю людей, которые из-за эфемерной дешевизны согласны на хранение чувствительной информации в публичном облаке. Как раз сейчас продумываю схему по резервному копированию баз на выделенный сервер, но пользоваться «облаками» - де-факто расписаться под собственной импотенцией как одмина.

araks ★★
()
Ответ на: комментарий от jerry_ru

А как оно копирует файлы которые в процессе записи? Битые получаются?

Почему битые - обычные.

Если происходит копирование файла, то файл открыт в монопольном режиме и ST не в состоянии его прохешировать до окончания копирования. На синхронизируемой ноде будет создан заполненный нулями временный файл идентичного размера, по окончании копирования начнется синхронизация.

Если происходит архивирование, то инициирующая сторона совершает несколько попыток синхронизировать пухнущий файл, после чего попытки прекращаются до окончания роста размера файла. ST-инициатор дохеширует оставшуюся часть файла и отправляет на принимающую ноду.

araks ★★
()
Ответ на: комментарий от araks

файл открыт в монопольном режиме

В юниксах так не принято.

legolegs ★★★★★
()
Ответ на: комментарий от jerry_ru

никак. следит за файлом. когда получает событие об изменении файла, пытается файл переименовать в самого себя. если удается, то файл доступен, и его можно копировать, если ошибка переименования - то файл еще пишется кем-то.

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от bvn13

В линуксе не взлетит. Тут можно переименовывать и удалять даже пишущиеся файлы. Безболезненно.

jerry_ru
()

А есть главное - шифрование данных?

devalone ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.