Phiên bản tự động khi thay đổi tệp (sửa đổi / tạo / xóa)


16

Tôi đang tìm kiếm một triển khai (trên Linux) của một cơ chế có thể tự động và minh bạch phiên bản bất kỳ thay đổi nào trong một thư mục (đệ quy). Đây được dự định là một bổ sung (có thể thay thế nếu tất cả các tính năng được yêu cầu có sẵn) cho phiên bản tiêu chuẩn (SVN, git, ...)

Một sản phẩm trên MS Windows thực hiện điều này là AutoVer (để có ý tưởng tốt hơn về các yêu cầu). Tôi rất thích có một cái gì đó tương tự nhưng nhắm vào Linux trong một môi trường phi đồ họa.

Tôi thấy rằng có một số nỗ lực để có chức năng này trên Linux, cách gần nhất tôi tìm thấy là tự động trên Subversion nhưng không rõ ràng khi thực hiện trên các môi trường hiện tại (ví dụ: các tệp cấu hình là cục bộ).

Có lẽ một cái gì đó làm việc với inotify?

Cảm ơn bạn trước cho bất kỳ con trỏ! Ái chà


liên quan: flashbake
Dan D.


Có yêu cầu đặc biệt nào về phần mềm bạn sử dụng không? Bởi vì nếu bạn chỉ tìm cách theo dõi các thay đổi bạn thực hiện thủ công (bằng cách chỉnh sửa các tệp), thì Eclipse có tính năng này tích hợp sẵn, nó được gọi là "lịch sử cục bộ".
Stefan Seidel

@StefanSeidel Tôi không phải là người bắt đầu chủ đề, nhưng tôi thích giải pháp không có IDE.
Michael Pankov

Câu trả lời:


5

1. Phương pháp mục đích chung sử dụng bazaar & inotify

Điều này chưa được tôi kiểm chứng nhưng tôi thấy bài viết này sử dụng bzr(bazaar) & inotifywaitđể theo dõi một thư mục và phiên bản kiểm soát các tệp trong đó bằng cách sử dụng bazaar.

Kịch bản này thực hiện tất cả công việc xem thư mục để thay đổi:

#!/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. Quản lý / v.v.

Đối với trường hợp đặc biệt của quản lý của hệ thống /etcthư mục, bạn có thể sử dụng ứng dụng etckeeper .

etckeeper là một tập hợp các công cụ để cho phép / etc được lưu trữ trong kho git, mercurial, darcs hoặc bzr. Nó móc vào apt (và các trình quản lý gói khác bao gồm yum và pacman-g2) để tự động cam kết thay đổi được thực hiện cho / etc trong quá trình nâng cấp gói. Nó theo dõi siêu dữ liệu tệp mà các hệ thống kiểm soát revison thường không hỗ trợ, nhưng điều đó rất quan trọng đối với / etc, chẳng hạn như các quyền của / etc / bóng. Nó khá mô-đun và cấu hình, trong khi cũng đơn giản để sử dụng nếu bạn hiểu những điều cơ bản khi làm việc với kiểm soát sửa đổi.

Đây là một hướng dẫn tốt để giúp bạn bắt đầu với nó.

3. Sử dụng git và incron

Kỹ thuật này sử dụng gitincron. Đối với phương pháp này, bạn cần làm như sau:

A. Làm một repo

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

B. Tạo một $HOME/bin/git-autocommitkịch bản

#!/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. Thêm một mục vào incrontab

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

4. Sử dụng Flashbake

Một tùy chọn khác là sử dụng một công cụ như Flashbake . Flashbake là hệ thống kiểm soát phiên bản mà Cory Doctorow (của danh tiếng BoingBaging) sử dụng để viết sách của mình.

Flashbake sử dụng git dưới mui xe để theo dõi các thay đổi nhưng nằm ở đâu đó giữa việc thực hiện sao lưu tự động và tự mình sử dụng hệ thống kiểm soát phiên bản đơn giản.

Cory muốn phiên bản này mang theo lời nhắc, ảnh chụp nhanh về nơi anh ta ở vào thời điểm một cam kết tự động xảy ra và những gì anh ta đang nghĩ. Tôi đã nhanh chóng phác thảo một tập lệnh Python để lấy thông tin theo ngữ cảnh mà anh ta muốn và bắt đầu hack cùng một tập lệnh shell để điều khiển git, sử dụng đầu ra của tập lệnh Python cho nhận xét cam kết khi một công việc cron gọi trình bao bọc.

Tài nguyên


3
inotifywait + "git local" = gitwatch.sh, xem tại đây: github.com/nevik/gitwatch/blob/master/gitwatch.sh
nghĩa tự làm

4

Ngay lập tức ZFS đến với tâm trí. Nó có thể tạo ảnh chụp nhanh - và có một số dự án để tự động tạo ảnh chụp nhanh .


Tôi đã đọc về ZFS nhưng có vẻ như nó không phải là một giải pháp ổn định cho các hệ thống tệp cơ bản (ít nhất là trong Linux)
WoJ

Tôi thực sự muốn có một giải pháp để nắm bắt được FS hiện có.
Michael Pankov

Có lẽ đây? ext3cow.com
Zac B

3

Tôi nghĩ rằng bạn đang đi đúng hướng inotify. Bài viết này chi tiết cách sử dụng cơ bản của nó trong trường hợp tương tự như của bạn. Tôi khuyên bạn nên sử dụng trực tiếp hoặc biên dịch tiện ích cấp kernel như fschange . Đây là một điều rắc rối, nhưng sau đó bạn có thể ràng buộc việc phát hiện các thay đổi thành một git commithoặc tương tự.

Những giải pháp đó đều có vấn đề dựa vào các giải pháp bên thứ ba không hoàn hảo. Nếu bạn không ngại bị bẩn tay, NodeJS cung cấp một cơ sở đa nền tảng tuyệt vời ( fs.watch ) cho mục đích chính xác này. Một hướng dẫn cơ bản về xem các tệp để thay đổi trong NodeJS có thể được tìm thấy ở đây . Trong vài chục dòng hoặc ít hơn, bạn có thể viết một cái gì đó theo dõi một thư mục cho các tệp, sau đó trình bày ra (thông qua child_ process ) và chạy một git commithoặc tương tự (hoặc thậm chí tăng thủ công chỉ mục tệp phiên bản, nếu bạn thích cuộn cách tiếp cận riêng).

fs.watchđược hỗ trợ bởi inotifylinux, nhưng sử dụng trực quan hơn rất nhiều. Có NodeJS dự án khác mà quấn rằng tập tin theo dõi chức năng trong cấp độ khác nhau của sự thuận tiện, giống như cái này hoặc cái này .


Vẫn chưa phải là một giải pháp sẵn sàng, và, có lẽ tôi sẽ đi với Python inotify. Nhưng cảm ơn.
Michael Pankov

3

inotify (2) trên Linux sẽ không thể xem một cây lớn, nhưng hệ thống tập tin cầu chì (được gắn ở vị trí riêng biệt) có thể có thể xử lý nó, bằng cách dịch các yêu cầu hệ thống tập tin sang các cuộc gọi svn hoặc git hoặc bằng cách thay đổi trực tiếp siêu dữ liệu svn / git.

Đây là một ý tưởng rất thú vị, nhưng tôi chưa từng nghe về bất kỳ triển khai nào hiện có.


Hãy nói rằng tôi chỉ có một vài tập tin.
Michael Pankov

0

Một kịch bản như vậy không khó để viết.

Kiểm soát phiên bản yêu thích của tôi là git.

kịch bản sau đây nên làm điều đó:

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

hoặc có định kỳ kiểm tra thư mục của bạn - hoặc nếu trình soạn thảo của bạn là cuộc gọi có thể script sau khi bạn lưu.

Nhưng nếu bạn làm như vậy thì có thể loại trừ các tệp lớn và có thể một số "vô dụng" như tự động.


Có, tôi biết rằng một giải pháp dựa trên cron là đơn giản để thực hiện. Tuy nhiên tôi đang tìm kiếm một cái gì đó sẽ phiên bản lưu, bất kể cơ chế lưu. Đây cũng là lý do tại sao tôi đề cập đến autoversionninf trên svn cũng như inotify trong câu hỏi của tôi.
WoJ

0

SparkleShare ( http : // spark Meatare.org ) dựa trên git và thực hiện chức năng Giống như Dropbox với kiểm soát phiên bản, nhưng bạn phải thiết lập máy chủ ssh (có thể là localhost).


Điều này là vụng về và đòi hỏi rất nhiều thiết lập. Bên cạnh đó, chức năng Dropbox là không cần thiết.
Michael Pankov

0

Tôi khuyên bạn nên thử NILFS. Tham khảo trang giới thiệu và bạn sẽ nhanh chóng có thể quyết định xem đây có phải là thứ bạn đang tìm kiếm hay không.

HTH


0

Ngoài ra còn có cách "người nghèo" làm việc này chỉ bằng rsync và công việc định kỳ. Về cơ bản, bạn dựa vào cơ sở sao lưu của rsync và sử dụng hai đường dẫn riêng biệt cộng với tiền tố / hậu tố để theo dõi các tệp của bạn.

Nó trông giống như thế này: / usr / bin / rsync -a -A -X --backup --suffix = date +".%Y-%m-%d_%H-%M-%S"$ source_path $ backup_path

Kết quả cuối cùng: Thay đổi tệp có tên test_rsync trong đường dẫn nguồn sau khi thực hiện ban đầu sẽ dẫn đến một tệp có tên test_rsync.2017-02-09_11-00-01 được tạo trong đường dẫn sao lưu.

Có một loạt vấn đề với điều này (nó hoạt động nếu bạn chỉ có một lượng tệp kha khá và sẽ thất bại với những thay đổi xảy ra giữa hai lần chạy rsync liên tiếp (trong 1 phút trong trường hợp của tôi)) nhưng nó có thể đủ cho nhu cầu của bạn.

Nếu chúng ta đang nói ở đây về samba chia sẻ một danh sách loại trừ có thể theo thứ tự, thì tôi vẫn chưa hiểu về điều đó.

Hãy cho tôi biết nếu bạn cải thiện điều này.


0

Dưới đây là tập lệnh Python3 thực hiện VMS như phiên bản tệp tự động bằng cách sử dụng dấu thời gian được gắn vào tên tệp gốc khi được lưu.

Tôi đã đưa một loạt các bình luận vào tập lệnh và chạy một nửa tá các tập lệnh như vậy trên máy ubfox của tôi với chỉ các thư mục khác nhau trong mỗi phiên bản khác nhau của tập lệnh để tôi đồng thời phiên bản nhiều thư mục. Không có hình phạt thực sự cho hiệu suất máy.

! / usr / bin / env python3

print ("DỰ ÁN PHIÊN BẢN PHIÊN BẢN BẮT ĐẦU") print ("version_creation.py") # đặt tất cả mã này vào tập lệnh của tên in này ("chạy dưới dạng .. 'python3 version_creation.py' từ dòng lệnh") print ("ctrl ' c 'to stop ") print (" ") print (" Để chạy chương trình ở loại nền bên dưới dòng lệnh và sau đó đóng cửa sổ. ") print (" nohup python3 version_creation.py ") print (" .... to dừng quá trình đi menu / quản trị / giám sát hệ thống ... và in python3 ") print (" ") print (" Luôn lưu tệp vào thư mục 'ProjectFiles' và tệp phiên bản ") print (" cũng sẽ được tạo trong thư mục đó . ") in (" ") in (" ") in (" ") in (" ")

nhập khẩu đóng cửa nhập khẩu os thời gian nhập khẩu

--- đặt khoảng thời gian để kiểm tra các tệp mới (tính bằng giây) bên dưới

- khoảng thời gian này phải nhỏ hơn khoảng thời gian các tệp mới xuất hiện!

t = 10

--- đặt thư mục nguồn (dr1) và thư mục đích (dr2)

dr1 = "/ đường dẫn / đến / source_directory"

dr2 = "/ đường dẫn / đến / target_directory"

nhập khẩu toàn cầu os nhập khẩu

dr1 = "/ home / michael / ProjectFiles" #both bản gốc và phiên bản sẽ được lưu vào thư mục này

dr2 = "/ nhà / michael / ProjectFileVersions"

trong khi Đúng:

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

in ("Trống")

    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)

in ("1 Recent_file_path =", mới nhất_file_path)

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

in ("2 gốcname =", tên gốc)

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

in ("filecreation =", filecreation)

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

in ("fivesec_ago =", fivesec_ago)

    timedif = fivesec_ago - filecreation #time between file creation

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

chia sẻ

bên dưới đã được đưa vào sớm hơn và hoạt động nhưng tôi thích kịch bản python ở trên tốt hơn nhiều ...... (đã sử dụng python trong khoảng 3 giờ)

#!/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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.