fsnotify เป็นไลบรารีการแจ้งเตือนระบบไฟล์ที่เขียนด้วย Go ซึ่งสามารถตรวจสอบการเปลี่ยนแปลงของไฟล์และไดเรคทอรีในระบบไฟล์และแจ้งให้แอปพลิเคชันทราบเมื่อเกิดการเปลี่ยนแปลง มันรองรับการทำงาน跨แพลตฟอร์มและสามารถทำงานได้บนระบบปฏิบัติการที่แตกต่างกัน เช่น Linux, macOS, และ Windows fsnotify ใช้กลไกการแจ้งเตือนระบบไฟล์ของระบบปฏิบัติการต่าง ๆ เช่น inotify บน Linux, FSEvents บน macOS, และ ReadDirectoryChangesW บน Windows
ต้องใช้ Go 1.17 หรือเวอร์ชันที่ใหม่กว่า สามารถดูเอกสารที่สมบูรณ์ได้ที่ https://pkg.go.dev/github.com/fsnotify/fsnotify
การรองรับสำหรับระบบปฏิบัติการที่แตกต่างกัน:
Backend | Operating System | Status |
---|---|---|
inotify | Linux | Supported |
kqueue | BSD, macOS | Supported |
ReadDirectoryChangesW | Windows | Supported |
FEN | illumos | Supported |
fanotify | Linux 5.9+ | ยังไม่ได้รับการรองรับ |
AHAFS | AIX | AIX branch; Experimental feature due to lack of maintainers and test environment |
FSEvents | macOS | ต้องการการรองรับ x/sys/unix |
USN Journals | Windows | ต้องการการรองรับ x/sys/windows |
Polling | All | ยังไม่ได้รับการรองรับ |
Android และ Solaris ซึ่งควรรวมถึง Linux และ illumos ยังไม่ได้ทดสอบ
การใช้งาน
การใช้งานของ fsnotify รวมถึง แต่ไม่จำกัดอยู่ที่ฉากหลักต่อไปนี้:
- ซิงโครไนเอชนไพล์แบบเรียลไทม์: fsnotify สามารถตรวจสอบการเปลี่ยนแปลงในระบบไฟล์แบบเรียลไทม์ ทำให้เหมาะสำหรับการนำไปใช้ในการซิงค์ไฟล์แบบเรียลไทม์ เมื่อเกิดการเปลี่ยนแปลงในไฟล์ต้นฉบับ การเปลี่ยนแปลงก็สามารถซิงค์ไปยังไฟล์เป้าหมายทันที ทำให้ไฟล์เหล่านั้นมีความสอดคล้องกัน
- การสร้างอัตโนมัติ: fsnotify สามารถตรวจสอบการเปลี่ยนแปลงในโค้ดต้นฉบับของโปรเจกต์และไฟล์ที่ต้องการ โดยเรียกใช้คำสั่งสร้างหน่วยงานเมื่อเกิดการเปลี่ยนแปลง ซึ่งสามารถผลักดันการสร้างอัตโนมัตินี้ จะสามารถประหยัดเวลาและความพยายามของการสร้างด้วยมือและเพิ่มความสามารถในการพัฒนา
- การสำรองข้อมูลไฟล์: fsnotify สามารถตรวจสอบการเปลี่ยนแปลงของไฟล์หรือไดเรคทอรีที่ต้องการถูกสำรองข้อมูล และเมื่อเกิดการเปลี่ยนแปลง การสำรองข้อมูลจะถูกเริ่มต้นทันที นี้จะให้ความมั่นคงของข้อมูลและป้องกันการสูญเสียข้อมูลที่เกิดจากการสูญเสียหรือเสียหาย
- การตรวจสอบบันทึกเรียลไทม์: fsnotify สามารถตรวจสอบการดำเนินการเช่น การสร้าง การแก้ไข และการลบของไฟล์บันทึกเมื่อเกิดการเปลี่ยนแปลงในไฟล์บันทึก ทำให้สามารถตรวจสอบการเปลี่ยนแปลงในเนื้อหาบันทึกแบบเรียลไทม์ได้อย่างมีประสิทธิภาพ
- การตรวจสอบความปลอดภัยของระบบไฟล์: fsnotify สามารถตรวจสอบเหตุการณ์ทางความปลอดภัยในระบบไฟล์ เช่น การเข้าถึงไฟล์ การแก้ไข และการลบ ซึ่งทำให้สามารถตรวจสอบความปลอดภัยของระบบไฟล์ได้อย่างรวดเร็ว ตรวจพบเหตุการณ์ที่ไม่ปลอดภัยและระบุได้ทันที
ตัวอย่างการใช้งาน
ตัวอย่างพื้นฐาน:
package main
import (
"log"
"github.com/fsnotify/fsnotify"
)
func main() {
// สร้าง watcher ใหม่
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
// เริ่มฟังเหตุการณ์
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("Event:", event)
if event.Has(fsnotify.Write) {
log.Println("Modified file:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("Error:", err)
}
}
}()
// เพิ่มเส้นทางที่ต้องการตรวจสอบ
err = watcher.Add("/tmp")
if err != nil {
log.Fatal(err)
}
// บล็อกโปรแกรมหลัก
<-make(chan struct{})
}
สามารถหาตัวอย่างเพิ่มเติมได้ที่ cmd/fsnotify และสามารถรันได้โดยใช้คำสั่งต่อไปนี้:
% go run ./cmd/fsnotify
เอกสารที่ละเอียดยิ่งสามารถหาได้ใน godoc: https://pkg.go.dev/github.com/fsnotify/fsnotify
คำถามที่พบบ่อย
จะยังคงถูกตรวจสอบหากไฟล์ถูกย้ายไปยังไดเร็คทอรีอื่น?
ไม่ นอกจากว่าคุณกำลังตรวจสอบตำแหน่งที่มันถูกย้ายไปยัง
มันจะตรวจสอบโฟลเดอร์ย่อยได้ไหม?
ไม่, คุณต้องเพิ่มการตรวจสอบสำหรับแต่ละโฟลเดอร์ที่คุณต้องการตรวจสอบ (การตรวจสอบแบบเรียกกลับถูกวางแผนไว้: #18).
ฉันต้องการตรวจสอบทั้งคู่ช่องผิดพลาดและเหตุการณ์ใน goroutine พร้อมกันหรือไม่?
ใช่ คุณสามารถใช้ select
เพื่ออ่านจากทั้งสองช่องใน goroutine เดียวกัน (คุณไม่จำเป็นต้องเริ่ม goroutine โดยต่างหากสำหรับแต่ละช่อง ดูตัวอย่างได้).
ทำไมการแจ้งเตือนไม่ทำงานบน NFS, SMB, FUSE, /proc, หรือ /sys?
fsnotify ต้องการการสนับสนุนจากระบบปฏิบัติการฐานเบียนเพื่อทำงาน โปรๆคอล NFS และ SMB ปัจจุบันไม่ให้การสนับสนุนระดับเครือข่ายสำหรับการแจ้งเตือนของไฟล์ และระบบไฟล์เสมือนเสมือน /proc และ /sys ก็ไม่ให้การสนับสนุน
สามารถแก้ไขได้โดยใช้การดูแลด้วยการสำรวจเฉพาะ (#9) แต่ขณะนี้ยังไม่ได้ทำการปรับปรุง
ทำไมฉันได้รับเหตุการณ์ Chmod จำนวนมาก?
บางโปรแกรมอาจสร้างการเปลี่ยนแปลงคุณสมบัติจำนวนมาก เช่น Spotlight บน macOS, โปรแกรมต้านไวรัส, โปรแกรมสำรองข้อมูล และบางโปรแกรมที่รู้จักอื่นๆ โดยทั่วไปการละเว้นเหตุการณ์ Chmod โดยทั่วไปมักเป็นภาคการดูแลด้วย เนื่องจากพวกเขามักจะไม่เกี่ยวข้อง และอาจสร้างปัญหา
การทำดัชนี Spotlight บน macOS อาจสร้างเหตุการณ์หลายครั้ง (ดูที่นี่ #15) ทางเลือกชั่วคราวคือเพิ่มโฟลเดอร์ของคุณไปยัง การตั้งค่าข้อมูลส่วนตัวของ Spotlight จนกว่าเราจะมีการปรับปรุงแบบ FSEvents อย่างเป็นธรรมชาติ (ดูที่นี่ #11).
การดูแลไฟล์ทำงานไม่ดี
โดยทั่วไปแล้วไม่แนะนำให้ดูแลไฟล์เดียว (แทนที่จะไดเร็กทอรี) เนื่องจากโปรแกรมมากมาย, โดยเฉพาะโปรแกรมแก้ไข, จะมีการอัพเดตไฟล์อะตอมิคอลี: มันจะเขียนลงไฟล์ชั่วคราวและจากนั้นย้ายมันไปยังตำแหน่งปลายทาง, ทับไฟล์เดิม (หรือแบบทดแย่งของมัน) การดูแลด้วยต้นฉบับของไฟล์ตอนนั้นจะหายไป
เป็นผลมาจากนั้น การขัดข้องของไฟฟล์ที่พลังงานหรือการล้มเหลวจะไม่สร้างผลลัพธ์ที่เต็มรูปแบบ
ดูแลไดเร็กทอรีแม่และใช้ Event.Name
เพื่อกรองออกไฟล์ที่คุณไม่สนใจ มีตัวอย่างในcmd/fsnotify/file.go
หมายเหตุสำหรับแพลตฟอร์มที่ระบุ
Linux
เมื่อไฟล์ถูกลบ, เหตุการณ์ REMOVE จะไม่ถูกออกโดยที่นี่ไฟล์เดสก์ริปเตอร์ทุกตัวถูกปิดไป ณ เวลานั้น, เหตุการณ์ CHMOD จะถูกออก:
fp := os.Open("file")
os.Remove("file") // CHMOD
fp.Close() // REMOVE
นี่หรือเหตุการณ์ที่ส่งออกโดย inotify, เพราะฉะนั้นจะไม่ควรมีการเปลี่ยนแปลงมากมาย
ตัวแปร sysctl fs.inotify.max_user_watches
ระบุจำนวนสูงสุดของการดูแลของแต่ละผู้ใช้, และ fs.inotify.max_user_instances
ระบุจำนวนสูงสุดของ inotify instances ต่อผู้ใช้ ทุ Watcher ที่คุณสร้างคือ "instance" และทุ path ที่คุณเพิ่มคือ "watch"
นอกจากนั้น, คุณสามารถหาได้ใน /proc
, ด้วย path /proc/sys/fs/inotify/max_user_watches
และ /proc/sys/fs/inotify/max_user_instances
.
เพื่อเพิ่มเขา, คุณสามารถใช้ sysctl
หรือ เขียนค่าลงไฟล์ proc:
sysctl fs.inotify.max_user_watches=124983
sysctl fs.inotify.max_user_instances=128
เพื่อให้การเปลี่ยนแปลงมีผลหลังจากการรีบู๊ต, แก้ไข /etc/sysctl.conf
หรือ /usr/lib/sysctl.d/50-default.conf
(รายละเอียดอาจแตกต่างสำหรับแต่ละการกระจาย Linux, กรุณาอ้างอิงตามเอกสารของการกระจาย Linux ของคุณ):
fs.inotify.max_user_watches=124983
fs.inotify.max_user_instances=128
หากครบถึงขีดจำกัด ผลลัพธ์จะเป็น "No space left on device" หรือ "Too many open files"
kqueue (macOS, ซิสเตมึส์ทั้งหมด)
kqueue ต้องการเปิดไฟล์เดสก์ริปเตอร์สำหรับแต่ละไฟล์ที่สังเกตเห็น เพราะฉะนั้นหากคุณทราบไดเร็กทอรีที่มีไฟล์ห้าไฟล์, นี่คือหกไฟล์ บนแพลตฟอร์มเหล่านี้, คุณจะถึงขีดจำกัดของ "ไฟล์เปิดสูงสุด" ของระบบไวเร็คลี
คุณสามารถใช้ตัวแปร sysctl kern.maxfiles
และ kern.maxfilesperproc
เพื่อควบคุมจำนวนสูงสุดของการเปิดไฟล์ ทั้งหมด