15

Я ищу реализацию (в Linux) механизма, который бы автоматически и прозрачно версировал любые изменения в каталоге (рекурсивно). Предполагается, что это дополнение (возможно, замена, если все требуемые функции доступны) к стандартному версионированию (SVN, git, ...)

Продукт на MS Windows, который делает это, AutoVer (чтобы лучше понять требования). Я хотел бы иметь что-то подобное, но нацеленное на Linux в неграфической среде.

Я видел, что есть некоторые попытки использовать эту функциональность в Linux, самая близкая из них, которую я нашел, - это автоверсионирование в Subversion, но это не очевидно для реализации в существующих средах (серверах, где, например, файлы конфигурации являются локальными).

Может быть, что-то работает с inotify?

Заранее спасибо за любые указатели! WOJ

9 ответов9

5

1. Универсальный метод с использованием базара

Это не проверено мной, но я нашел эту запись, которая использует bzr (bazaar) & inotifywait для мониторинга каталога и контроля версий файлов в нем с помощью bazaar.

Этот скрипт выполняет всю работу по просмотру каталога на предмет изменений:

#!/bin/bash

# go to checkout repository folder you want to watch
cd path/to/www/parent/www
# start watching the directory for changes recusively, ignoring .bzr dir
# comment is made out of dir/filename
# no output is shown from this, but wrinting a filename instead of /dev/null 
# would allow logging
inotifywait –exclude \.bzr -r -q -m -e CLOSE_WRITE \
    –format=”bzr commit -m ‘autocommit for %w/%f’” ./ | \
    sh  2>/dev/null 1>&2 &
# disown the pid, so the inotify thread will get free from parent process
# and will not be terminated with it
PID=`ps aux | grep inotify | grep CLOSE_WRITE | grep -v grep | awk ‘{print $2}’`
disown $PID

# this is for new files, not modifications, optional
inotifywait –exclude \.bzr -r -q -m -e CREATE \
    –format=”bzr add *; bzr commit -m ‘new file added %w/%f’” ./ | \
    sh  2>/dev/null 1>&2 &
PID=`ps aux | grep inotify | grep CREATE | grep -v grep | awk ‘{print $2}’`
disown $PID

exit 0;

2. Управление / и т.д.

Для особого случая управления каталогом /etc вашей системы вы можете использовать приложение etckeeper.

etckeeper - это набор инструментов для хранения /etc в репозитории git, mercurial, darcs или bzr. Он подключается к apt (и другим менеджерам пакетов, включая yum и pacman-g2) для автоматической фиксации изменений, внесенных в /etc во время обновлений пакетов. Он отслеживает файловые метаданные, которые системы контроля версий обычно не поддерживают, но это важно для /etc, например, для разрешений /etc /shadow. Он достаточно модульный и настраиваемый, а также простой в использовании, если вы понимаете основы работы с контролем версий.

Вот хороший учебник, с которого можно начать.

3. Использование git и incron

Эта техника использует git и incron . Для этого метода вам нужно сделать следующее:

А. Сделайте репо

% mkdir $HOME/git
% cd $HOME/git
% git init

Б. Создайте скрипт $HOME/bin/git-autocommit

#!/bin/bash

REP_DIR="$HOME/git"       # repository directory
NOTIFY_DIR="$HOME/srv"    # directory to version

cd $REP_DIR
GIT_WORK_TREE=$NOTIFY_DIR /usr/bin/git add .
GIT_WORK_TREE=$NOTIFY_DIR /usr/bin/git commit -a -m "auto"

C. Добавить запись в incrontab

% sudo incrontab -e $HOME/srv IN_MODIFY,IN_CREATE,IN_MOVED_FROM,IN_MOVED_TO $HOME/bin/git-autocommit

4. Использование Flashbake

Другой вариант - использовать такой инструмент, как Flashbake. Flashbake - это система контроля версий, которую Кори Доктороу (из знаменитости BoingBoing) использует для написания своих книг.

Flashbake использует git для отслеживания изменений, но находится где-то между автоматическим резервным копированием и использованием простой системы контроля версий.

Кори хотел, чтобы версия содержала подсказки, снимки того, где он был в то время, когда происходил автоматический коммит, и что он думал. Я быстро набросал сценарий Python для извлечения нужной ему контекстной информации и начал собирать сценарий оболочки для управления git, используя вывод сценария Python для комментария коммита, когда задание cron вызывало оболочку оболочки.

Ресурсы

4

Тут же на ум приходит ZFS. Он может создавать снимки - и есть несколько проектов для автоматического создания снимков.

3

Я думаю, что вы на правильном пути с inotify . Эта статья подробно описывает его основное использование в случае, похожем на ваш. Я бы предложил использовать его напрямую или скомпилировать утилиту уровня ядра, такую как fschange . Это немного хлопотно, но вы можете связать обнаружение изменений с git commit или подобным.

Оба эти решения имеют проблему использования несовершенных решений сторонних производителей. Если вы не возражаете запачкать руки, NodeJS предоставляет отличное кроссплатформенное средство (fs.watch) для этой конкретной цели. Базовое руководство по просмотру файлов на предмет изменений в NodeJS можно найти здесь. В несколько десятков строк или меньше, вы могли бы написать что-то, что просматривает каталог для файлов, а затем выдает (через child_process) и запускает git commit или аналогичный (или даже вручную увеличивает индекс файла версии, если вам нравится ваш собственный подход).

fs.watch поддерживается inotify на linux, но гораздо более интуитивно понятен в использовании. Существуют другие проекты NodeJS, которые оборачивают эту функцию просмотра файлов с различными уровнями удобства, как этот или этот.

3

inotify(2) в Linux не сможет наблюдать большое дерево, но файловая система fuse (смонтированная в отдельном месте), вероятно, могла бы справиться с этим, переводя запросы файловой системы в вызовы svn или git или напрямую изменяя метаданные svn/git.

Это очень интересная идея, но я не слышал ни о каких существующих реализациях.

0

Вот скрипт Python3, который делает VMS как автоматическое управление версиями файлов, используя отметку времени, добавленную к исходному имени файла при сохранении.

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

!/usr/bin/env python3

print ("НАЧАТЬ ВЕРСИИ ФАЙЛОВ ПРОЕКТА") print ("version_creation.py") # поместить весь этот код в скрипт с таким именем print ("запустить как .. 'python3 version_creation.py' из командной строки") print ("ctrl ') c 'to stop ") print (" ") print (" Чтобы запустить программу в фоновом режиме ниже для командной строки, а затем закрыть окно. ") print (" nohup python3 version_creation.py ") print (" .... to остановить процесс перейти в меню / администрирование / системный монитор ... и уничтожить python3 ") print (" ") print (" Всегда сохранять файлы в каталог 'ProjectFiles' и файлы версий ") print (" также будет создан в этом каталоге . ") print (" ") print (" ") print (" ") print (" ")

импорт shutil импорт os время импорта

--- установите временной интервал для проверки новых файлов (в секундах) ниже

- этот интервал должен быть меньше интервала появления новых файлов!

т = 10

--- установить исходный каталог (dr1) и целевой каталог (dr2)

dr1 = "/path/to/source_directory"

dr2 = "/path/to/target_directory"

импорт глобус импорт ос

dr1 = "/home/michael/ProjectFiles" # оба оригинала и версии будут сохранены в этом каталоге

dr2 = "/home/michael/ProjectFileVersions"

пока верно:

if os.listdir(dr1) == []:

печать ("Пусто")

    n = 100
else:
    list_of_files = glob.glob(dr1+'/*')   # * means all if need specific format then *.csv
    latest_file_path = max(list_of_files, key=os.path.getctime)

print ("1 Latest_file_path =", latest_file_path)

    originalname = latest_file_path.split('/')[-1]

print ("2 originalname =", originalname)

    filecreation = (os.path.getmtime(latest_file_path))

print ("filecreation =", filecreation)

    now = time.time()
    fivesec_ago = now - 5 # Number of seconds

print ("fivesec_ago =", fivesec_ago)

    timedif = fivesec_ago - filecreation #time between file creation

print ("timedif =", timedif)

    if timedif <= 5: #if file created less than 5 seconds ago

        nameroot = originalname.split(".")[-0]
        print ("3 nameroot= ", nameroot)

        extension = os.path.splitext(originalname)[1][1:]
        print ("4 extension = ", extension)

        curdatetime = time.strftime('%Y%m%d-%H%M%S')
        print ("5 curdatetime = ", curdatetime)

        newassembledname = (nameroot + "_" + curdatetime + "." + extension)
        print ("6 newassembledname = ", newassembledname)



        source = dr1+"/"+originalname
        print ("7 source = ", source)

        target = dr1+"/"+newassembledname
        print ("8 target = ", target)

        shutil.copy(source, target)


    time.sleep(t)

доля

ниже был введен ранее и работает, но мне нравится вышеупомянутый скрипт на python намного лучше ......(использую python около 3 часов)

#!/usr/bin/env python3

print ("PROJECT FILES VERSIONING STARTED")
print ("projectfileversioning.py")
print ("run as..  'python3 projectfileversioning.py'       from command line")
print ("ctrl 'c'      to stop")
print (" ")
print ("To run program in background type below to command line and then close the window. ")
print ("nohup python3 projectfileversioning.py")
print ("....to stop process go menu/administration/system monitor... and kill python")
print (" ")
print ("Always save files to the 'ProjectFiles' directory and the file ")
print ("   will be redirected to the ProjectFileVersions where")
print ("   time stamped versions will also be created.")
print (" ")
print ("If you like you may then copy/move the versioned and original file from 'ProjectFileVersions' to ")
print ("any other directory you like.")

import shutil
import os
import time

#--- set the time interval to check for new files (in seconds) below 
#-   this interval should be smaller than the interval new files appear!
t = 10

#--- set the source directory (dr1) and target directory (dr2)
#dr1 = "/path/to/source_directory"
#dr2 = "/path/to/target_directory"

import glob
import os

dr1 = "/home/michael/ProjectFiles"
dr2 = "/home/michael/ProjectFileVersions"


while True:

    if os.listdir(dr1) == []:
        n = 100
    else:
        list_of_files = glob.glob(dr1+'/*')   # * means all if need specific format then *.csv
        latest_file_path = max(list_of_files, key=os.path.getctime)
        print ("1 Latest_file_path = ", latest_file_path)

        originalname = latest_file_path.split('/')[-1]
        print ("2 originalname = ", originalname)

        nameroot = originalname.split(".")[-0]
        print ("3 nameroot= ", nameroot)

        extension = os.path.splitext(originalname)[1][1:]
        print ("4 extension = ", extension)

        curdatetime = time.strftime('%Y%m%d-%H%M%S')
        print ("5 curdatetime = ", curdatetime)

        newassembledname = (nameroot + "_" + curdatetime + "." + extension)
        print ("6 newassembledname = ", newassembledname)




        source = dr1+"/"+originalname
        print ("7 source = ", source)

        target = dr2+"/"+originalname
        print ("8 target = ", target)

        shutil.copy(source, target)



        source = dr1+"/"+originalname
        print ("9 source = ", source)

        target = dr2+"/"+newassembledname
        print ("10 target = ", target)

        shutil.move(source, target)
        time.sleep(t)


#share
0

Существует также способ «бедняков» сделать это, используя только rsync и работу cron. Вы в основном полагаетесь на средство резервного копирования rsync и используете два отдельных пути плюс префикс / суффикс для отслеживания ваших файлов.

Более менее это выглядит так:/usr/bin/rsync -a -A -X --backup --suffix = date +".%Y-%m-%d_%H-%M-%S" $ source_path $ backup_path

Конечный результат: изменение файла с именем test_rsync в исходном пути после первоначального выполнения приведет к созданию файла с именем test_rsync.2017-02-09_11-00-01 в пути резервного копирования.

С этим связано множество проблем (это работает, если у вас только приличное количество файлов, и сбой при изменениях, которые происходят между двумя последовательными запусками rsync (1 минута в моем случае)), но этого может быть достаточно для ваших нужд.

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

Дайте мне знать, если вы улучшите это.

0

SparkleShare (http://sparkleshare.org) основан на git и реализует функциональность Dropbox-Like с контролем версий, но вы должны настроить ssh-сервер (может быть localhost).

0

Такой сценарий не сложно написать.

Мой любимый контроль версий - это git.

следующий скрипт должен это сделать:

#!/bin/sh
git add .
git commit -am "my automatic commit"

либо периодически проверяйте вашу директорию, либо, если ваш редактор вызывает сценарий после сохранения.

Но если вы делаете это таким образом, возможно, имеет смысл исключить большие файлы и, возможно, некоторые "бесполезные", такие как автосохранения.

0

Я бы порекомендовал вам попробовать NILFS. Перейдите на страницу «О нас», и вы быстро сможете решить, что именно вы ищете или нет.

НТН

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .