fsnotify merupakan pustaka notifikasi sistem file yang ditulis dalam bahasa Go, yang dapat memantau perubahan pada file dan direktori dalam sistem file, sekaligus memberikan pemberitahuan kepada aplikasi saat terjadi perubahan. Pustaka ini mendukung operasi lintas platform dan dapat berjalan di berbagai sistem operasi seperti Linux, macOS, dan Windows. fsnotify memanfaatkan mekanisme notifikasi sistem file dari berbagai sistem operasi, seperti inotify pada Linux, FSEvents pada macOS, dan ReadDirectoryChangesW pada Windows.
Memerlukan penggunaan Go versi 1.17 atau yang lebih baru; dokumentasi lengkap dapat ditemukan di https://pkg.go.dev/github.com/fsnotify/fsnotify
Dukungan untuk berbagai sistem operasi:
Backend | Sistem Operasi | Status |
---|---|---|
inotify | Linux | Didukung |
kqueue | BSD, macOS | Didukung |
ReadDirectoryChangesW | Windows | Didukung |
FEN | illumos | Didukung |
fanotify | Linux 5.9+ | Belum didukung |
AHAFS | AIX | Cabang AIX; Fitur eksperimental karena kurangnya pengelola dan lingkungan pengujian |
FSEvents | macOS | Memerlukan dukungan x/sys/unix |
Jurnal USN | Windows | Memerlukan dukungan x/sys/windows |
Polling | Semua | Belum didukung |
Android dan Solaris, yang seharusnya termasuk Linux dan illumos, belum diuji.
Kasus Penggunaan
Beberapa kasus penggunaan fsnotify meliputi namun tidak terbatas pada situasi berikut:
- Sinkronisasi file real-time: fsnotify dapat memantau perubahan dalam sistem file secara real-time, sehingga cocok untuk implementasi sinkronisasi file real-time. Ketika terjadi perubahan pada file sumber, perubahan dapat segera disinkronkan ke file target, memastikan konsistensi file.
- Pembangunan otomatis: fsnotify dapat memantau perubahan pada kode sumber proyek dan file dependensi, serta memicu perintah pembangunan saat terjadi perubahan, sehingga mencapai pembangunan otomatis. Hal ini dapat menghemat waktu dan usaha dari pembangunan manual, serta meningkatkan efisiensi pengembangan.
- Cadangan file: fsnotify dapat memantau perubahan pada file atau direktori yang perlu dicadangkan, dan memulai cadangan segera saat terjadi perubahan. Hal ini menjaga keamanan data dan mencegah kerugian data akibat kehilangan atau kerusakan file.
- Pemantauan log real-time: fsnotify dapat memantau operasi seperti pembuatan, modifikasi, dan penghapusan file log, serta memicu program pemantauan log saat terjadi perubahan pada file log, efektif memantau perubahan konten log secara real-time.
- Pemantauan keamanan sistem file: fsnotify dapat memantau peristiwa keamanan dalam sistem file, seperti akses, modifikasi, dan penghapusan file. Hal ini memungkinkan pemantauan keamanan sistem file, dengan segera mengidentifikasi dan mencatat peristiwa yang tidak aman.
Contoh Penggunaan
Contoh penggunaan dasar:
package main
import (
"log"
"github.com/fsnotify/fsnotify"
)
func main() {
// Membuat watcher baru.
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
// Mulai mendengarkan peristiwa.
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("Peristiwa:", event)
if event.Has(fsnotify.Write) {
log.Println("File Dimodifikasi:", event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("Error:", err)
}
}
}()
// Tambahkan jalur yang perlu dipantau.
err = watcher.Add("/tmp")
if err != nil {
log.Fatal(err)
}
// Blokir goroutine utama.
<-make(chan struct{})
}
Contoh lebih lanjut dapat ditemukan di cmd/fsnotify dan dapat dijalankan menggunakan perintah berikut:
% go run ./cmd/fsnotify
Dokumentasi lebih terperinci dapat ditemukan di godoc: https://pkg.go.dev/github.com/fsnotify/fsnotify
Pertanyaan Umum
Apakah akan tetap dipantau jika file dipindahkan ke direktori lain?
Tidak, kecuali jika Anda memantau lokasi tempat file tersebut dipindahkan.
Apakah ini memantau subdirektori?
Tidak, Anda harus menambahkan pemantauan untuk setiap direktori yang ingin Anda pantau (pemantauan rekursif direncanakan: #18).
Apakah saya perlu memantau kedua saluran error dan acara secara bersamaan dalam goroutine?
Ya. Anda dapat menggunakan select
untuk membaca dari kedua saluran dalam goroutine yang sama (Anda tidak perlu memulai goroutine secara terpisah untuk setiap saluran; lihat contoh).
Mengapa pemberitahuan tidak berfungsi di NFS, SMB, FUSE, /proc, atau /sys?
fsnotify memerlukan dukungan dari sistem operasi bawahannya untuk berfungsi. Protokol NFS dan SMB saat ini tidak menyediakan dukungan tingkat jaringan untuk pemberitahuan file, dan sistem file virtual /proc dan /sys juga tidak menyediakan dukungan.
Hal ini dapat diperbaiki dengan menggunakan pemantau pemungutan suara (#9), tetapi hal ini belum diimplementasikan.
Mengapa saya menerima banyak peristiwa Chmod?
Beberapa program dapat menghasilkan sejumlah besar perubahan atribut, seperti Spotlight di macOS, program antivirus, aplikasi pencadangan, dan beberapa aplikasi lain yang diketahui. Secara umum, mengabaikan peristiwa Chmod biasanya merupakan praktik terbaik karena seringkali tidak berguna dan dapat menyebabkan masalah.
Proses indeks Spotlight di macOS dapat menyebabkan beberapa peristiwa (lihat #15). Solusi sementara adalah menambahkan folder Anda ke Pengaturan Privasi Spotlight sampai kita memiliki implementasi FSEvents asli (lihat #11).
Memantau file tidak berjalan lancar
Pada umumnya, tidak direkomendasikan untuk memantau file individual (daripada direktori) karena banyak program, terutama editor, akan secara atomik memperbarui file: akan menulis ke file sementara dan kemudian memindahkannya ke lokasi target, menimpa file asli (atau beberapa varian dari itu). Pemantauan pada file asli sekarang hilang karena file tersebut tidak ada lagi.
Akibatnya, pemadaman listrik atau crash tidak akan mengakibatkan file yang tertulis setengah jadi.
Pantau direktori induk dan gunakan Event.Name
untuk menyaring file yang tidak Anda minati. Ada contoh dalam cmd/fsnotify/file.go
.
Catatan Untuk Platform Tertentu
Linux
Ketika sebuah file dihapus, peristiwa REMOVE tidak akan dikeluarkan hingga semua deskriptor file tertutup; pada saat ini, peristiwa CHMOD akan dikeluarkan:
fp := os.Open("file")
os.Remove("file") // CHMOD
fp.Close() // REMOVE
Ini adalah peristiwa yang dikirimkan oleh inotify, sehingga tidak boleh terlalu banyak perubahan yang dibuat padanya.
Variabel sysctl fs.inotify.max_user_watches
menentukan jumlah maksimum pemantau per pengguna, dan fs.inotify.max_user_instances
menentukan jumlah maksimum instansi inotify per pengguna. Setiap Watcher yang Anda buat adalah "instansi," dan setiap path yang Anda tambahkan adalah "pemantauan".
Ini juga dapat ditemukan di /proc
, dengan path /proc/sys/fs/inotify/max_user_watches
dan /proc/sys/fs/inotify/max_user_instances
.
Untuk meningkatkannya, Anda dapat menggunakan sysctl
atau menuliskan nilai ke file proc:
sysctl fs.inotify.max_user_watches=124983
sysctl fs.inotify.max_user_instances=128
Untuk membuat perubahan tersebut berlaku setelah reboot, edit /etc/sysctl.conf
atau /usr/lib/sysctl.d/50-default.conf
(detailnya dapat bervariasi untuk setiap distribusi Linux, silakan merujuk ke dokumentasi distribusi Anda):
fs.inotify.max_user_watches=124983
fs.inotify.max_user_instances=128
Mencapai batas akan menghasilkan kesalahan "No space left on device" atau "Too many open files".
kqueue (macOS, semua sistem BSD)
kqueue memerlukan membuka deskriptor file untuk setiap file yang diamati; oleh karena itu, jika Anda mengamati direktori yang berisi lima file, itu akan menjadi enam deskriptor file. Di platform-platform ini, Anda akan lebih cepat mencapai batas "maksimum file terbuka" sistem.
Anda dapat menggunakan variabel sysctl kern.maxfiles
dan kern.maxfilesperproc
untuk mengontrol jumlah maksimum file terbuka.