# include " wtr/watcher.hpp "
# include < iostream >
# include < string >
using namespace std ;
using namespace wtr ;
// The event type, and every field within it, has
// string conversions and stream operators. All
// kinds of strings -- Narrow, wide and weird ones.
// If we don't want particular formatting, we can
// json-serialize and show the event like this:
// some_stream << event
// Here, we'll apply our own formatting.
auto show (event e) {
cout << to<string>(e. effect_type ) + ' '
+ to<string>(e. path_type ) + ' '
+ to<string>(e. path_name )
+ (e. associated ? " -> " + to<string>(e. associated -> path_name ) : " " )
<< endl;
}
auto main () -> int {
// Watch the current directory asynchronously,
// calling the provided function on each event.
auto watcher = watch ( " . " , show);
// Do some work. (We'll just wait for a newline.)
getchar ();
// The watcher would close itself around here,
// though we can check and close it ourselves.
return watcher. close () ? 0 : 1 ;
} # Sigh
PLATFORM_EXTRAS= $( test " $( uname ) " = Darwin && echo ' -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -framework CoreFoundation -framework CoreServices ' )
# Build
eval c++ -std=c++17 -Iinclude src/wtr/tiny_watcher/main.cpp -o watcher $PLATFORM_EXTRAS
# Run
./watcher #include "wtr/watcher-c.h"
#include <stdio.h>
void callback ( struct wtr_watcher_event event , void * _ctx ) {
printf (
"path name: %s, effect type: %d path type: %d, effect time: %lld, associated path name: %sn" ,
event . path_name ,
event . effect_type ,
event . path_type ,
event . effect_time ,
event . associated_path_name ? event . associated_path_name : ""
);
}
int main () {
void * watcher = wtr_watcher_open ( "." , callback , NULL );
getchar ();
return ! wtr_watcher_close ( watcher );
}pip install wtr-watcher from watcher import Watch
with Watch ( "." , print ):
input ()cargo add wtr-watcher tokio futures use futures :: StreamExt ;
use wtr_watcher :: Watch ;
# [ tokio :: main ( flavor = "current_thread" ) ]
async fn main ( ) -> Result < ( ) , Box < dyn std :: error :: Error > > {
let show = |e| async move { println ! ( "{e:?}" ) } ;
let events = Watch :: try_new ( "." ) ? ;
events . for_each ( show ) . await ;
Ok ( ( ) )
} import * as watcher from 'watcher' ;
var w = watcher . watch ( '.' , ( event ) => {
console . log ( event ) ;
} ) ;
process . stdin . on ( 'data' , ( ) => {
w . close ( ) ;
process . exit ( ) ;
} ) ;ผลลัพธ์ของแต่ละรายการข้างต้นจะเป็นสิ่งนี้ขึ้นอยู่กับรูปแบบ:
modify file /home/e-dant/dev/watcher/.git/refs/heads/next.lock
rename file /home/e-dant/dev/watcher/.git/refs/heads/next.lock -> /home/e-dant/dev/watcher/.git/refs/heads/next
create file /home/e-dant/dev/watcher/.git/HEAD.lock
สนุก!
ผู้เฝ้าดูเหตุการณ์ระบบไฟล์ซึ่งเป็น
ฉันพยายามรักษาสาย 1579 ที่ประกอบขึ้นเป็นรันไทม์ของ Watcher ค่อนข้างง่ายและ API ใช้งานได้จริง:
auto w = watch(path, [](event ev) { cout << ev; });wtr.watcher ~ผู้เฝ้าดู อาจใช้เป็น ห้องสมุดโปรแกรมหรือทั้งสองอย่าง หากคุณไม่ต้องการสร้างบางสิ่งบางอย่างกับห้องสมุดไม่ต้องกังวล เพียงแค่ใช้ของเราและคุณมีผู้เฝ้าดูระบบไฟล์ซึ่งพิมพ์เหตุการณ์ระบบไฟล์เป็น JSON ประณีต. นี่คือวิธี:
# The main branch is the (latest) release branch.
git clone https://github.com/e-dant/watcher.git && cd watcher
# Via Nix
nix run | grep -oE ' cmake-is-tough '
# With the build script
tool/build --no-build-test --no-run && cd out/this/Release # Build the release version for the host platform.
./wtr.watcher | grep -oE ' needle-in-a-haystack/.+" ' # Use it, pipe it, whatever. (This is an .exe on Windows.)คุณสามารถดู ระบบไฟล์ทั้งหมด ด้วยโครงการนี้ ในเกือบทุกกรณีเราใช้ทรัพยากรจำนวนใกล้ศูนย์และใช้ประโยชน์จากแคชอย่างมีประสิทธิภาพ เราทดสอบอย่างสม่ำเสมอว่าค่าใช้จ่ายในการตรวจจับและส่งเหตุการณ์ไปยังผู้ใช้เป็นลำดับของขนาดที่น้อยกว่าการดำเนินการของระบบไฟล์ที่ถูกวัด
เราเรียกใช้โครงการนี้ผ่านการทดสอบหน่วยกับ sanitiziers ที่มีอยู่ทั้งหมด รหัสนี้พยายามอย่างหนักที่จะเป็นเธรด, หน่วยความจำ, ขอบเขต, ประเภทและความปลอดภัยของทรัพยากร สิ่งที่เราขาดจากภาษาเราพยายามทำเพื่อทดสอบ สำหรับคำจำกัดความความปลอดภัยในทางปฏิบัติโครงการนี้อาจเหมาะกับ
ผู้เฝ้าดู ขึ้นอยู่กับไลบรารีมาตรฐาน C ++ เพื่อประสิทธิภาพเราใช้ประโยชน์จากระบบปฏิบัติการเมื่อเป็นไปได้บน Linux, Darwin และ Windows สำหรับการทดสอบและการดีบักเราใช้ Snitch และ Sanitizers
Watcher สามารถวิ่งได้เกือบทุกที่ ข้อกำหนดเพียงอย่างเดียวคือระบบไฟล์
ชิ้นส่วนสำคัญคือไลบรารี (ส่วนหัวเท่านั้น) และโปรแกรม CLI (ไม่บังคับ)
include/wtr/watcher.hpp รวมสิ่งนี้เพื่อใช้ Watcher ในโครงการ C ++ ของคุณ การคัดลอกสิ่งนี้ลงในโครงการของคุณและรวมถึง #include "wtr/watcher.hpp" (หรือคล้ายกัน) ก็เพียงพอที่จะลุกขึ้นและทำงานในภาษานี้ เอกสารเพิ่มเติมบางอย่างและห้องสมุดระดับสูงสามารถพบได้ในเหตุการณ์และดูส่วนหัวwatcher-c สร้างสิ่งนี้เพื่อใช้ Watcher จาก C หรือผ่าน FFI ในภาษาอื่น ๆsrc/wtr/watcher/main.cpp สร้างสิ่งนี้เพื่อใช้ Watcher จากบรรทัดคำสั่ง เอาต์พุตเป็นสตรีม JSON ที่ครบถ้วนสมบูรณ์src/wtr/tiny_watcher/main.cpp โปรแกรม CLI ที่มีน้อยและอ่านง่ายกว่า แหล่งที่มาสำหรับสิ่งนี้เกือบจะเหมือนกับการใช้ตัวอย่างสำหรับ C ++ต้นไม้ไดเรกทอรีอยู่ในบันทึกด้านล่าง
สองหน่วยการสร้างพื้นฐานที่นี่คือ:
watch หรือคลาส (ขึ้นอยู่กับภาษา)event (หรือมีชื่อคล้ายกันอีกครั้งขึ้นอยู่กับภาษา) watch ใช้เส้นทางซึ่งเป็นสิ่งที่คล้ายกับสตริงและการโทรกลับเป็นสิ่งที่คล้ายกับฟังก์ชั่น ตัวอย่างเช่นการผ่าน watch อาร์เรย์ตัวละครและการปิดจะทำงานได้ดีใน C ++
ตัวอย่างสำหรับภาษาที่หลากหลายสามารถพบได้ในการเริ่มต้นอย่างรวดเร็ว API ค่อนข้างสอดคล้องกันในภาษา
ผู้เฝ้าดูจะดูต่อไปอย่างมีความสุขจนกว่าคุณจะหยุดมันหรือมันกระทบกับข้อผิดพลาดที่ไม่สามารถกู้คืนได้
วัตถุ event ใช้เพื่อส่งข้อมูลเกี่ยวกับเหตุการณ์ระบบไฟล์ไปยังการโทรกลับ (โดยคุณ) เพื่อ watch
วัตถุ event จะมี:
path_name ซึ่งเป็นเส้นทางที่แน่นอนไปยังเหตุการณ์path_type ประเภทของเส้นทาง หนึ่งใน:dirfilehard_linksym_linkwatcherothereffect_type , "เกิดอะไรขึ้น" หนึ่งใน:renamemodifycreatedestroyownerothereffect_time เวลาของเหตุการณ์ในนาโนวินาทีตั้งแต่ยุคassociated (Event, C ++) หรือ associated_path_name (การใช้งานอื่น ๆ ทั้งหมดชื่อพา ธ เดียว):(โปรดทราบว่าสำหรับ JavaScript เราใช้ตัวอักษรอูฐเพื่อให้สอดคล้องกับระบบนิเวศของภาษานั้น)
ประเภทของ watcher เป็นพิเศษ
กิจกรรมที่มีประเภทนี้จะรวมข้อความจากผู้เฝ้าดู คุณอาจได้รับข้อความแสดงข้อผิดพลาดหรือการอัปเดตสถานะที่สำคัญ
รูปแบบนี้ได้รับเลือกให้รองรับข้อความแบบอะซิงโครนัสจากผู้เฝ้าดูในรูปแบบทั่วไปแบบพกพา
เหตุการณ์ "ผู้เฝ้าดู" ที่สำคัญที่สุดสองเหตุการณ์คือเหตุการณ์ "สด" ครั้งแรกและเหตุการณ์ "ตาย" สุดท้าย
ข้อความปรากฏขึ้นล่วงหน้าไปยังเส้นทางฐานที่ดู
ตัวอย่างเช่นหลังจากเปิดเครื่องเฝ้าดู AT /a/path คุณอาจได้รับข้อความเหล่านี้จากผู้เฝ้าดู:
s/self/live@/a/pathe/self/die@/a/path ข้อความเริ่มต้นด้วย s มักจะระบุการดำเนินการที่ประสบความสำเร็จ, w , ระบุคำเตือนที่ไม่ใช่อันตรายหรือ e ซึ่งบ่งบอกถึงข้อผิดพลาดที่ร้ายแรง
ที่สำคัญการปิดผู้เฝ้าดูจะสร้างข้อผิดพลาดเสมอหาก
self/live ยังไม่ได้ถูกส่ง; หรือกล่าวอีกนัยหนึ่งหากผู้เฝ้าดูไม่ได้เริ่มต้นอย่างเต็มที่ ในกรณีนี้ผู้เฝ้าดูจะปิดทันทีหลังจากเปิดอย่างเต็มที่และรายงานข้อผิดพลาดในการโทรทั้งหมดเพื่อปิด เหตุการณ์สุดท้ายจะเป็นเหตุการณ์ destroy จากผู้เฝ้าดูเสมอ คุณสามารถแยกวิเคราะห์ได้เช่นนี้สำหรับ Event ev :
ev.path_type == path_type::watcher && ev.effect_type == effect_type::destroy;แฮ็คมีความสุข
โครงการนี้พยายามทำให้คุณสามารถทำงานกับเหตุการณ์ระบบไฟล์ได้ง่าย ฉันคิดว่าเครื่องมือที่ดีใช้งานง่าย หากโครงการนี้ไม่ได้ถูกยศาสตร์ให้ยื่นปัญหา
นี่คือภาพรวมของเอาต์พุตที่ถ่ายในขณะที่เตรียมการกระทำนี้ก่อนที่จะเขียนย่อหน้านี้
{
"1666393024210001000" : {
"path_name" : " /home/edant/dev/watcher/.git/logs/HEAD " ,
"effect_type" : " modify " ,
"path_type" : " file "
},
"1666393024210026000" : {
"path_name" : " /home/edant/dev/watcher/.git/logs/refs/heads/next " ,
"effect_type" : " modify " ,
"path_type" : " file "
},
"1666393024210032000" : {
"path_name" : " /home/edant/dev/watcher/.git/refs/heads/next.lock " ,
"effect_type" : " create " ,
"path_type" : " other "
}
}ซึ่งค่อนข้างเจ๋ง
โปรแกรมที่มีความสามารถอยู่ที่นี่
โครงการนี้สามารถเข้าถึงได้ผ่าน:
tool/build : รวมส่วนหัว/ไลบรารี C ++, CLI, ทดสอบและเป้าหมายมาตรฐานtool/cross : รวมถึงห้องสมุดและส่วนหัวที่ใช้ร่วมกัน watcher-c , cross-compiled สำหรับหลายแพลตฟอร์มwatcher-c (คงที่และแชร์), CLI, การทดสอบและเป้าหมายเป้าหมายดูแพ็คเกจที่นี่
nix build # To just build
nix run # Build the default target, then run without arguments
nix run . -- / | jq # Build and run, watch the root directory, pipe it to jq
nix develop # Enter an isolated development shell with everything needed to explore this projectbazel build cli # Build, but don't run, the cli
bazel build hdr # Ditto, for the single-header
bazel run cli # Run the cli program without argumentstool/build
cd out/this/Release
# watches the current directory forever
./wtr.watcher
# watches some path for 10 seconds
./wtr.watcher ' your/favorite/path ' -s 10สิ่งนี้จะดูแลเฉพาะแพลตฟอร์มบางส่วนสร้างรุ่นการดีบักการดีบักและเครื่องทำความสะอาดและการทดสอบบางอย่าง
cmake -S . -B out
cmake --build out --config Release
cd out
# watches the current directory forever
./wtr.watcher
# watches some path for 10 seconds
./wtr.watcher ' your/favorite/path ' -s 10ผู้เฝ้าดูในทุกแพลตฟอร์มโดยเจตนาเพิกเฉยต่อเหตุการณ์การดัดแปลงซึ่งเปลี่ยนเวลา ACESS ในไฟล์หรือไดเรกทอรีเท่านั้น
ยูทิลิตี้ของเหตุการณ์เหล่านั้นเป็นที่น่าสงสัย
ดูเหมือนว่าจะเป็นอันตรายมากกว่าดี ผู้เฝ้าดูคนอื่น ๆ เช่น C# Watcher ของ Microsoft ไม่สนใจพวกเขาตามค่าเริ่มต้น แอปพลิเคชันผู้ใช้บางคนพึ่งพาเหตุการณ์การปรับเปลี่ยนที่จะรู้ว่าตัวเองโหลดไฟล์ซ้ำเมื่อใด
มีโซลูชันที่ดีกว่าและสมบูรณ์มากขึ้นและค่าเริ่มต้นเหล่านี้อาจเปลี่ยนแปลงได้อีกครั้ง
การให้วิธีการเพิกเฉยต่อเหตุการณ์จากกระบวนการ ID ชวเลขจากกระบวนการ "นี้" และวิธีการระบุแหล่งที่มาของเหตุการณ์ประเภทใดที่เราสนใจเป็นผู้สมัครที่ดีสำหรับการแก้ปัญหาที่สมบูรณ์ยิ่งขึ้น
ฉันสบายใจกับ C ++ เมื่อฉันเขียนสิ่งนี้ครั้งแรก ฉันเขียนโครงการนี้ใหม่ใน Rust เป็นการทดลอง มีประโยชน์และข้อเสียในการเกิดสนิม บางสิ่งปลอดภัยกว่าเล็กน้อยในการแสดงออกสิ่งอื่น ๆ ไม่แน่นอน ความจำเป็นในการทำคณิตศาสตร์ตัวชี้ในบางประเภททึบแสงที่แตกต่างจากเคอร์เนลตัวอย่างเช่นไม่ปลอดภัยที่จะแสดงในสนิม สิ่งอื่น ๆ ปลอดภัยกว่า แต่โครงการนี้ไม่ได้รับประโยชน์จากพวกเขามากนัก
สนิมเปล่งประกายในการใช้งานและการแสดงออก นั่นอาจเป็นเหตุผลที่เพียงพอที่จะใช้ เหนือสิ่งอื่นใดเราสามารถทำงานกับลักษณะ Async และประเภทพีชคณิตเพื่อความดีที่ดี
ฉันไม่แน่ใจว่ามีภาษาที่สามารถ "เพียงแค่" ทำให้รหัสส่วนใหญ่ในโครงการนี้ปลอดภัยตามคำจำกัดความ
ความกล้าของโครงการนี้อะแดปเตอร์พูดคุยกับเคอร์เนล พวกเขาจะต้องใช้อินเทอร์เฟซระดับระบบที่ไม่ปลอดภัยไม่ปลอดภัย
API สาธารณะมีเพียงประมาณ 100 บรรทัดนั้นได้รับการฝึกฝนมาอย่างดีและผ่านการตรวจสอบได้ดี ไม่ค่อยเกิดขึ้นที่นั่น
การสร้าง FFI โดยการเปิดเผยอะแดปเตอร์ด้วย C ABI อาจคุ้มค่า ภาษาส่วนใหญ่ควรจะสามารถขอได้
ความปลอดภัยของอะแดปเตอร์แพลตฟอร์มจำเป็นต้องขึ้นอยู่กับเอกสารของแต่ละแพลตฟอร์มสำหรับอินเทอร์เฟซของพวกเขา เช่นเดียวกับอินเทอร์เฟซระดับระบบทั้งหมดตราบใดที่เรามั่นใจว่าเงื่อนไขก่อนและโพสต์ที่ถูกต้องและเงื่อนไขเหล่านั้นมีการกำหนดไว้อย่างดีเราควรจะดี
ในบรรดาการใช้งานเฉพาะแพลตฟอร์ม FSEvents API ใช้กับ Darwin และ ReadDirectoryChanges API ใช้กับ Windows มีงานพิเศษบางอย่างที่เราทำเพื่อเลือกอะแดปเตอร์ที่ดีที่สุดบน Linux อะแดปเตอร์ fanotify จะถูกใช้เมื่อเคอร์เนลเวอร์ชันมากกว่า 5.9 กระบวนการที่มีอยู่นั้นมีรูทส่วนตัวและการโทรระบบที่จำเป็นนั้นได้รับอนุญาตเป็นอย่างอื่น การโทรของระบบที่เกี่ยวข้องกับ fanotify อาจไม่ได้รับอนุญาตเมื่ออยู่ในคอนเทนเนอร์หรือ cgroup แม้จะมีสิทธิพิเศษและเคอร์เนลที่จำเป็น อะแดปเตอร์ inotify ใช้เป็นอย่างอื่น คุณสามารถค้นหารหัสการเลือกสำหรับ Linux ได้ที่นี่
เนมสเปซสำหรับอะแดปเตอร์ของเราเป็นแบบอินไลน์ เมื่อ detail::...::watch() ถูกเรียกใช้มันจะแก้ไขให้เป็นหนึ่งเดียว (และเพียงหนึ่งเดียว) การใช้งานแพลตฟอร์ม specifc ของฟังก์ชั่น watch() หนึ่งสัญลักษณ์หลายแพลตฟอร์มที่แพลตฟอร์มเป็นเนมสเปซแบบอินไลน์
ประสิทธิภาพจะได้รับความนิยมเมื่อเรานำ warthog ออกมาซึ่งเป็นอะแดปเตอร์ที่ไม่ขึ้นกับแพลตฟอร์มของเรา อะแดปเตอร์นี้ใช้บนแพลตฟอร์มที่ไม่มีทางเลือกที่ดีกว่าเช่น (ไม่ใช่ดาร์วิน) BSD และ Solaris (เพราะ warthog ชนะ kqueue )
Watcher ยังคงค่อนข้างมีประสิทธิภาพเมื่อไม่มีทางเลือกที่ดีไปกว่า warthog ในฐานะที่เป็นกฎง่ายๆการสแกนเส้นทางมากกว่าหนึ่งแสนเส้นทางด้วย warthog อาจพูดติดอ่าง
ฉันจะเปิดตาเพื่อให้ดีขึ้น APIs เคอร์เนลบน BSD
ไม่มีวิธีที่เชื่อถือได้ในการสื่อสารเมื่อผู้เฝ้าดูพร้อมที่จะส่งกิจกรรมไปยังการโทรกลับ
สำหรับสองสามพันเส้นทางอาจใช้เวลาไม่กี่มิลลิวินาที สำหรับเส้นทางนับหมื่นของหลายพันให้พิจารณารอไม่กี่วินาที
ไม่มีการใช้งานเฉพาะแพลตฟอร์มใดที่ให้ข้อมูลเกี่ยวกับแอตทริบิวต์ที่เปลี่ยนไป สิ่งนี้ทำให้การสนับสนุนเหตุการณ์เหล่านั้นขึ้นอยู่กับการจัดเก็บข้อมูลนี้ด้วยตนเอง การจัดเก็บแผนที่ของเส้นทางไปยังโครงสร้าง stat การกระจายไปตามการเปลี่ยนแปลงแอตทริบิวต์เป็นความมุ่งมั่นของหน่วยความจำที่ไม่สำคัญ
เหตุการณ์เจ้าของและแอตทริบิวต์ไม่ได้รับการสนับสนุนเพราะฉันไม่แน่ใจว่าจะสนับสนุนเหตุการณ์เหล่านั้นได้อย่างไร
ระบบไฟล์พิเศษรวมถึง /proc และ /sys ไม่สามารถดูด้วย inotify , fanotify หรือ warthog การทำงานในอนาคตอาจเกี่ยวข้องกับการจัดส่งโปรแกรม EBPF เพื่อให้เคอร์เนลใช้ สิ่งนี้จะช่วยให้เราสามารถตรวจสอบ modify เหตุการณ์ในระบบไฟล์พิเศษเหล่านั้น
จำนวนไฟล์ที่ดูถูก จำกัด เมื่อใช้ inotify
สำหรับห้องสมุดส่วนหัวเท่านั้นและตัวจับเวลาเล็ก ๆ C ++ 17 ขึ้นไปควรจะดี
เราอาจใช้ c ++ 20 coroutines สักวันหนึ่ง
$ tool/gen-event/dir &
$ tool/gen-event/file &
$ valgrind --tool=cachegrind wtr.watcher ~ -s 30I refs: 797,368,564
I1 misses: 6,807
LLi misses: 2,799
I1 miss rate: 0.00%
LLi miss rate: 0.00%
D refs: 338,544,669 (224,680,988 rd + 113,863,681 wr)
D1 misses: 35,331 ( 24,823 rd + 10,508 wr)
LLd misses: 11,884 ( 8,121 rd + 3,763 wr)
D1 miss rate: 0.0% ( 0.0% + 0.0% )
LLd miss rate: 0.0% ( 0.0% + 0.0% )
LL refs: 42,138 ( 31,630 rd + 10,508 wr)
LL misses: 14,683 ( 10,920 rd + 3,763 wr)
LL miss rate: 0.0% ( 0.0% + 0.0% ) เนมสเปซและสัญลักษณ์อย่างใกล้ชิดติดตามไดเรกทอรีในโฟลเดอร์ devel/include เนมสเปซแบบอินไลน์อยู่ในไดเรกทอรีด้วย - Affix
ตัวอย่างเช่น wtr::watch อยู่ในไฟล์ devel/include/wtr/watcher-/watch.hpp watcher เนมสเปซใน wtr::watcher::watch ไม่ระบุชื่อโดยการประชุมนี้
ในเชิงลึกเพิ่มเติม: ฟังก์ชั่น ::detail::wtr::watcher::adapter::watch() ถูกกำหนดภายในหนึ่ง (และเพียงหนึ่งเดียวเท่านั้น!) ของไฟล์ devel/include/detail/wtr/watcher/adapter/*/watch.hpp * จะตัดสินใจในเวลาคอมไพล์ (ขึ้นอยู่กับระบบปฏิบัติการของโฮสต์)
ส่วนหัวทั้งหมดใน devel/include จะถูกรวมเข้ากับ include/wtr/watcher.hpp และเพิ่มตัวป้องกันไว้ด้านบน ผู้พิทักษ์ไม่ได้เปลี่ยนไปตามเวอร์ชันรุ่น ในอนาคตมันอาจ
watcher
├── src
│ └── wtr
│ ├── watcher
│ │ └── main.cpp
│ └── tiny_watcher
│ └── main.cpp
├── out
├── include
│ └── wtr
│ └── watcher.hpp
└── devel
├── src
│ └── wtr
└── include
├── wtr
│ ├── watcher.hpp
│ └── watcher-
│ ├── watch.hpp
│ └── event.hpp
└── detail
└── wtr
└── watcher
├── semabin.hpp
└── adapter
├── windows
│ └── watch.hpp
├── warthog
│ └── watch.hpp
├── linux
│ ├── watch.hpp
│ ├── sysres.hpp
│ ├── inotify
│ │ └── watch.hpp
│ └── fanotify
│ └── watch.hpp
└── darwin
└── watch.hpp
คุณสามารถเรียกใช้
tool/treeเพื่อดูต้นไม้นี้ในพื้นที่
https://github.com/notify-rs/notify :
lines of code : 2799
lines of tests : 475
lines of docs : 1071
implementation languages : rust
interface languages : rust
supported platforms : linux, windows, darwin, bsd
kernel apis : inotify, readdirectorychanges, fsevents, kqueue
non-blocking : yes
dependencies : none
tests : yes
static analysis : yes (borrow checked, memory and concurrency safe language)
https://github.com/e-dant/watcher :
lines of code : 1579
lines of tests : 881
lines of docs : 1977
implementation languages : cpp
interface languages : cpp, shells
supported platforms : linux, darwin, windows, bsd
kernel apis : inotify, fanotify, fsevents, readdirectorychanges
non-blocking : yes
dependencies : none
tests : yes
static analysis : yes
https://github.com/facebook/watchman.git :
lines of code : 37435
lines of tests : unknown
lines of docs : unknown
implementation languages : cpp, c
interface languages : cpp, js, java, python, ruby, rust, shells
supported platforms : linux, darwin, windows, maybe bsd
kernel apis : inotify, fsevents, readdirectorychanges
non-blocking : yes
dependencies : none
tests : yes (many)
static analysis : yes (all available)
https://github.com/p-ranav/fswatch :
lines of code : 245
lines of tests : 19
lines of docs : 114
implementation languages : cpp
interface languages : cpp, shells
supported platforms : linux, darwin, windows, bsd
kernel apis : inotify
non-blocking : maybe
dependencies : none
tests : some
static analysis : none
https://github.com/tywkeene/go-fsevents :
lines of code : 413
lines of tests : 401
lines of docs : 384
implementation languages : go
interface languages : go
supported platforms : linux
kernel apis : inotify
non-blocking : yes
dependencies : yes
tests : yes
static analysis : none (gc language)
https://github.com/radovskyb/watcher :
lines of code : 552
lines of tests : 767
lines of docs : 399
implementation languages : go
interface languages : go
supported platforms : linux, darwin, windows
kernel apis : none
non-blocking : no
dependencies : none
tests : yes
static analysis : none
https://github.com/parcel-bundler/watcher :
lines of code : 2862
lines of tests : 474
lines of docs : 791
implementation languages : cpp
interface languages : js
supported platforms : linux, darwin, windows, maybe bsd
kernel apis : fsevents, inotify, readdirectorychanges
non-blocking : yes
dependencies : none
tests : some (js bindings)
static analysis : none (interpreted language)
https://github.com/atom/watcher :
lines of code : 7789
lines of tests : 1864
lines of docs : 1334
implementation languages : cpp
interface languages : js
supported platforms : linux, darwin, windows, maybe bsd
kernel apis : inotify, fsevents, readdirectorychanges
non-blocking : yes
dependencies : none
tests : some (js bindings)
static analysis : none
https://github.com/paulmillr/chokidar :
lines of code : 1544
lines of tests : 1823
lines of docs : 1377
implementation languages : js
interface languages : js
supported platforms : linux, darwin, windows, bsd
kernel apis : fsevents
non-blocking : maybe
dependencies : yes
tests : yes (many)
static analysis : none (interpreted language)
https://github.com/Axosoft/nsfw :
lines of code : 2536
lines of tests : 1085
lines of docs : 148
implementation languages : cpp
interface languages : js
supported platforms : linux, darwin, windows, maybe bsd
kernel apis : fsevents
non-blocking : maybe
dependencies : yes (many)
tests : yes (js bindings)
static analysis : none
https://github.com/canton7/SyncTrayzor :
lines of code : 17102
lines of tests : 0
lines of docs : 2303
implementation languages : c #
interface languages : c #
supported platforms : windows
kernel apis : unknown
non-blocking : yes
dependencies : unknown
tests : none
static analysis : none (managed language)
https://github.com/g0t4/Rx-FileSystemWatcher :
lines of code : 360
lines of tests : 0
lines of docs : 46
implementation languages : c #
interface languages : c #
supported platforms : windows
kernel apis : unknown
non-blocking : yes
dependencies : unknown
tests : yes
static analysis : none (managed language)