2012-05-26 2 views
6

Wenn der unten stehende Code ausgeführt wird, wird die Uhr nur ausgelöst, wenn ich tmp.txt manuell editiere und speichere, entweder mit meinem IDE, TextEditor .app oder vim.NodeJS fs.watch im Verzeichnis wird nur ausgelöst, wenn vom Editor geändert, aber nicht Shell oder fs Modul

Es ist nicht durch Verfahren des Schreibstroms oder manueller Shell Ausgabeumleitung (Eingabe echo „test“> /path/to/tmp.txt ").

Obwohl, wenn ich die Datei selbst sehen, und . nicht seine dirname, dann funktioniert es

var fs, Path, file, watchPath, w; 

fs = require('fs'); 
Path = require('path'); 
file = __dirname + '/tmp.txt'; 
watchPath = Path.dirname(file); // changing this to just file makes it trigger 

w = fs.watch (watchPath, function (e,f) { 
    console.log("will not get here by itself"); 
    w.close(); 
}); 
fs.writeFileSync(file,"test","utf-8"); 

fs.createWriteStream(file, { 
    flags:'w', 
    mode: 0777 
}) 
.end('the_date="'+new Date+'";'); // another method fails as well 

setTimeout (function() { 
    fs.writeFileSync(file,"test","utf-8"); 
},500); // as does this one 
// child_process exec and spawn fail the same way with or without timeout 

So sind die Fragen: warum und wie dieses Ereignis von einem Knoten Skript programmatisch triggern

Dank

+0

nur fs.watch ändern -> fs.watchFile und fertig. ref: [Git-Link] (https://github.com/joyent/node/issues/3640) – mayankcpdixit

Antwort

9

Es wird nicht ausgelöst, da eine Änderung des Inhalts einer Datei keine Änderung des Verzeichnisses ist.

Unter den Abdeckungen, mindestens ab 0.6, fs.watch auf dem Mac verwendet kqueue, und es ist eine ziemlich dünne Wrapper um kqueue Dateisystembenachrichtigungen. Also, wenn Sie die Details wirklich verstehen wollen, müssen Sie kqueue und Inodes und solche Dinge verstehen.

Aber wenn Sie eine kurze "Lüge-zu-Kinder" -Erklärung wollen: Was ein Benutzer als "Datei" betrachtet, ist wirklich zwei verschiedene Dinge - die eigentliche Datei und der Verzeichniseintrag, der auf die eigentliche Datei verweist. Auf diese Weise können Sie beispielsweise feste Links und Dateien erstellen, die auch nach dem Löschen noch gelesen und geschrieben werden können.

Wenn Sie in eine vorhandene Datei schreiben, wird im Allgemeinen keine Änderung am Verzeichniseintrag vorgenommen, sodass für jeden, der das Verzeichnis beobachtet, keine Änderungen angezeigt werden. Deshalb löst echo> tmp.txt Sie nicht aus.

Wenn Sie jedoch beispielsweise eine neue temporäre Datei schreiben und es dann über die alte Datei verschieben, das den Verzeichniseintrag ändert (es ein Zeiger auf die neue Datei an Stelle des alten zu machen), so werden Sie Lass dich erinnern. Deshalb löst TextEditor.app Sie aus.

9

Die dünne?! g ist, haben Sie gebeten, das Verzeichnis und nicht die Datei zu sehen.

Das Verzeichnis wird nicht aktualisiert, wenn die Datei geändert ist, z. B. über Shell-Umleitung; In diesem Fall wird die Datei geöffnet, geändert und geschlossen. Das Verzeichnis wird nicht geändert - nur die Datei ist.

Wenn Sie einen Texteditor verwenden, um eine Datei zu ändern, ist die übliche Reihe von System hinter den Kulissen ruft sieht wie folgt aus etwas:

fd = open("foo.new") 
write(fd, new foo contents) 
unlink("foo") 
rename("foo.new", "foo") 

diese Weise die foo Datei ist entweder ganz die alte Datei oder ganz die neue Datei, und es gibt keine Möglichkeit für eine "partielle Datei" mit den neuen Inhalten. Die Umbenennungsoperationen do ändern das Verzeichnis und lösen so die Verzeichnisüberwachung aus.

+0

Grundsätzlich die gleichen Informationen wie in meiner simultanen Antwort, aber ich denke, es ist lesbarer als meins, also bin ich upvoting es. – abarnert

+0

@abarnert: aber der Ping war eine gute Idee, deine Antwort ist definitiv auch die +1 wert. :) – sarnold

4

Obwohl die obigen Antworten vernünftig erscheinen, sind sie nicht ganz genau. Es ist tatsächlich eine sehr nützliche Funktion, um ein Verzeichnis für Dateiänderungen anzuhören, nicht nur "umbenennen". Ich denke, diese Funktion funktioniert wie erwartet in Windows und in Knoten 0.9.2 ist auch für Mac arbeiten, da sie zur FSEvents API geändert, die diese Funktion unterstützt:

Version 0.9.2 (Unstable)

Verwandte Themen