web-dev-qa-db-fra.com

Comment enregistrer l'accès à un dossier spécifique et les modifications de son contenu?

J'ai besoin de suivre le temps d'accès au dossier et je veux savoir quelles modifications y sont apportées.

Comment déclencher ces événements? Existe-t-il un moyen d'exécuter un fichier .sh spécifique lorsque le dossier est ouvert?

2
tvshajeer

Je suppose que vous devez connaître l'heure (d'horloge) d'ouverture du dossier, par ex. nautilus , pas le temps nécessaire pour accéder au dossier.

Utilisation de la liste des fenêtres

Vous pouvez obtenir la liste des fenêtres à partir de la commande wmctrl -l, et voyez si le nom du dossier apparaît dans la liste. La boucle à vérifier prendrait cependant au moins une fraction de seconde pour remarquer que le dossier est ouvert.

Vous auriez wmctrl à installer:

Sudo apt-get install wmctrl

Dans l'exemple ci-dessous, le script exécute une commande lorsqu'un dossier est accédé pour la première fois et se ferme.

Comment utiliser:

  • Collez le script dans un fichier vide
  • Enregistrez-le sous access_time.py
  • Changement dans la section head du script "<command_to_run>" par votre commande (entre guillemets)
  • Exécutez-le soit avec la commande:

    python3 </path/to/script> <foldername_without_path>
    

    ou, si vous l'avez rendu exécutable:

    </path/to/access_time.py> <foldername_without_path>
    
#!/usr/bin/env python3
import subprocess
import sys
#--- replace "<command_to_run>" with your command (between quotes):
command = "<command_to_run>"
#---
foldername = sys.argv[1]
while True:
    try:
        test = subprocess.check_output(["wmctrl", "-l"]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass
    if foldername in test:
        subprocess.call(["/bin/bash", "-c", command])
        break

Modifier

Vous pouvez cependant le faire fonctionner "tout-en-un", vous n'avez donc pas besoin d'un autre script. Le script ci-dessous crée un fichier dans votre répertoire $ HOME avec l'heure à laquelle votre dossier a été accédé .:

#!/usr/bin/env python3
import subprocess
import sys
import os
import time
home = os.environ["HOME"]
foldername = sys.argv[1]

#--- the path your file is saved to (change if you want to, but use full paths)
path = home
#---

while True:
    try:
        test = subprocess.check_output(["wmctrl", "-l"]).decode("utf-8")
    except subprocess.CalledProcessError:
        pass
    if foldername in test:
        with open(path+"/time_data.txt", "a") as out:
            out.write("the folder "+foldername+" was opened "+time.ctime()+"\n")
        break
  • Utilisez-le comme la première option (mais vous n'avez évidemment pas besoin de définir la commande)
  • Placez un point avant le nom de fichier pour en faire un fichier caché (appuyez sur Ctrl+H pour basculer la visibilité):

    Si vous le souhaitez, changez:

    with open(path+"/time_data.txt", "a") as out:
    

    dans:

    with open(path+"/.time_data.txt", "a") as out:
    

    (Attention au tiret!)

Édition 2

D'après vos commentaires et la discussion dans le chat, je comprends que vous recherchez en fait un outil pour enregistrer l'accès à un dossier (par exemple par nautilus) et les modifications du contenu de celui-ci.
En option supplémentaire, un script de journal complet qui enregistre dans deux threads différents:

  • Toutes les occasions où le dossier a été consulté par ex. nautilus, connecté dans un fichier access_log.txt
  • Toutes les occasions où la fenêtre du dossier a été fermée, également connecté access_log.txt
  • Tous les fichiers qui ont été ajoutés (récursivement) ou supprimés du répertoire, connectés à un fichier directory_log.txt

Ces événements sont enregistrés dans deux fichiers différents, car les journaux ont des temps d'actualisation différents. L'enregistrement en temps réel de ce qui arrive à un grand répertoire avec beaucoup de sous-répertoires n'est pas quelque chose que vous voudriez faire toutes les 5 secondes environ. La conséquence est que:

  • le journal d'accès a (comme je l'ai défini) une précision de 0,5 seconde
  • le journal du répertoire (ajout/suppression de fichiers) a une précision de 10 minutes. Les événements seront signalés dans les 10 minutes suivant leur déroulement, avec une précision d'horodatage de 10 minutes.

    Je l'ai testé sur un répertoire (réseau) de ~ 800 Go. Si votre répertoire est beaucoup plus petit, le cycle de journalisation du répertoire peut également être (beaucoup) plus petit. Je l'ai testé par exemple sur un répertoire de 20 Go, avec un cycle (journal de répertoire) de 10 secondes.

Exemple de sortie access_log.txt:

---------------Thu Feb 19 21:01:09 2015---------------
folder opened

---------------Thu Feb 19 21:01:27 2015---------------
folder closed

Exemple de sortie directory_log.txt:

---------------Thu Feb 19 21:14:24 2015---------------
+ /home/jacob/Afbeeldingen/Downloads/2023.pdf
- /home/jacob/Afbeeldingen/Downloads/History-journal
- /home/jacob/Afbeeldingen/Downloads/google-earth-stable_current_i386.deb

Le script:

  • Configurez-le comme les scripts ci-dessus avec une différence importante:

    • au lieu d'utiliser le nom du dossier comme argument , définissez la valeur complète chemin + le nom du dossier dans la tête du script (voir l'exemple dans le script)
  • La commande pour l'exécuter est alors:

    python3 /path/to/script.py
    
#!/usr/bin/env python3
import subprocess
import os
import time
import difflib
from threading import Thread
home = os.environ["HOME"]

# The folder to watch:
folder = "/home/jacob/Afbeeldingen"
# the path your log files are saved to (change if you want to, but use full paths):
path = home
#---

for f in os.listdir(path):
    if f.startswith("dr_check_"):
        os.remove(path+"/"+f)

dr_data = path+"/directory_log.txt"
access_data = path+"/access_log.txt"

for f in [dr_data, access_data]:
    if not os.path.exists(f):
        subprocess.Popen(["touch", f])       
foldername = folder.split("/")[-1]

def check_windowlist(foldername):
    while True:
        try:
            if foldername in subprocess.check_output(["wmctrl", "-l"]).decode("utf-8"):
                return "folder opened\n"
            else:
                return "folder closed\n"
            break
        except subprocess.CalledProcessError:
            pass

def check_directory(directory, outfile):
    with open(outfile, "wt") as out:
        for root, dirs, files in os.walk(directory):
            for f in files:
                out.write(root+"/"+f+"\n")

def run_accesscheck():
    while True:
        ch1 = check_windowlist(foldername)
        time.sleep(0.5)
        ch2 = check_windowlist(foldername)
        if ch1 != ch2:
            with open(access_data, "a") as out:
                out.write("-"*15+time.ctime()+"-"*15+"\n"+ch2+"\n")

def run_directorycheck():
    last = 1; outfile_name = "dr_check_"; last_outfile = ""
    while True:
        outfile = path+"/"+outfile_name+str(last)+".txt"
        check_directory(folder, outfile)
        if last != 1:
            changes = []
            diff = difflib.ndiff(
                open(last_outfile).readlines(),
                open(outfile).readlines()
                )
            for item in diff:
                if item.startswith("-") or item.startswith("+"):
                    changes.append(item)
            if len(changes) > 0:
                with open(dr_data, "a") as out:
                    out.write("-"*15+time.ctime()+"-"*15+"\n")
                    for it in sorted(changes):
                        out.write(it)
                    out.write("\n")
            os.remove(last_outfile)       
        last_outfile = outfile; last = last+1
        time.sleep(600)

Thread(target = run_directorycheck).start()
Thread(target = run_accesscheck).start()
3
Jacob Vlijm

Si vous souhaitez utiliser Bash à la place de Python:

#!/bin/bash
folder=$1
while true;
do
    command=$(wmctrl -l | grep -o "$folder")
    if [[ "$folder" == "$command" ]];
    then
        ./myscript.sh
        break;
    fi
done

Éditer:

J'ai changé un script pour que vous puissiez l'exécuter avec la commande suivante:

bash folderwatch.sh BackupSSD

En outre, vous pouvez rendre un script exécutable afin de pouvoir l'utiliser sans sh ni bash, car le shell est défini dans la première ligne du script, par exemple:

chmod u+x folderwatch.sh
./folderwatch.sh BackupSSD
1
Panta

Sudo apt-get incron pour installer le système "inotify cron"

http://inotify.aiken.cz/?section=incron&page=about&lang=en

echo $USER | Sudo tee --append /etc/incron.allow pour vous permettre de jouer au jeu.

icrontab -e pour créer un événement à regarder. Il ouvre nano.

Entrez le désir de votre cœur. par exemple.,

/home/nodak/watched_dir IN_ACCESS /home/nodak/bin/personal.sh

Enregistrez et testez.

Plus d'informations sur http://manpages.ubuntu.com/manpages/saucy/man5/incrontab.5.html

Bien qu'elle soit simple et trompeuse, la syntaxe des manœuvres compliquées n'est pas tout à fait la même que régulière bash, cf, https://stackoverflow.com/questions/23706194/using-zenity-in-a-root-incron-job-to-display-message-to-currently-logged-in-user

0
Nodak