Penutup chapter I/O scheduling menagih satu janji: agar penggantian scheduler bertahan melewati reboot, kita perlu bereaksi pada momen perangkat muncul di sistem. Momen itu adalah event udev — mesin event, lokasi berkas rule, dan operator dasarnya sudah kita bedah pada chapter udev dan device rules . Chapter ini mengambil sisi yang belum disentuh: menulis rule yang tepat sasaran untuk satu perangkat tertentu. Studi kasusnya konkret — studio kampus membeli lima webcam yang persis sama, dan hanya satu milik Budi — lalu kita beri unit itu nama tetap, izin khusus, dan aksi otomatis saat dicolok.

Satu Kamera di Antara Lima yang Sama #

Kelima webcam Logitech BRIO di studio identik di mata ATTR{idVendor} dan ATTR{idProduct} — pasangan vendor ID dan product ID hanya membedakan model, bukan unit. Rule yang mencocokkan pasangan ID itu, sebagaimana ditulis pada chapter udev dan device rules, akan menyangkut lima kamera sekaligus. Pembeda antar-unit adalah nomor seri yang tercetak pada perangkat USB induknya, dan di sinilah perbedaan dua kunci pencocokan jadi penting: ATTR{...} membaca atribut sysfs milik perangkat yang memancarkan event, sedangkan ATTRS{...} menaiki rantai induk perangkat itu sampai menemukan nilai yang cocok.

Nomor seri ditemukan dengan udevadm info -a . Perintah ini berangkat dari node perangkat lalu berjalan ke atas melewati setiap induk, mencetak semua kunci yang sah dipakai sebagai kriteria rule. Berikut contoh tampilannya pada node /dev/video1 milik kamera Budi:

console
$ udevadm info -a -n /dev/video1

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.

  looking at device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/video4linux/video1':
    KERNEL=="video1"
    SUBSYSTEM=="video4linux"
    ATTR{index}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0':
    KERNELS=="3-2:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="uvcvideo"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2':
    KERNELS=="3-2"
    SUBSYSTEMS=="usb"
    ATTRS{idVendor}=="046d"
    ATTRS{idProduct}=="085e"
    ATTRS{serial}=="KAM-BUDI-01"

Dua hal patut dicermati dari keluaran di atas. Pertama, node video1 sendiri hidup di subsystem video4linux, sedangkan serial berada dua tingkat di atasnya pada perangkat USB 3-2 — karena itulah rule kita nanti menggabungkan SUBSYSTEM=="video4linux" dengan ATTRS{serial}. Kedua, kunci milik perangkat induk ditulis dengan akhiran S (KERNELS, SUBSYSTEMS, ATTRS) sebagai penanda bahwa pencocokannya menaiki rantai.

Sekarang kita tulis rule lengkapnya ke berkas latihan. Nama foldernya bebas; yang penting isi berkasnya nanti persis sama dengan /etc/udev/rules.d/99-kamera-budi.rules di sistem sungguhan:

bash
mkdir -p latihan/rules
cat > latihan/rules/99-kamera-budi.rules <<'EOF'
# Kamera BRIO milik Budi: nama tetap + izin ketat
ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{serial}=="KAM-BUDI-01", SYMLINK+="kamera-budi", MODE="0660"
EOF
cat latihan/rules/99-kamera-budi.rules

Output yang Dihasilkan:

text
# Kamera BRIO milik Budi: nama tetap + izin ketat
ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{serial}=="KAM-BUDI-01", SYMLINK+="kamera-budi", MODE="0660"

Mari kita bedah kelima kuncinya satu per satu:

  1. ACTION=="add": kriteria — hanya event kedatangan yang dicocokkan; event remove saat kamera dicabut tidak menyentuh rule ini.
  2. SUBSYSTEM=="video4linux": kriteria — event harus berasal dari node video; syarat inilah yang membuat symlink mendarat di samping /dev/video1, bukan pada node induk USB-nya.
  3. ATTRS{serial}=="KAM-BUDI-01": kriteria — udev menaiki rantai induk dari node video sampai menemukan atribut serial; kelima kamera studio sejenis, tetapi nomor seri hanya dimiliki satu unit.
  4. SYMLINK+="kamera-budi": aksi — menambahkan symlink /dev/kamera-budi yang menunjuk ke node asli; operator += dipakai karena daftar nama bersifat tambahan, sehingga rule lain boleh menambah nama tanpa saling menimpa.
  5. MODE="0660": aksi — izin node menjadi rw-rw----; operator = menetapkan nilai, dan penugasan terakhir yang menang bila ada rule lain juga menyetel MODE.

Satu baris rule memuat dua dunia sekaligus: kriteria memakai ==, aksi memakai = atau +=. Operator keempat, :=, menetapkan nilai final yang terkunci — tidak bisa ditimpa rule berikutnya. Perbedaan tanda ini penting: satu karakter menentukan apakah udev membandingkan atau mengubah.

Menguji Rule tanpa Mencabut Kamera #

Rule baru hidup saat event sungguhan datang, tetapi mencabut-colok perangkat untuk setiap revisi melelahkan. Untuk memahami cara udev mengevaluasi rule, kita pakai cocok-aturan.sh dari bundle chapter ini: skrip kecil yang membaca sebuah berkas rule dan sebuah berkas event, lalu memeriksa apakah setiap syarat K=="V" rule ada pada event. Dua berkas event di bundle mewakili dua skenario — event-kamera.txt adalah event add milik node video kamera Budi, dan event-mouse.txt adalah event mouse milik Siti:

bash
mkdir -p latihan/rules
cat > latihan/rules/99-kamera-budi.rules <<'EOF'
# Kamera BRIO milik Budi: nama tetap + izin ketat
ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{serial}=="KAM-BUDI-01", SYMLINK+="kamera-budi", MODE="0660"
EOF
cat event-kamera.txt
echo ---
cat event-mouse.txt
bash cocok-aturan.sh latihan/rules/99-kamera-budi.rules event-kamera.txt
bash cocok-aturan.sh latihan/rules/99-kamera-budi.rules event-mouse.txt

Output yang Dihasilkan:

text
ACTION=add
SUBSYSTEM=video4linux
DEVNAME=/dev/video1
ATTRS{serial}=KAM-BUDI-01
ID_MODEL=Logitech_BRIO
---
ACTION=add
SUBSYSTEM=input
DEVNAME=/dev/input/mouse2
ATTRS{serial}=MOUSE-SITI-77
ID_MODEL=Mouse_Wireless
COCOK: aturan dieksekusi untuk event ini
TIDAK COCOK: syarat SUBSYSTEM=video4linux tidak ada pada event

Blok di atas menulis ulang berkas rule diam-diam di baris awalnya — blok latihan dalam buku ini selalu mandiri, jadi isinya dibuat ulang meski sama dengan blok sebelumnya. Cara kerja sang pencocok:

  1. grep -oE '[A-Z]+(\{...\})?=="..."': skrip hanya menangkap segmen K=="V" — bagian aksi SYMLINK+= dan MODE= tidak ikut diperiksa karena bukan pencocokan.
  2. Kunci ENV{ID_MODEL} diterjemahkan menjadi ID_MODEL: property event memang dibaca seperti environment variable oleh udev.
  3. grep -qxF "K=V": tiap syarat dicari sebagai baris utuh pada berkas event; satu syarat hilang berarti seluruh rule gagal — semua kriteria digabung dengan logika AND, persis semantik udev.
  4. Hasilnya dua arah: event kamera memenuhi kelima syarat, sedangkan event mouse berhenti di SUBSYSTEM — nomor seri MOUSE-SITI-77 bahkan belum sempat diperiksa.

Urutan Berkas: Umum Dulu, Khusus Belakangan #

udev membaca semua berkas .rules dari /usr/lib/udev/rules.d/ dan /etc/udev/rules.d/ dalam urutan nama berkas. Studio kita memanfaatkan urutan itu: 70-model-broad.rules membuka izin grup untuk semua kamera BRIO, lalu 99-kamera-budi.rules mengencangkannya untuk satu unit. Mari kita uji rule yang umum dengan pencocok yang sama:

bash
cat 70-model-broad.rules
bash cocok-aturan.sh 70-model-broad.rules event-kamera.txt
bash cocok-aturan.sh 70-model-broad.rules event-mouse.txt

Output yang Dihasilkan:

text
# Semua kamera BRIO studio: izin grup dibuka untuk anggota tim
ACTION=="add", SUBSYSTEM=="video4linux", ENV{ID_MODEL}=="Logitech_BRIO", MODE="0664"
COCOK: aturan dieksekusi untuk event ini
TIDAK COCOK: syarat SUBSYSTEM=video4linux tidak ada pada event

Saat kamera Budi dicolok, urutan eksekusinya begini: berkas 70- berjalan lebih dulu dan menyetel MODE="0664", lalu berkas 99- menyusul dan menimpanya dengan MODE="0660" — penugasan terakhir menang, dan symlink hanya ditambah oleh berkas 99-, jadi /dev/kamera-budi tetap lahir. Nomor 99- pada konvensi admin bukan gaya-gayaan: aturan admin berjalan paling akhir sehingga keputusan lokal selalu menang atas kebijakan bawaan distro. Berkas dengan nama sama di /etc/udev/rules.d/ bahkan menimpa total berkas bawaan paket di /usr/lib/udev/rules.d/; kumpulan resep rule siap pakai lainnya dirangkum di wiki Arch tentang udev .

Memasang dan Menguji di Sistem Sungguhan #

Di sistem sungguhan, kedua berkas rule itu tinggal menempati /etc/udev/rules.d/ dan udev diminta membaca ulang:

bash
sudo cp latihan/rules/99-kamera-budi.rules 70-model-broad.rules /etc/udev/rules.d/
sudo udevadm control --reload

Kedua perintah di atas butuh root, jadi tidak bisa dijalankan di lingkungan latihan. Setelahnya, sudo udevadm trigger memancarkan ulang event untuk perangkat yang sudah terpasang — atau cukup cabut lalu colok kembali kameranya, sebagaimana diperingatkan pada chapter udev dan device rules di section System Administration. Sebelum mengandalkan sebuah rule di produksi, udevadm test menyimulasikan seluruh jalur evaluasi untuk satu perangkat tanpa mengubah apa pun. Berikut contoh tampilan ringkasnya:

console
$ sudo udevadm test /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/video4linux/video1

This program is for debugging only, it does not run any program,
specified by RUN or IMPORT{builtin} keywords. It does not touch
hardware or influence the running udev, and does not load kernel modules.

Load module index
Reading rules file: /usr/lib/udev/rules.d/50-udev-default.rules
Reading rules file: /etc/udev/rules.d/70-model-broad.rules
Reading rules file: /etc/udev/rules.d/99-kamera-budi.rules
video1: LINK 'kamera-budi'
video1: MODE 0660

Bacaan baris Reading rules file memperlihatkan urutan yang kita rancang: rule umum dibaca sebelum rule khusus. Dua baris terakhir adalah hasil kerja rule — symlink kamera-budi dan mode 0660. Perintah udevadm test sengaja tidak menjalankan program RUN, jadi aman diulang berkali-kali saat menyeting rule.

Aksi Otomatis: RUN dan Pemicu systemd #

Bagian aksi RUN memungkinkan rule memicu tugas nyata, misalnya skrip backup yang menyalin isi kartu memori begitu kamera terdeteksi. Dua ketentuan main menjaga kesehatan sistem: program di RUN berjalan sebagai root tanpa terminal, dan program itu harus cepat selesai karena menahan pemrosesan event. Satu jebakan lagi menanti: kamera modern memaparkan beberapa node sekaligus (video0, video1, …) dan setiap node memancarkan event sendiri, sehingga rule tanpa penyaring KERNEL memicu skrip lebih dari sekali:

bash
# /etc/udev/rules.d/99-kamera-budi.rules -- versi dengan aksi backup
ACTION=="add", SUBSYSTEM=="video4linux", KERNEL=="video0", ATTRS{serial}=="KAM-BUDI-01", \
    SYMLINK+="kamera-budi", MODE="0660", RUN+="/usr/local/sbin/backup-kamera.sh"

Tidak semua aksi butuh RUN. Janji pada penutup chapter I/O scheduling dibayar begini: ACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq" — penugasan ATTR menulis langsung ke berkas sysfs perangkat, sehingga begitu disk mekanis terdeteksi, schedulernya otomatis menjadi bfq tanpa echo manual dan tanpa reboot.

Rangkaian ini menutup satu sisi kehidupan perangkat: udev memastikan perangkat hadir dengan nama, izin, dan konfigurasi yang benar sejak detik pertama. Tetapi udev hanya mengurus momen kedatangan — apa yang dikerjakan kernel setelah kamera dipakai merekam, packet tiba di interface, atau proses saling berebut CPU, tidak terlihat dari rule mana pun. Untuk membedah waktu eksekusi itu kita perlu kaca pembesar yang bekerja di dalam kernel: ftrace, perf, dan kawan-kawannya — topik chapter tracing dan profiling .

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

cocok-aturan.sh

Unduh berkas
bash
#!/bin/bash
# cocok-aturan.sh -- mini rule matcher untuk memahami evaluasi udev.
# Pemakaian: ./cocok-aturan.sh <file-rule> <file-event>
# Setiap syarat K=="V" pada rule harus ada pada file event sebagai baris "K=V".
# Kunci ENV{X} dicocokkan ke property event "X=V" (seperti perilaku udev).
# Assignment (SYMLINK+=, MODE=, dst.) bukan syarat, jadi diabaikan.

if [ $# -lt 2 ]; then
    # dipanggil tanpa argumen -> tidak ada rule/event yang diuji
    exit 0
fi

aturan=$1
acara=$2

for syarat in $(grep -oE '[A-Z]+(\{[a-zA-Z0-9_]+\})?=="[^"]+"' "$aturan" \
                | tr -d '"' | sed 's/==/=/'); do
    kunci=${syarat%%=*}
    kunci=$(printf '%s' "$kunci" | sed 's/^ENV{\([a-zA-Z0-9_]*\)}$/\1/')
    nilai=${syarat#*=}
    if ! grep -qxF "$kunci=$nilai" "$acara"; then
        echo "TIDAK COCOK: syarat $syarat tidak ada pada event"
        exit 0
    fi
done
echo "COCOK: aturan dieksekusi untuk event ini"