Versi otomatis setelah perubahan file (modifikasi / buat / hapus)

16

Saya mencari implementasi (di Linux) dari suatu mekanisme yang secara otomatis dan transparan akan membuat perubahan dalam direktori (secara rekursif). Ini dimaksudkan sebagai tambahan (mungkin penggantian jika semua fitur yang diminta tersedia) ke versi standar (SVN, git, ...)

Produk pada MS Windows yang melakukan ini adalah AutoVer (untuk memiliki gagasan yang lebih baik tentang persyaratan). Saya ingin memiliki sesuatu seperti itu tetapi ditujukan untuk Linux dalam lingkungan non-grafis.

Saya melihat bahwa ada beberapa upaya untuk memiliki fungsi ini di Linux, yang terdekat saya temukan adalah autoversionning pada Subversion tetapi tidak jelas untuk diterapkan pada lingkungan yang ada (server di mana, misalnya, file konfigurasi adalah lokal).

Mungkin sesuatu bekerja dengan inotify?

Terima kasih sebelumnya untuk petunjuk apa pun! WoJ

WoJ
sumber
terkait: flashbake
Dan D.
Apakah ada persyaratan khusus tentang perangkat lunak yang Anda gunakan? Karena jika Anda hanya ingin melacak perubahan yang Anda lakukan secara manual (dengan mengedit file), Eclipse memiliki fitur bawaan, itu disebut "sejarah lokal".
Stefan Seidel
@StefanSeidel Saya bukan pemula topik, tapi saya lebih suka solusi no-IDE.
Michael Pankov

Jawaban:

5

1. Metode tujuan umum menggunakan bazaar & inotify

Ini belum diuji oleh saya, tetapi saya menemukan penulisan ini yang menggunakan bzr(bazaar) & inotifywaituntuk memantau direktori dan versi mengontrol file di dalamnya menggunakan bazaar.

Script ini melakukan semua pekerjaan menonton direktori untuk perubahan:

#!/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. Mengelola / dll

Untuk kasus khusus mengelola /etcdirektori sistem Anda, Anda dapat menggunakan aplikasi dllkeeper .

etckeeper adalah kumpulan alat untuk membiarkan / etc disimpan dalam repositori git, mercurial, darcs, atau bzr. Itu terhubung ke apt (dan manajer paket lainnya termasuk yum dan pacman-g2) untuk secara otomatis melakukan perubahan yang dibuat ke / dll selama peningkatan paket. Ini melacak metadata file yang sistem kontrol revisi biasanya tidak mendukung, tapi itu penting untuk / etc, seperti izin / etc / shadow. Ini cukup modular dan dapat dikonfigurasi, sementara juga mudah digunakan jika Anda memahami dasar-dasar bekerja dengan kontrol revisi.

Berikut tutorial yang bagus untuk memulai.

3. Menggunakan git dan incron

Teknik ini memanfaatkan gitdan incron. Untuk metode ini, Anda perlu melakukan hal berikut:

A. Buat repo

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

B. Buat $HOME/bin/git-autocommitskrip

#!/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. Tambahkan entri ke incrontab

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

4. Menggunakan Flashbake

Pilihan lain adalah menggunakan alat seperti Flashbake . Flashbake adalah sistem kontrol versi yang digunakan Cory Doctorow (dari BoingBoing fame) untuk menulis buku-bukunya.

Flashbake menggunakan git di bawah tenda untuk melacak perubahan tetapi berada di antara melakukan backup otomatis dan menggunakan sistem kontrol versi biasa.

Cory ingin versi itu membawa prompt, snapshot dari di mana dia pada saat komit otomatis terjadi dan apa yang dia pikirkan. Saya dengan cepat membuat skrip Python untuk menarik informasi kontekstual yang dia inginkan dan mulai meretas skrip shell untuk menggerakkan git, menggunakan output skrip Python untuk komentar komit ketika pekerjaan cron memanggil pembungkus shell.

Sumber daya

slm
sumber
3
inotifywait + "git local" = gitwatch.sh, lihat di sini: github.com/nevik/gitwatch/blob/master/gitwatch.sh
diyism
4

Segera ZFS terlintas dalam pikiran. Itu dapat membuat snapshot - dan ada beberapa proyek untuk secara otomatis membuat snapshots .

bdecaf
sumber
Saya membaca tentang ZFS tetapi sepertinya itu bukan solusi yang stabil untuk sistem file dasar (setidaknya di Linux)
WoJ
Saya benar-benar ingin solusi untuk memanfaatkan FS yang ada.
Michael Pankov
Mungkin ini ext3cow.com
Zac B
3

Saya pikir Anda berada di jalur yang benar inotify. Artikel ini merinci penggunaan dasarnya dalam kasus yang mirip dengan milik Anda. Saya menyarankan untuk menggunakannya secara langsung, atau mengkompilasi utilitas tingkat kernel seperti fschange . Ini adalah sesuatu yang merepotkan, tetapi Anda kemudian dapat mengikat deteksi perubahan ke git commitatau serupa.

Kedua solusi tersebut memiliki masalah mengandalkan solusi pihak ketiga yang agak tidak sempurna. Jika Anda tidak keberatan mengotori tangan Anda, NodeJS menyediakan fasilitas lintas platform yang sangat baik ( fs.watch ) untuk tujuan yang tepat ini. Tutorial dasar menonton file untuk perubahan di NodeJS dapat ditemukan di sini . Dalam beberapa lusin baris atau kurang, Anda bisa menulis sesuatu yang mengawasi direktori untuk file, dan kemudian keluar (melalui child_process ) dan menjalankan git commitatau serupa (atau bahkan secara manual menambah indeks file versi, jika Anda suka roll-your- pendekatan sendiri).

fs.watchdidukung oleh inotifydi linux, tetapi jauh lebih intuitif untuk digunakan. Ada proyek NodeJS lain yang membungkus fungsi menonton file dalam berbagai tingkat kenyamanan, seperti ini atau ini .

Zac B
sumber
Masih bukan solusi yang siap, dan, well, saya mungkin akan pergi dengan Python inotify. Tapi terima kasih.
Michael Pankov
3

inotify (2) di Linux tidak akan dapat menonton pohon besar, tetapi sistem file sekering (dipasang di lokasi yang terpisah) mungkin bisa mengatasinya, dengan menerjemahkan permintaan sistem file ke panggilan svn atau git, atau dengan mengubah metadata svn / git secara langsung.

Ini adalah ide yang sangat menarik, tetapi saya belum pernah mendengar implementasi yang ada.

Mikhail Kupchik
sumber
Katakanlah saya hanya memiliki beberapa file.
Michael Pankov
0

Naskah seperti itu tidak sulit untuk ditulis.

Kontrol versi favorit saya adalah git.

skrip berikut harus melakukannya:

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

baik yang secara berkala memeriksa direktori Anda - atau jika editor Anda panggilan skrip setelah Anda simpan.

Tetapi jika Anda melakukannya seperti ini mungkin masuk akal untuk mengecualikan file besar dan mungkin beberapa "tidak berguna" seperti autosave.

bdecaf
sumber
Ya saya tahu bahwa solusi berbasis cron mudah diterapkan. Namun saya mencari sesuatu yang akan versi pada save, tidak peduli mekanisme save. Ini juga mengapa saya menyebutkan autoversionninf di svn dan juga tidak memberitahukan pertanyaan saya.
WoJ
0

SparkleShare ( http://sparkleshare.org ) didasarkan pada git dan mengimplementasikan fungsionalitas seperti-Dropbox dengan kontrol versi, tetapi Anda harus menyiapkan server ssh (bisa menjadi host lokal).

FSMaxB
sumber
Hal ini kikuk dan membutuhkan banyak pengaturan. Selain itu, fungsionalitas Dropbox tidak diperlukan.
Michael Pankov
0

Saya sarankan Anda untuk mencoba NILFS. Lihat halaman tentang dan Anda akan dapat dengan cepat memutuskan di mana ini yang Anda cari atau tidak.

HTH

Nehal Dattani
sumber
0

Ada juga cara "orang miskin" melakukan ini hanya dengan menggunakan rsync dan pekerjaan cron. Anda pada dasarnya mengandalkan fasilitas cadangan rsync dan menggunakan dua jalur terpisah ditambah awalan / akhiran untuk melacak file Anda.

Ini lebih kurang terlihat seperti ini: / usr / bin / rsync -a -A -X --backup --suffix = date +".%Y-%m-%d_%H-%M-%S"$ source_path $ backup_path

Hasil akhir: Mengubah file yang disebut test_rsync di jalur sumber setelah eksekusi awal akan menghasilkan file yang disebut test_rsync.2017-02-09_11-00-01 yang dibuat di jalur cadangan.

Ada banyak masalah dengan ini (ini berfungsi jika Anda memiliki jumlah file yang layak saja dan akan gagal untuk perubahan yang terjadi antara dua kali berturut-turut rsync (1 menit dalam kasus saya)) tetapi mungkin cukup untuk kebutuhan Anda.

Jika kita berbicara di sini tentang samba berbagi daftar pengecualian mungkin dalam urutan, belum sempat untuk itu, aku takut.

Beri tahu saya jika Anda memperbaiki ini.

Florin COJOCARU
sumber
0

Berikut ini adalah skrip Python3 yang membuat VMS menyukai versi file otomatis menggunakan cap waktu yang ditambahkan ke nama file asli saat disimpan.

Saya telah memasukkan banyak komentar ke dalam skrip dan menjalankan setengah lusin skrip seperti itu di mesin ubuntu saya dengan hanya direktori yang berbeda di setiap versi skrip yang berbeda sehingga saya secara bersamaan memversi banyak direktori. Tidak ada penalti nyata untuk kinerja alat berat.

! / usr / bin / env python3

print ("PROYEK FILES VERSIONING STARTED") print ("version_creation.py") # tempatkan semua kode ini ke dalam skrip dari print nama ini ("run as .. 'python3 version_creation.py' dari command line") print ("ctrl ' c 'untuk berhenti ") cetak (" ") cetak (" Untuk menjalankan program di latar belakang ketik di bawah ini untuk baris perintah dan kemudian tutup jendela. ") cetak (" nohup python3 version_creation.py ") cetak (" .... untuk hentikan proses buka menu / administrasi / monitor sistem ... dan bunuh python3 ") print (" ") print (" Selalu simpan file ke direktori 'ProjectFiles' dan file versi ") print (" juga akan dibuat di direktori itu . ") print (" ") print (" ") print (" ") print (" ")

import shutil import os import time

--- atur interval waktu untuk memeriksa file baru (dalam detik) di bawah ini

- Interval ini harus lebih kecil daripada interval file baru muncul!

t = 10

--- atur direktori sumber (dr1) dan direktori target (dr2)

dr1 = "/ path / ke / source_directory"

dr2 = "/ path / ke / target_directory"

impor global impor os

dr1 = "/ home / michael / ProjectFiles" #keduanya asli dan versi akan disimpan ke direktori ini

dr2 = "/ home / michael / ProjectFileVersions"

sementara Benar:

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

cetak ("Kosong")

    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)

Bagikan

di bawah ini dimasukkan sebelumnya dan berfungsi tetapi saya suka skrip python di atas jauh lebih baik ...... (telah menggunakan python selama sekitar 3 jam)

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