Riwayat Perintah

Memanfaatkan history, tombol panah, dan Ctrl-R untuk bekerja lebih cepat.

Daftar isi

Topik ini membahas daftar riwayat perintah yang dicatat bash pada sesi interaktif. Daftar itu ditampilkan dengan history, ditelusuri dengan tombol panah, dan dicari dengan Ctrl-R. Entri di dalamnya dapat dijalankan ulang lewat ekspansi riwayat, sedangkan ukuran dan penyimpanannya juga dapat diatur. Setelah membacanya, perintah yang panjang dapat dipanggil kembali tanpa diketik ulang, dan variasi dari baris lama dapat disunting dengan cepat.

Daftar riwayat dan perintah history#

Bash menyimpan setiap baris perintah yang diketik pada sesi interaktif ke dalam daftar riwayat di memori. Daftar ini bernomor mulai dari satu untuk entri terlama, dan setiap sesi terminal memiliki daftarnya sendiri. Ketika sesi ditutup secara normal, isi daftar dituliskan ke berkas riwayat yang namanya disimpan variabel HISTFILE, secara bawaan ~/.bash_history. Sesi berikutnya kemudian dapat memuat kembali isi berkas itu.

Sesi pada halaman ini berjalan tanpa terminal interaktif, sehingga perekaman riwayat diperlihatkan melalui shell interaktif baru yang dijalankan di dalam sesi skrip. Tiga baris di dalam printf berperan sebagai perintah yang diketik, HISTFILE=/dev/null menjaga agar riwayat sementara itu tidak menulis berkas apa pun, dan PS1 disetel sederhana. Karena shell berjalan tanpa terminal fisik, bash mencetak pesan peringatan job control, yaitu fitur pengelolaan pekerjaan di latar depan dan latar belakang. Pesan itu dibuang ke /dev/null, sehingga yang tersisa hanya keluaran perintahnya.

bash
# memulai shell interaktif baru lalu mengalirkan tiga baris perintah ke dalamnya
printf 'echo satu\necho dua\nhistory 3\n' | HISTFILE=/dev/null PS1='$ ' bash -i 2>/dev/null
text Keluaran
satu
dua
    1  echo satu
    2  echo dua
    3  history 3

Keluaran history terdiri atas dua kolom, yaitu nomor entri dan baris perintahnya. Entri terlama berada di atas, sehingga nomor 1 adalah perintah pertama sesi tersebut. Argumen angka membatasi tampilan, dan history 3 hanya mencantumkan tiga entri terakhir. Tanpa argumen, seluruh daftar dicetak hingga batas yang disetel oleh variabel HISTSIZE.

Penyimpanan ke berkas terjadi pada saat shell ditutup, bukan setiap kali perintah selesai dijalankan. Blok berikut memeriksa mekanisme itu: shell interaktif baru menjalankan satu perintah, menutup dirinya, lalu isi berkas riwayatnya dibaca dengan cat.

bash
# riwayat sesi interaktif tersimpan ketika shell ditutup
mkdir -p /tmp/kerja-riwayat
rm -f /tmp/kerja-riwayat/hist-demo
printf 'echo catat-awal\n' | HISTFILE=/tmp/kerja-riwayat/hist-demo PS1='$ ' bash -i 2>/dev/null
cat /tmp/kerja-riwayat/hist-demo
text Keluaran
catat-awal
echo catat-awal

Baris pertama adalah keluaran perintah di dalam shell baru, sedangkan baris kedua adalah isi berkas riwayatnya. Berkas tersebut memuat baris perintah apa adanya tanpa nomor, dan penomoran baru diberikan ketika daftar dimuat ke sesi berikutnya.

Menelusuri riwayat dengan tombol panah#

Cara paling cepat memanggil kembali perintah terdahulu adalah tombol panah atas dan bawah yang ditangani pustaka readline. Tombol panah atas menampilkan entri yang lebih lama satu demi satu, sedangkan tombol panah bawah bergerak kembali ke arah yang lebih baru. Baris yang tampil dapat disunting langsung sebelum Enter ditekan, misalnya mengganti nama berkas di dalamnya, sehingga perbaikan ejaan pada perintah panjang selesai dalam beberapa tekan tombol.

TombolEfek
↑menampilkan entri yang lebih lama
↓menampilkan entri yang lebih baru
Entermenjalankan baris yang sedang tampil
Ctrl-Cmembatalkan baris yang diambil dan menampilkan prompt kosong

Penelusuran dengan tombol panah hanya menyentuh daftar sesi yang sedang berjalan. Sesi lain di jendela terminal yang berbeda memiliki daftar tersendiri sampai masing-masing ditutup dan menuliskan isinya ke berkas riwayat. Karena interaksi semacam ini tidak meninggalkan keluaran yang dapat direkam sebagai teks, cara mengenalinya adalah mencobanya langsung pada terminal, misalnya menekan panah atas beberapa kali lalu menyunting sebagian baris sebelum menjalankannya.

Pencarian mundur dengan Ctrl-R#

Untuk daftar yang panjang, menelusuri satu per satu dengan tombol panah menjadi lambat. Kombinasi Ctrl-R memulai pencarian mundur (reverse search), yaitu pencarian dari entri terbaru menuju entri yang lebih lama. Setelah Ctrl-R ditekan, prompt berubah menjadi tanda pencarian, dan setiap karakter yang diketik langsung menyaring daftar sehingga kecocokan terbaru tampil di tempatnya.

TekanEfek
Ctrl-Rmemulai pencarian mundur, ditekan lagi untuk kecocokan yang lebih lama
karakter kata kuncimemperbarui kecocokan pada setiap ketikan
tombol panah kananmenghentikan pencarian dan mengambil barisnya untuk disunting
Entermenjalankan baris yang sedang cocok
Ctrl-Gmembatalkan pencarian dan mengembalikan prompt kosong

Seluruh proses ini terjadi pada baris masukan, sehingga keluarannya tidak dapat direkam di halaman ini. Pola pemakaiannya tetap dapat diringkas: tekan Ctrl-R, ketik sebagian kata yang diingat dari perintah lama, ulangi Ctrl-R bila kecocokan yang tampil bukan yang dicari, lalu jalankan atau sunting barisnya. Pencarian Ctrl-R menggunakan daftar yang sama dengan tombol panah, sehingga keduanya saling melengkapi: tombol panah untuk entri terdekat, sedangkan Ctrl-R untuk entri yang lebih jauh. Apabila pencarian tidak menemukan apa pun, perintah yang dicari mungkin berasal dari sesi yang berbeda. Daftar sesi tersebut belum tentu sudah dituliskan ke berkas riwayat bersama.

Menjalankan ulang dengan ekspansi riwayat#

Bash menyediakan ekspansi riwayat (history expansion), yaitu penggantian bagian baris dengan entri daftar riwayat sebelum baris itu dijalankan. Penanda yang paling sering dipakai adalah !!, yang berarti baris perintah terakhir dan diganti seluruhnya.

bash
# !! menjalankan ulang baris perintah terakhir
printf 'echo kalibrasi-dimulai\n!!\n' | HISTFILE=/dev/null PS1='$ ' bash -i 2>/dev/null
text Keluaran
kalibrasi-dimulai
kalibrasi-dimulai

Bentuk yang menyertai sudo juga lazim dipakai. Perintah yang diketik tanpa hak administratif, misalnya pembacaan berkas milik sistem, dapat diulang dengan sudo !! tanpa mengetik ulang seluruh barisnya.

Penanda !$ berarti argumen terakhir baris sebelumnya. Bentuk ini praktis ketika argumen panjang perlu dipakai dua kali, misalnya membuat direktori lalu langsung masuk ke dalamnya.

bash
# !$ dipakai ulang sebagai argumen terakhir baris sebelumnya
printf 'mkdir -p /tmp/kerja-riwayat/arsip\ncd !$\npwd\n' | HISTFILE=/dev/null PS1='$ ' bash -i 2>/dev/null
text Keluaran
/tmp/kerja-riwayat/arsip

Perintah pwd mencetak jalur yang sama dengan argumen mkdir tadi, karena cd !$ diperluas menjadi cd /tmp/kerja-riwayat/arsip. Penanda juga dapat menyebut nomor entri, misalnya !1 untuk entri pertama sesuai daftar history.

Pengaturan ukuran dan penyimpanan riwayat#

Jumlah entri yang disimpan diatur oleh variabel HISTSIZE, sedangkan HISTFILESIZE mengatur jumlah maksimum baris pada berkas riwayat. Nilai keduanya dapat dibaca pada shell interaktif baru.

bash
# membaca nilai bawaan riwayat pada shell interaktif baru
printf 'echo "HISTSIZE=$HISTSIZE"\necho "HISTFILESIZE=$HISTFILESIZE"\n' | HISTFILE=/dev/null PS1='$ ' bash -i 2>/dev/null
text Keluaran
HISTSIZE=500
HISTFILESIZE=500

Nilai 500 di atas adalah bawaan bash pada shell tanpa berkas konfigurasi pengguna. Ubuntu menyertakan ~/.bashrc bawaan yang menaikkan kedua nilai tersebut menjadi 1000 dan 2000, sehingga keluaran pada mesin latihan dapat berbeda. Kedua variabel diatur dengan penugasan biasa, misalnya HISTSIZE=2000, dan penugasannya diletakkan di ~/.bashrc agar berlaku pada setiap sesi. Riwayat sesi yang sedang berjalan dapat dibersihkan dengan history -c.

Perilaku pencatatan juga dapat diatur. Variabel HISTCONTROL dengan nilai ignoredups menekan entri yang sama secara berurutan, sedangkan nilai ignorespace mengabaikan baris yang diawali spasi. Dua blok berikut membandingkan daftar yang sama dengan dan tanpa pengaturan tersebut.

bash
# dua perintah identik berurutan tanpa HISTCONTROL
printf 'echo stok=12\necho stok=12\nhistory 4\n' | HISTFILE=/dev/null PS1='$ ' bash -i 2>/dev/null
text Keluaran
stok=12
stok=12
    1  echo stok=12
    2  echo stok=12
    3  history 4
bash
# contoh yang sama dengan HISTCONTROL=ignoredups
printf 'echo stok=12\necho stok=12\nhistory 4\n' | HISTCONTROL=ignoredups HISTFILE=/dev/null PS1='$ ' bash -i 2>/dev/null
text Keluaran
stok=12
stok=12
    1  echo stok=12
    2  history 4

Tanpa pengaturan, dua entri echo stok=12 tercatat berurutan. Dengan HISTCONTROL=ignoredups, entri kedua tidak dicatat karena sama dengan entri di depannya, sehingga history 4 hanya menampilkan dua entri. Variabel HISTIGNORE melengkapi keduanya dengan menerima pola baris yang sepenuhnya diabaikan, misalnya HISTIGNORE="ls:pwd" untuk baris ls dan pwd.

Kesalahan umum#

Mengira riwayat sudah tersimpan di berkas. Penyimpanan terjadi ketika shell ditutup secara normal, sehingga entri yang dicatat belum ada di ~/.bash_history selama sesi masih terbuka. Terminal yang mati mendadak atau sesi yang diputus tanpa perintah exit dapat kehilangan entri terakhirnya. Tutup sesi dengan exit apabila riwayatnya masih dibutuhkan.

Menjalankan ekspansi !kata tanpa memeriksa entri yang dituju. Kecocokan diambil dari entri terbaru yang diawali kata tersebut, dan perintahnya langsung dieksekusi tanpa konfirmasi. Bila kata kuncinya terlalu umum, misalnya !s, baris yang dijalankan bisa jadi bukan yang dimaksud. Telusuri nomornya lewat history terlebih dahulu, lalu panggil dengan nomornya seperti !12.

Mengharapkan ekspansi bekerja di dalam skrip. Ekspansi riwayat hanya aktif pada shell interaktif, sehingga baris seperti !! pada skrip diteruskan apa adanya dan tidak menjalankan ulang apa pun. Skrip mengakses argumen lewat parameter posisi atau variabel, bukan lewat daftar riwayat.

Ringkasan#

  • history mencantumkan daftar perintah sesi beserta nomornya, dan daftar itu dituliskan ke HISTFILE ketika shell ditutup secara normal.
  • Tombol panah menelusuri entri satu demi satu, sedangkan Ctrl-R mencari mundur berdasarkan kata kunci langsung dari baris masukan.
  • Ekspansi riwayat seperti !!, !$, dan !kata menjalankan ulang entri tanpa mengetik ulang, tetapi hanya aktif pada shell interaktif.
  • HISTSIZE, HISTFILESIZE, dan HISTCONTROL mengatur jumlah entri, ukuran berkas riwayat, serta entri yang diabaikan.

Referensi#