web-dev-qa-db-ja.com

ファイル変更時の自動バージョン管理(変更/作成/削除)

ディレクトリ内の変更を(再帰的に)自動的かつ透過的にバージョン管理するメカニズムの実装(Linux上)を探しています。これは、標準バージョン管理(SVN、git、...)への追加(要求されたすべての機能が利用可能な場合は置換)を目的としています。

これを行うMS Windows上の製品は AutoVer です(要件をよりよく理解するため)。私はそのようなものが欲しいのですが、非グラフィカル環境のLinuxを対象としています。

Linuxでこの機能を使用しようとする試みがいくつかあることがわかりました。最も近いのは、 Subversionでの自動バージョン管理 ですが、既存の環境(たとえば、構成ファイルがあるサーバー)に実装することは明らかではありません。地元)。

多分inotifyで動作する何か?

よろしくお願いします! WoJ

16
WoJ

1. Bazaar&inotifyを使用した汎用メソッド

これは私によってテストされていませんが、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の管理

システムの/etcディレクトリを管理する特別な場合は、アプリ etckeeper を使用できます。

etckeeperは、/ etcをgit、Mercurial、darcs、またはbzrリポジトリに保存できるようにするツールのコレクションです。 apt(およびyumとpacman-g2を含む他のパッケージマネージャー)をフックして、パッケージのアップグレード中に/ etcに加えられた変更を自動的にコミットします。これは、リビジョン制御システムが通常サポートしていないファイルメタデータを追跡しますが、/ etc/shadowのアクセス許可など、/ etcにとって重要です。非常にモジュール化されて構成可能であると同時に、リビジョン管理の操作の基本を理解していれば簡単に使用できます。

ここに 良いチュートリアル があります。

3.gitとincronを使用する

この手法では、gitincronを利用します。この方法では、次のことを行う必要があります。

A。レポを作成する

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

B。$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名声の)Cory Doctorowが彼の本を書くために使用するバージョン管理システムです。

Flashbakeは内部でgitを使用して変更を追跡しますが、自動バックアップを実行することと、プレーンバージョン管理システムを自分で使用することの間のどこかにあります。

Coryは、バージョンにプロンプ​​ト、自動コミットが発生したときの彼のスナップショット、および彼が考えていたものを伝えることを望んでいました。私はすぐにPythonスクリプトをスケッチして、彼が必要とするコンテキスト情報を引き出し、Pythonスクリプトの出力を使用して、シェルスクリプトをハッキングしてgitを駆動し始めました。 cronジョブがシェルラッパーを呼び出したときにコメントをコミットします。

資源

6
slm

すぐに [〜#〜] zfs [〜#〜] が頭に浮かぶ。それはスナップショットを作成できます-そして 自動的にスナップショットを作成する するいくつかのプロジェクトがあります.

4
bdecaf

あなたはinotifyで正しい方向に進んでいると思います。 この記事 は、あなたと同じような場合の基本的な使用法を詳しく説明しています。直接使用するか、 fschange のようなカーネルレベルのユーティリティをコンパイルすることをお勧めします。これは面倒なことですが、変更の検出をgit commitなどにバインドできます。

これらのソリューションはどちらも、やや不完全なサードパーティのソリューションに依存するという問題があります。手を汚してもかまわないのであれば、 NodeJS は、まさにこの目的のために、優れたクロスプラットフォーム機能( fs.watch )を提供します。 NodeJSの変更をファイルで監視する基本的なチュートリアルは、 ここ にあります。数十行以内で、ファイルのディレクトリを監視し、( child_process を介して)シェルアウトしてgit commitなどを実行する(または手動でインクリメントする)ものを作成できます。独自のアプローチが好きな場合は、バージョンファイルインデックス)。

fs.watchはLinuxではinotifyによってサポートされていますが、使用する方がはるかに直感的です。 this one または this one のように、ファイル監視機能をさまざまなレベルの利便性でラップするNodeJSプロジェクトが他にもあります。

3
Zac B

linuxのinotify(2)は大きなツリーを監視できませんが、(別の場所にマウントされた)Fuseファイルシステムは、ファイルシステム要求をsvnまたはgit呼び出しに変換するか、svn/gitメタデータを直接変更することで、おそらくそれを処理できます。

これは非常に興味深いアイデアですが、既存の実装について聞いたことがありませんでした。

3
Mikhail Kupchik

これは、保存時に元のファイル名に追加されたタイムスタンプを使用して自動ファイルバージョン管理のようなVMSを実行するPython3スクリプトです。

私はたくさんの解説をスクリプトに入れて、ubuntuマシンでそのようなスクリプトを半ダース実行しました。スクリプトのバージョンごとにディレクトリが異なるだけなので、複数のディレクトリを同時にバージョン管理しています。マシンのパフォーマンスに実際のペナルティはありません。

!/ usr/bin/env python3

print( "PROJECT FILES VERSIONING STARTED")print( "version_creation.py")#この名前のスクリプトにこのすべてのコードを配置しますprint( "run as .. 'python3 version_creation.py' from command line")print( "ctrl ' c'to stop ")print(" ")print("以下のバックグラウンドでプログラムを実行するには、コマンドラインに入力してからウィンドウを閉じます。 ")print(" Nohup python3 version_creation.py ")print(" .... toプロセスを停止しますgo menu/administration/system monitor ... and kill python3 ")print(" ")print(" Always save files to the 'ProjectFiles' directory and the version files ")print("もそのディレクトリに作成されます。 ")print(" ")print(" ")print(" ")print(" ")

import shutil import os import time

---以下の新しいファイルをチェックする時間間隔(秒単位)を設定します

-この間隔は、新しいファイルが表示される間隔よりも小さくする必要があります。

t = 10

---ソースディレクトリ(dr1)とターゲットディレクトリ(dr2)を設定します

dr1 = "/ path/to/source_directory"

dr2 = "/ path/to/target_directory"

import glob import os

dr1 = "/ home/michael/ProjectFiles"#オリジナルとバージョンの両方がこのディレクトリに保存されます

dr2 = "/ home/michael/ProjectFileVersions"

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)

印刷( "1Latest_file_path ="、latest_file_path)

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

印刷( "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

印刷( "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
michael

Rsyncとcronジョブのみを使用してこれを行う「貧乏人」の方法もあります。基本的にrsyncのバックアップ機能に依存し、ファイルを追跡するために2つの別々のパスとプレフィックス/サフィックスを使用します。

/ 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の2つの連続した実行(私の場合は1分)の間に発生する変更では失敗します)が、ニーズには十分かもしれません。

ここでsamba共有について話している場合、除外リストが適切である可能性がありますが、まだそれを回避していないのではないかと思います。

これを改善するかどうか教えてください。

0
Florin COJOCARU

SparkleShare( http://sparkleshare.org )はgitに基づいており、バージョン管理を備えたDropboxのような機能を実装していますが、ssh-server(localhostにすることもできます)を設定する必要があります。

0
FSMaxB

このようなスクリプトを書くのは難しくありません。

私のお気に入りのバージョン管理はgitです。

次のスクリプトで実行する必要があります。

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

定期的にディレクトリを確認するか、保存後にエディターがスクリプト可能な呼び出しかどうかを確認してください。

しかし、このようにすると、大きなファイルや自動保存のような「役に立たない」ファイルを除外するのが理にかなっているかもしれません。

0
bdecaf

NILFSを試すことをお勧めします。 ページについて を参照すると、これが探しているものであるかどうかをすばやく判断できます。

HTH

0
Nehal Dattani