Automatische Versionierung bei Dateiänderung (Ändern / Erstellen / Löschen)

11492
WoJ

Ich suche nach einer Implementierung (unter Linux) eines Mechanismus, der alle Änderungen in einem Verzeichnis automatisch und transparent versioniert (rekursiv). Dies ist als Zusatz (möglicherweise als Ersatz, wenn alle angeforderten Funktionen verfügbar sind) zur Standardversionierung (SVN, git, ...) vorgesehen.

Ein Produkt unter MS Windows, das dies tut, ist AutoVer (um die Anforderungen besser zu verstehen ). Ich hätte so etwas gerne, wäre aber in einer nicht grafischen Umgebung auf Linux ausgerichtet.

Ich habe gesehen, dass es einige Versuche gibt, diese Funktionalität unter Linux zu nutzen. Die nächste, die ich gefunden habe, ist die automatische Umstellung auf Subversion. Es ist jedoch nicht naheliegend, sie in vorhandenen Umgebungen (Servern, auf denen beispielsweise Konfigurationsdateien lokal sind) zu implementieren.

Vielleicht mit etwas arbeiten inotify?

Vielen Dank im Voraus für alle Hinweise! WoJ

15
verwandt: [flashbake] (http://bitbucketlabs.net/flashbake/) Dan D. vor 12 Jahren 0
http://sourceforge.net/apps/mediawiki/fuse/index.php?title=VersioningFileSystems SleighBoy vor 12 Jahren 0
Gibt es eine spezielle Anforderung, welche Software Sie verwenden? Wenn Sie nur Änderungen nachverfolgen möchten, die Sie manuell vornehmen (durch Bearbeiten von Dateien), verfügt Eclipse über diese Funktion, die als "lokaler Verlauf" bezeichnet wird. Stefan Seidel vor 11 Jahren 0
@StefanSeidel Ich bin nicht der Themenstarter, aber ich würde keine IDE-Lösung bevorzugen. Michael Pankov vor 11 Jahren 0

9 Antworten auf die Frage

5
slm

1. Allzweckmethode mit Basar & Inotify

Dies wurde von mir nicht getestet, aber ich habe dieses Schreiben gefunden, das bzr(basar) & verwendet inotifywait, um ein Verzeichnis zu überwachen und die darin enthaltenen Dateien mit basar zu kontrollieren.

Dieses Skript erledigt das Verzeichnis auf Änderungen:

#!/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 ‘’` 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 ‘’` disown $PID  exit 0; 

2. Verwalten von / etc

Für den speziellen Fall der Verwaltung Ihres Systemverzeichnisses /etckönnen Sie die App etckeeper verwenden .

etckeeper ist eine Sammlung von Tools, mit denen / etc in einem git-, mercurial-, darcs- oder bzr-Repository gespeichert werden kann. Apt (und andere Paketmanager, einschließlich yum und pacman-g2) können automatisch Änderungen an / etc übernehmen, die während der Paketaktualisierung vorgenommen wurden. Es verfolgt Dateimetadaten, die Revisionskontrollsysteme normalerweise nicht unterstützen. Dies ist jedoch für / etc wichtig, beispielsweise die Berechtigungen von / etc / shadow. Es ist ziemlich modular und konfigurierbar, aber auch einfach zu verwenden, wenn Sie die Grundlagen der Arbeit mit der Revisionskontrolle kennen.

Hier ist ein gutes Tutorial, um den Einstieg zu erleichtern.

3. Mit git und inkrement

Diese Technik verwendet gitund incron. Für diese Methode müssen Sie Folgendes tun:

A. Repo erstellen

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

B. Erstellen Sie ein $HOME/bin/git-autocommitSkript

#!/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. Fügen Sie einen Eintrag zu Incrontab hinzu

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

4. Flashbake verwenden

Eine andere Option ist die Verwendung eines Tools wie Flashbake . Flashbake ist das Versionskontrollsystem, mit dem Cory Doctorow (von BoingBoing berühmt) seine Bücher schreibt.

Flashbake verwendet git unter der Haube, um Änderungen nachzuverfolgen, liegt jedoch irgendwo zwischen automatisierten Backups und einem einfachen Versionskontrollsystem.

Cory wollte, dass die Version Aufforderungen und Momentaufnahmen davon enthielt, wo er sich zu dem Zeitpunkt befand, an dem sich ein automatisches Commit befand, und was er dachte. Ich entwarf schnell ein Python-Skript, um die Kontextinformationen abzurufen, die er wollte, und fing an, ein Shell-Skript zu hacken, um git zu fahren, und benutzte die Ausgabe des Python-Skripts für den Commit-Kommentar, wenn ein Cron-Job den Shell-Wrapper aufrief.

Ressourcen

inotifywait + "git local" = gitwatch.sh, schauen Sie hier: https://github.com/nevik/gitwatch/blob/master/gitwatch.sh diyism vor 8 Jahren 2
4
bdecaf

Immediatly ZFS comes to mind. It can create snapshots - and there are some projects to automatically create snapshots.

Ich habe über ZFS gelesen, aber es scheint keine stabile Lösung für grundlegende Dateisysteme zu sein (zumindest in Linux). WoJ vor 12 Jahren 0
Ich möchte wirklich eine Lösung, die sich an die vorhandene FS anlehnt. Michael Pankov vor 11 Jahren 0
Vielleicht das? http://www.ext3cow.com Zac B vor 11 Jahren 0
3
Zac B

Ich denke, du bist auf dem richtigen Weg inotify. In diesem Artikel wird die grundlegende Verwendung in einem ähnlichen Fall beschrieben. Ich würde vorschlagen, es entweder direkt zu verwenden oder ein Dienstprogramm auf Kernel-Ebene wie fschange zu kompilieren . Dies ist etwas umständlich, aber Sie könnten dann die Erkennung von Änderungen an ein git commitoder ähnliches binden .

Diese Lösungen haben beide das Problem, sich auf etwas unvollständige Lösungen von Drittanbietern zu verlassen. Wenn es Ihnen nichts ausmacht, sich die Hände schmutzig zu machen, bietet NodeJS eine ausgezeichnete plattformübergreifende Einrichtung ( fs.watch ) für genau diesen Zweck. Ein grundlegendes Tutorial zum Überprüfen von Dateien auf Änderungen in NodeJS finden Sie hier . In ein paar Dutzend Zeilen oder weniger könnten Sie etwas schreiben, das ein Verzeichnis auf Dateien überwacht, und dann (über child_process ) ausschaltet und ein git commitoder ein ähnliches Programm ausführt (oder sogar einen Versionsdateiindex manuell inkrementiert, wenn Ihnen der roll-your- eigener Ansatz).

fs.watchwird von inotifyLinux unterstützt, ist aber viel intuitiver zu bedienen. Es gibt andere NodeJS-Projekte, die diese Funktion zum Überwachen von Dateien in verschiedenen Komfortniveaus einschließen, wie dieses oder dieses .

Immer noch keine fertige Lösung, und ich würde wahrscheinlich mit Pythons "inotify" gehen. Aber danke. Michael Pankov vor 11 Jahren 0
3
Mikhail Kupchik

Inotify (2) unter Linux kann keinen großen Baum überwachen, aber das Dateisystem (an einem separaten Speicherort gemountet) kann wahrscheinlich damit umgehen, indem die Dateisystemanforderungen in svn- oder git-Aufrufe übersetzt werden oder indem die svn / git-Metadaten direkt geändert werden.

Dies ist eine sehr interessante Idee, aber ich hatte bisher noch keine Implementierungen gehört.

Nehmen wir an, ich habe nur ein paar Dateien. Michael Pankov vor 11 Jahren 0
0
bdecaf

Ein solches Skript ist nicht schwer zu schreiben.

Meine Lieblingsversion ist git.

Folgendes Skript sollte es tun:

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

Lassen Sie das Verzeichnis regelmäßig überprüfen - oder, ob Ihr Editor nach dem Speichern scriptfähig ist.

Wenn Sie dies jedoch tun, kann es sinnvoll sein, große Dateien und einige "nutzlose" wie automatische Speicherplätze auszuschließen.

Ja, ich weiß, dass eine cron-basierte Lösung einfach zu implementieren ist. Ich bin jedoch auf der Suche nach etwas, das Version speichern würde, unabhängig vom Speichermechanismus. Dies ist auch der Grund, warum ich in meiner Frage autoversionninf auf svn sowie inotify erwähnt habe. WoJ vor 12 Jahren 0
0
FSMaxB

SparkleShare ( http://sparkleshare.org ) basiert auf git und implementiert eine Dropbox-Like-Funktionalität mit Versionskontrolle. Sie müssen jedoch einen ssh-Server einrichten (kann localhost sein).

Dieses Ding ist unbeholfen und erfordert viel Setup. Außerdem ist die Dropbox-Funktionalität nicht erforderlich. Michael Pankov vor 11 Jahren 0
0
Nehal Dattani

I'd recommend you to try NILFS. Refer the about page and you will be quicky able to decide whther is this the one what you are looking for or not.

HTH

0
Florin COJOCARU

Es gibt auch eine "arme" Methode, dies nur mit Rsync und einem Cron-Job zu tun. Sie verlassen sich im Wesentlichen auf die Sicherungsfunktion von rsync und verwenden zwei separate Pfade sowie ein Präfix / Suffix, um Ihre Dateien zu verfolgen.

Es sieht weniger aus wie folgt: / usr / bin / rsync -a -A -X --backup --suffix = date +".%Y-%m-%d_%H-%M-%S"$ source_path $ backup_path

Endergebnis: Wenn Sie eine Datei mit dem Namen test_rsync nach der ersten Ausführung im Quellpfad ändern, wird im Sicherungspfad eine Datei mit dem Namen test_rsync.2017-02-09_11-00-01 erstellt.

Es gibt eine Reihe von Problemen mit diesem (es funktioniert, wenn Sie nur eine anständige Anzahl von Dateien haben und bei Änderungen, die zwischen zwei aufeinanderfolgenden Rsync-Durchläufen (in meinem Fall 1 Minute) auftreten) fehlschlagen. Dies kann jedoch für Ihre Anforderungen ausreichend sein.

Wenn wir hier über Samba-Freigaben sprechen, könnte eine Ausschlussliste in Ordnung sein, ich bin noch nicht dazu gekommen.

Lassen Sie mich wissen, wenn Sie dies verbessern.

0
michael

Hier ist ein Python3-Skript, das VMS wie die automatische Dateiversion mit einem Zeitstempel ausführt, der beim Speichern an den ursprünglichen Dateinamen angehängt wird.

Ich habe ein paar Kommentare in das Skript eingefügt und ein halbes Dutzend solcher Skripts auf meinem Ubuntu-Rechner ausgeführt, wobei nur die Verzeichnisse in den verschiedenen Versionen des Skripts unterschiedlich sind, sodass ich gleichzeitig mehrere Verzeichnisse versioniere. Kein echter Nachteil für die Maschinenleistung.

! / usr / bin / env python3

print ("PROJECT FILES VERSIONING STARTED") print ("version_creation.py") #den gesamten Code in das Skript dieses Namens einfügen print ("run as .. 'python3 version_creation.py' von der Befehlszeile aus)" print ("ctrl") c 'to stop ") print (" ") print (" Um ein Programm im Hintergrund auszuführen, geben Sie unten die Befehlszeile ein und schließen Sie das Fenster. ") print (" nohup python3 version_creation.py ") print (" .... to Prozess stoppen go menu / administration / system monitor ... und kill python3 ") print (" "print (" Dateien immer im Verzeichnis "ProjectFiles" speichern und die Versionsdateien ") print (" wird auch in diesem Verzeichnis erstellt . ") print (" ") print (" ") print (" ") print (" ")

Import Shutil Import os Importzeit

--- Legen Sie das Zeitintervall für die Suche nach neuen Dateien (in Sekunden) fest

- Dieses Intervall sollte kleiner sein als das Intervall, in dem neue Dateien angezeigt werden!

t = 10

--- das Quellverzeichnis (dr1) und das Zielverzeichnis (dr2) einstellen

dr1 = "/ Pfad / zu / Quellverzeichnis"

dr2 = "/ Pfad / zu / Zielverzeichnis"

import glob import os

dr1 = "/ home / michael / ProjectFiles" # beide Originale und Versionen werden in diesem Verzeichnis gespeichert

dr2 = "/ home / michael / ProjectFileVersions"

während wahr:

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

drucken ("leer")

 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] 

drucken ("2 originalname =", originalname)

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

drucken ("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 

drucken ("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) 

Aktie

das unten wurde früher eingefügt und funktioniert, aber ich mag das obige Python-Skript viel besser ...... (habe Python seit ungefähr 3 Stunden verwendet)

#!/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