Skrip pertama

Menulis skrip bash pertama dengan shebang, chmod +x, serta perbedaan eksekusi dan sourcing.

Daftar isi

Setelah rangkaian perintah dapat diketik dengan lancar di terminal, langkah berikutnya adalah menyimpan rangkaian itu ke dalam berkas sehingga dapat dipanggil ulang tanpa diketik ulang. Topik ini membahas cara menyusun skrip bash pertama, mulai dari baris shebang, pemberian izin eksekusi melalui chmod, hingga dua cara menjalankan berkas skrip, yaitu eksekusi sebagai program dan sourcing ke dalam shell yang sedang berjalan. Pekerjaan kecil yang sering diulang dapat disimpan sebagai satu berkas yang cukup dipanggil kapan pun dibutuhkan.

Dari perintah interaktif ke skrip#

Skrip paling baik ditulis untuk pekerjaan yang sudah dapat dikerjakan secara manual. Rangkaian perintah berikut adalah contohnya, yaitu membuat catatan singkat lalu menghitung jumlah barisnya. Ketik ketiga perintah ini di terminal, satu per satu, kemudian amati keluarannya.

bash
# pekerjaan kecil yang biasa diketik berulang kali di terminal
mkdir -p catatan
printf 'rapat mingguan\nbelanja bulanan\n' > catatan/agenda.txt
wc -l catatan/agenda.txt
text Keluaran
2 catatan/agenda.txt

Keluaran yang muncul persis sama apabila ketiga perintah itu disimpan ke dalam satu berkas dan dijalankan sekali saja. Urutan perintah pada skrip dieksekusi dari atas ke bawah, sebagaimana shell membaca ketikan di terminal. Prinsip ini penting untuk dipegang sejak awal, karena skrip tidak memiliki kemampuan baru yang tidak dimiliki terminal, melainkan hanya menyimpan urutan perintah yang sudah dikuasai.

Keuntungan menyimpan urutan perintah muncul ketika pekerjaan itu diulang. Mengetik ulang tiga perintah masih terkendali, tetapi rangkaian pekerjaan nyata biasanya memuat puluhan perintah dengan argumen yang panjang. Semakin panjang urutannya, semakin besar peluang satu langkah terlewat atau salah ketik. Berkas skrip menyimpan urutan itu sekali saja, sehingga pemanggilan ulang cukup dilakukan dengan satu perintah.

Baris shebang#

Berkas skrip adalah berkas teks biasa yang isinya berupa perintah bash, sehingga dapat dibuat dengan editor teks apa pun. Baris pertamanya memiliki peran khusus dan disebut shebang, yakni pasangan karakter #! diikuti jalur penerjemah yang digunakan saat berkas dijalankan langsung sebagai program. Kernel, yaitu inti sistem operasi, membaca baris ini untuk menentukan program yang mengolah sisa isi berkasnya. Untuk skrip bash, bentuk yang lazim adalah #!/usr/bin/env bash.

Perintah env dipilih alih-alih jalur tetap seperti /bin/bash karena env mencari bash pada variabel PATH sebelum menjalankannya. Dengan cara ini, skrip tetap berjalan pada sistem yang menempatkan bash di lokasi berbeda, misalnya di /usr/local/bin. Perbedaan ini terasa kecil pada satu komputer, tetapi berpengaruh ketika skrip yang sama digunakan di banyak sistem.

Skrip pertama bernama sapa.sh disimpan di samping topik ini dan berisi dua perintah printf. Baris set -euo pipefail pada awal skrip mengaktifkan strict mode, yaitu aturan penanganan error yang lebih ketat, sehingga kesalahan tidak berlanjut tanpa terdeteksi. Rincian opsi tersebut dibahas tuntas pada topik strict mode. Untuk saat ini, baris itu cukup dijadikan kebiasaan tetap pada setiap skrip bash.

bash sapa.sh
#!/usr/bin/env bash
# sapa.sh: skrip bash pertama

set -euo pipefail

printf 'Halo, dunia!\n'
printf 'Skrip pertama berhasil dijalankan.\n'

Menjalankan skrip dengan bash#

Cara pertama menjalankan skrip adalah memanggil penerjemahnya secara eksplisit. Perintah bash sapa.sh melahirkan proses bash baru yang membaca isi berkas lalu menjalankannya baris demi baris. Baris shebang pada cara ini hanya dianggap komentar, karena penerjemah sudah ditentukan oleh perintah yang dipanggil. Cara ini dapat digunakan kapan pun tanpa mengubah izin berkas, sehingga sering menjadi pilihan pertama saat skrip sedang dikembangkan. Jalankan perintah berikut dan bandingkan keluarannya dengan urutan interaktif pada bagian sebelumnya.

bash
# panggil penerjemah bash dengan nama berkas sebagai masukannya
bash sapa.sh
text Keluaran
Halo, dunia!
Skrip pertama berhasil dijalankan.

Keluarannya sama dengan hasil mengetik dua perintah printf satu per satu. Karakteristik cara ini perlu diperhatikan, yaitu seluruh eksekusi berlangsung di dalam proses bash yang baru lahir. Segala perubahan yang terjadi di dalam skrip, seperti penugasan variabel atau definisi fungsi, hilang bersama proses itu ketika skrip selesai. Setiap pemanggilan membaca berkas dari awal, sehingga hasil suntingan selalu terlihat pada pemanggilan berikutnya. Perilaku ini menjadi dasar pembahasan sourcing pada bagian akhir topik.

Izin eksekusi dengan chmod#

Cara kedua menjalankan skrip adalah memperlakukannya seperti program, yaitu mengetik jalurnya langsung. Kernel menuntut satu syarat sebelum mengizinkan cara ini, yaitu berkas harus memiliki izin eksekusi. Berkas skrip yang baru dibuat biasanya hanya memuat izin baca dan tulis, yaitu -rw-r--r--, sehingga izin eksekusi perlu ditambahkan. Perintah chmod dengan tambahan +x menambahkan izin tersebut, sedangkan izin berkas dapat diperiksa dengan stat -c '%A %n' yang menampilkan izin dan nama berkas.

bash
# tambahkan izin eksekusi, lalu periksa hasilnya
chmod +x sapa.sh
stat -c '%A %n' sapa.sh
text Keluaran
-rwxr-xr-x sapa.sh

Huruf x yang muncul pada keluaran menandakan izin eksekusi untuk pemilik berkas, kelompoknya, dan pengguna lain. Setelah izin terpasang, skrip dapat dipanggil langsung. Ketik ./sapa.sh untuk menjalankannya.

bash
# jalankan langsung sebagai program
./sapa.sh
text Keluaran
Halo, dunia!
Skrip pertama berhasil dijalankan.

Awalan ./ wajib ditulis dan menunjuk direktori saat ini. Shell tidak mencari program di direktori saat ini, melainkan hanya pada daftar direktori yang tersimpan di variabel PATH. Tanpa awalan tersebut, shell menganggap sapa.sh sebagai nama program yang berada di PATH dan melaporkan bahwa perintahnya tidak ditemukan. Dengan awalan ./, kernel membaca baris shebang lalu menyerahkan berkas kepada bash sesuai isinya.

Eksekusi dan sourcing#

Perintah bash sapa.sh dan ./sapa.sh sama-sama melahirkan proses baru. Cara ketiga, yaitu sourcing, bekerja berbeda, yakni menjalankan isi berkas pada shell yang sedang berjalan tanpa melahirkan proses baru. Perintah source digunakan untuk itu. Perbedaan isolasinya dapat diamati lebih dahulu lewat subshell, yaitu proses salinan yang lahir dari sepasang tanda kurung, dengan demonstrasi berikut.

bash
# subshell menjalankan salinan shell, perubahan tidak mengalir balik
(warna="dalam-subshell"; printf 'di dalam subshell: %s\n' "$warna")
printf 'di shell induk: %s\n' "${warna-belum-ada}"
text Keluaran
di dalam subshell: dalam-subshell
di shell induk: belum-ada

Nilai warna hidup hanya di dalam proses salinan dan tidak dikenal pada shell induk. Proses anak yang lahir dari bash sapa.sh berperilaku sama, sehingga variabel maupun fungsi yang didefinisikan di dalam skrip ikut hilang ketika skrip selesai. Perilaku ini menjaga shell interaktif tetap bersih dari efek samping skrip yang dijalankannya.

Kondisi berubah ketika definisi memang dirancang untuk dipakai ulang, misalnya sekumpulan fungsi salam yang disimpan sebagai library, yakni berkas definisi yang dimuat oleh skrip lain. Berkas lib.sh berisi definisi seperti itu. Berkas library tidak wajib memuat shebang karena tidak pernah dijalankan langsung sebagai program, melainkan selalu dimuat oleh shell lain.

bash lib.sh
# lib.sh: library definisi yang dimuat melalui sourcing

SALAM="Halo"

sapa() {
    printf '%s, dunia!\n' "$SALAM"
}

Jalankan lib.sh sebagai program anak terlebih dahulu untuk melihat efeknya.

bash
# jalankan lib.sh sebagai program anak
bash lib.sh

Tidak ada keluaran yang muncul dan tidak ada pula yang berubah pada shell yang menjalankan perintah itu. Sekarang muat berkas yang sama melalui sourcing.

bash
# muat definisi ke dalam shell yang sedang berjalan
source lib.sh

Setelah sourcing, fungsi sapa dan variabel SALAM hidup pada shell yang sedang dipakai dan langsung dapat dipanggil.

bash
# fungsi dari library kini dapat dipanggil
sapa
text Keluaran
Halo, dunia!
bash
# variabel yang didefinisikan di dalam library juga ikut dimuat
printf 'SALAM berisi %s\n' "$SALAM"
text Keluaran
SALAM berisi Halo

Kesalahan umum#

Skrip tidak dapat dijalankan langsung dengan pesan Permission denied. Kesalahan ini muncul ketika ./nama.sh diketik padahal izin eksekusi belum diberikan. Kernel menolak menjalankan berkas yang tidak memuat huruf x pada izinnya. Perbaikannya adalah chmod +x nama.sh, atau memanggil skrip melalui penerjemah dengan bash nama.sh, yang tidak menuntut izin eksekusi apa pun.

Shebang tidak berada pada baris pertama. Kernel hanya membaca baris pertama berkas untuk menemukan penerjemahnya. Baris kosong atau komentar di atasnya menggeser shebang dari posisi pertama, sehingga pemanggilan langsung kehilangan acuan penerjemah. Pastikan #!/usr/bin/env bash selalu menjadi baris paling atas, tanpa spasi di depannya.

Mengharapkan efek sourcing dari pemanggilan biasa. Berkas library yang dipanggil dengan bash lib.sh tidak meninggalkan definisi apa pun pada shell yang memanggilnya. Efek itu hanya muncul melalui source, karena hanya sourcing yang menjalankan isi berkas pada shell saat ini. Apabila sebuah fungsi tetap tidak dikenal setelah berkasnya dimuat, periksa apakah berkasnya dimuat dengan source atau hanya dijalankan sebagai program.

Ringkasan#

  • Skrip bash adalah urutan perintah yang sama dengan yang diketik di terminal, disimpan dalam berkas teks dan dijalankan dari atas ke bawah.
  • Baris shebang #!/usr/bin/env bash menyatakan penerjemah yang digunakan kernel saat berkas dijalankan langsung sebagai program.
  • bash nama.sh dapat digunakan kapan pun, sedangkan ./nama.sh menuntut izin eksekusi dari chmod +x.
  • Eksekusi melahirkan proses baru yang mengisolasi variabel dan fungsi, sedangkan sourcing memuat definisi ke dalam shell yang sedang berjalan.

Referensi#