Pendatang baru dari Windows biasanya membawa asumsi bahwa mencetak berarti mencari driver di situs produsen lalu menjalankan berkas instalasi. Di Linux caranya berbeda: hampir semua pencetakan melewati satu layanan bernama CUPS, dan printer modern justru paling lancar ketika tidak dipasangi driver vendor sama sekali. Chapter ini membedah perjalanan satu berkas dari aplikasi sampai kertas, cara membuat antrian cetak dengan lpadmin, mengelola antrian dengan lp/lpstat/cancel, lalu menutup dengan membaca log ketika cetakan menolak keluar.

CUPS: Satu Layanan untuk Semua Cetakan #

CUPS (Common Unix Printing System) adalah daemon cupsd yang menjadi satu-satunya gerbang percetakan di distro besar mana pun. Layanan ini berbicara IPP (Internet Printing Protocol) — protokol percetakan berbasis HTTP yang mendengarkan port 631 — sehingga setiap printer, lokal maupun jaringan, tampak sebagai antrian bernama di mata aplikasi. Karena berbasis HTTP, CUPS juga punya antarmuka web bawaan yang dibuka dengan menunjuk browser ke localhost:631 — administrasi tanpa terminal. Gambaran lengkapnya ada di wiki CUPS .

Perjalanan Satu Cetakan: Filter dan Backend #

Ketika browser mengeksekusi Print, berkas tidak dikirim langsung ke printer. Ia mengalir melalui jalur ini: aplikasi menyerahkan dokumen ke cupsd lewat IPP, job menunggu di spool /var/spool/cups, lalu rantai filter mengonversi dokumen (PDF, teks, gambar) menjadi data yang dimengerti printer, dan akhirnya backend mengantarkan hasilnya lewat URI perangkat — usb:// untuk kabel, ipp:// untuk jaringan, socket:// untuk printer lawas. Filter klasik seperti a2ps dulu bertugas mengubah teks polos menjadi PostScript berhalaman rapi.

Kita bisa merasakan arsitektur itu dengan pipeline mini. Skrip cetak-file.sh di bundle chapter ini adalah filter sekaligus backend mainan: bagian awk memformat teks menjadi halaman bernomor (peran filter), dan “pengiriman” dilakukan dengan menulis ke berkas .prn (peran backend):

bash
printf 'Notulen rilis:\n- v2.1 bulan depan\n- perbaiki label USB\n' > catatan.txt
bash cetak-file.sh catatan.txt LaserKantor
cat catatan.txt.prn

Output yang Dihasilkan:

text
backend: menulis ke catatan.txt.prn
+--------------------------------------------------+
| LASERKANTOR -- tugas: catatan.txt                |
+--------------------------------------------------+
  1  Notulen rilis:
  2  - v2.1 bulan depan
  3  - perbaiki label USB
+--------------------------------------------------+
| halaman 1, 3 baris                               |
+--------------------------------------------------+

Halaman itu tampil dengan kepala cetak, isi bernomor baris, dan kaki halaman — format yang persis dikerjakan filter sungguhan. Bagian penting skripnya:

  1. Blok if [ $# -eq 0 ]: tanpa argumen, skrip menjalankan demo pada berkas sementara lalu keluar sukses — pola yang membuatnya aman dijalankan dari folder mana pun.
  2. Baris hasil="$berkas.prn": menentukan tujuan “backend” berupa berkas — padanan berkas backend sungguhan yang menulis ke usb://.
  3. Baris awk -v tugas="$berkas" -v printer="$printer": filter menerima dua parameter, identitas tugas dan nama printer, seperti opsi yang diterima filter CUPS.
  4. Blok BEGIN: membangun kepala halaman sekali di awal — garis pembatas dan identitas tugas LASERKANTOR -- tugas: catatan.txt.
  5. Blok { printf "%3d %s\n", NR, $0 }: menomori setiap baris isi — inti pekerjaan a2ps versi mini ini.
  6. Baris > "$hasil": seluruh keluaran filter dialihkan ke berkas tujuan; inilah momen “dokumen dikirim ke printer” versi latihan.

Driver: PPD dan IPP Everywhere #

Dua generasi teknologi hidup berdampingan di sini. Cara lama memakai PPD (PostScript Printer Description): berkas teks yang memetakan kemampuan printer — resolusi, ukuran kertas, duplex — agar filter tahu format apa yang boleh dibuat, dan driver vendor kadang ditambahkan sebagai filter khusus. Cara baru disebut IPP Everywhere (sebutan Apple: AirPrint): printer modern mengiklankan kemampuannya sendiri lewat IPP sehingga CUPS cukup menyalinnya — di sinilah istilah driverless berasal. Untuk printer jaringan keluaran belakangan ini, pendekatan kedua hampir selalu menang: tanpa unduhan, tanpa berkas vendor.

Menambah Antrian dengan lpadmin #

Satu perintah biasanya cukup untuk mendaftarkan printer jaringan modern:

bash
sudo lpadmin -p LaserKantor -E -v ipp://192.0.2.10/ipp/print -m everywhere

Empat opsi itu memuat seluruh ceritanya: -p LaserKantor memberi nama antrian (nama bebas, dipakai saat mencetak), -E sekaligus mengaktifkan antrian dan menerimanya job, -v menunjuk URI perangkat, dan -m everywhere memilih “driver” tanpa driver tadi. Untuk melihat URI apa saja yang tersedia, lpinfo -v mendaftarkannya — detail seluruh opsi ada di lpadmin(8) . Jalur alternatifnya adalah antarmuka web localhost:631 pada tab Administration → Add Printer, yang menuntun langkah yang sama lewat formulir; hasil akhirnya identik.

Antrian dalam Praktik: lp, lpstat, dan cancel #

Mencetak dari terminal memakai lp -d LaserKantor laporan.pdf, dan -d boleh dilewati bila antrian default sudah ditetapkan lewat lpoptions -d. Statusnya dipantau dengan lpstat; berikut contoh tampilan lpstat -t yang merangkum scheduler, antrian, dan job berjalan:

text
scheduler is running
system default destination: LaserKantor
printer LaserKantor is idle.  enabled since Jan 15 10:11
LaserKantor-42              budi               1024   Jan 15 10:11

Antrian sedang sehat: scheduler hidup, LaserKantor dalam keadaan idle, dan satu job milik budi sedang menunggu. Membatalkannya cukup cancel LaserKantor-42. Dua pasang perintah pelengkap layak diingat: cupsdisable/cupsenable menjeda dan melanjutkan pemrosesan antrian, sedangkan cupsreject/cupsaccept menolak dan menerima job baru — dua tombol yang berbeda tujuan.

Di Balik Layar: printers.conf #

Semua antrian yang kita buat tersimpan sebagai berkas teks /etc/cups/printers.conf — mengingat isinya sama dengan menjelaskan antrian tanpa membuka terminal:

bash
mkdir -p cups
cat > cups/printers.conf <<'EOF'
<Printer LaserKantor>
UUID urn:uuid:1c2f3a4b-5d6e-4f70-89ab-cdef01234567
Info HP LaserJet ruang meeting
DeviceURI ipp://192.0.2.10/ipp/print
State Idle
StateTime 1767225600
Accepting Yes
Shared Yes
ErrorPolicy retry-job
</Printer>
EOF
cat cups/printers.conf

Output yang Dihasilkan:

text
<Printer LaserKantor>
UUID urn:uuid:1c2f3a4b-5d6e-4f70-89ab-cdef01234567
Info HP LaserJet ruang meeting
DeviceURI ipp://192.0.2.10/ipp/print
State Idle
StateTime 1767225600
Accepting Yes
Shared Yes
ErrorPolicy retry-job
</Printer>

Mari kita bedah pasangan kunci-nilainya:

  1. <Printer LaserKantor> … </Printer>: satu blok per antrian; nama blok adalah nama yang dipakai lp -d.
  2. DeviceURI ipp://...: alamat backend — ke mana cetakan dikirim; versi lokal akan berbunyi usb://....
  3. State Idle: kondisi antrian saat ini; nilai lain yang sering muncul adalah Processing dan Stopped (antrian dijeda).
  4. Accepting Yes: pasangan flag cupsaccept/cupsreject — antrian ini masih menerima job baru.
  5. Shared Yes: antrian diiklankan ke jaringan — kunci dari pembagian printer di bawah.
  6. ErrorPolicy retry-job: kebijakan saat cetakan gagal; di sini CUPS mencoba mengulang job yang gagal.

Berbagi Printer di Jaringan #

Karena CUPS sudah berbicara HTTP, berbagi printer nyaris cuma soal membuka keran: di komputer pemilik printer, sudo cupsctl --share-printers mengaktifkan publikasi seluruh antrian bertanda Shared Yes, dan protokol mDNS membuat printer itu muncul otomatis di desktop lain. Klien yang tidak menunggu penemuan otomatis tinggal mendaftarkan URI jaringannya: sudo lpadmin -p LaserKantor -E -v ipp://192.0.2.20:631/printers/LaserKantor -m everywhere — perhatikan port 631 pada URI, sama seperti halaman web administrasinya. Tidak ada berkas driver yang lalu-lalang; yang berpindah hanya pekerjaan cetak.

Troubleshooting: Membaca error_log #

Ketika cetakan tidak keluar, jawabannya hampir selalu sudah tertulis di /var/log/cups/error_log. Tiap baris log diawali satu huruf — I informasi, W peringatan, E galat, C kritis — dan LogLevel di cupsd.conf mengatur seberapa banyak yang dicatat. Memfilter galat dan membuang kolom waktunya adalah keterampilan kunci; rincian seluruh status ada di lpstat(1) :

bash
cat > error_log <<'EOF'
I [15/Jan/2026:10:11:58 +0700] [Job 42] Adding start banner page "none".
I [15/Jan/2026:10:11:58 +0700] [Job 42] Queued on "LaserKantor" by "budi".
E [15/Jan/2026:10:12:01 +0700] [Job 42] Unsupported document-format "application/msword".
I [15/Jan/2026:10:12:01 +0700] [Job 42] Job canceled by "budi".
EOF
grep -c '^E ' error_log
grep '^E ' error_log | cut -d' ' -f4-

Output yang Dihasilkan:

text
1
[Job 42] Unsupported document-format "application/msword".

Dari empat baris itu, satu-satunya baris E langsung menunjuk biang keladi: dokumen berformat application/msword tidak didukung antrian tersebut — pengguna membatalkan jobnya sendiri. Cara bacanya: grep '^E ' menyisakan baris galat, lalu cut -d' ' -f4- membuang tiga kolom pertama (huruf kode, tanggal, zona waktu) agar pesannya terbaca jelas. Tabel gejala ringkasnya:

GejalaPeriksa dulu
Job masuk antrian lalu menghilangbaris E di error_log — biasanya filter gagal mengonversi format
Antrian berstatus Stoppedcupsenable LaserKantor lalu cek penyebabnya di log
Printer terdeteksi, hasil kosongmodel driver — coba ulang antrian dengan -m everywhere
Koneksi printer jaringan gagalURI ipp:// dan port 631 ke host printer

Pola “pekerjaan masuk antrian lalu digulirkan lewat log” ini mirip sekali dengan perangkat lepas-pasang lain: USB drive dan kartu SD juga lewat subsistem, antrean, dan titik pemeriksaan sebelum datanya berpindah. Kita bedah perangkat yang paling sering kita selipkan ke tas pada Chapter Removable Devices .

Berkas Sumber

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

cetak-file.sh

Unduh berkas
bash
#!/usr/bin/env bash
# cetak-file.sh -- pipeline cetak mini ala CUPS: teks -> filter -> backend berkas
# Pemakaian: bash cetak-file.sh <berkas-teks> [nama-printer]
# Hasil    : <berkas-teks>.prn berisi "halaman" siap kirim ke printer.
# Tanpa argumen: demo singkat pada berkas sementara.

if [ $# -eq 0 ]; then
    tmp=$(mktemp)
    printf 'halo dari filter cetak\n' > "$tmp"
    bash "$0" "$tmp" LaserKantor > /dev/null
    rm -f "$tmp" "$tmp.prn"
    echo "demo selesai di direktori sementara"
    exit 0
fi

berkas=$1
printer=${2:-LaserKantor}
hasil="$berkas.prn"

if [ ! -f "$berkas" ]; then
    echo "gagal: berkas $berkas tidak ditemukan"
    exit 0
fi

awk -v tugas="$berkas" -v printer="$printer" '
    BEGIN {
        garis = "+" substr("----------------------------------------------------", 1, 50) "+"
        print garis
        printf "| %-48s |\n", toupper(printer) " -- tugas: " tugas
        print garis
    }
    {
        printf "%3d  %s\n", NR, $0
    }
    END {
        print garis
        printf "| %-48s |\n", "halaman 1, " NR " baris"
        print garis
    }
' "$berkas" > "$hasil"

echo "backend: menulis ke $hasil"