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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.