Cara Menggunakan eval di Linux Bash Script

Diterbitkan: 2022-08-22
Laptop Linux menampilkan prompt bash
fatmawati achmad zaenuri/Shutterstock.com

Dari semua perintah Bash, eval tua yang malang mungkin memiliki reputasi terburuk. Dibenarkan, atau hanya pers yang buruk? Kami membahas penggunaan dan bahaya dari perintah Linux yang paling tidak disukai ini.

Kita Perlu Bicara Tentang eval

Digunakan sembarangan, eval dapat menyebabkan perilaku tak terduga dan bahkan ketidakamanan sistem. Dari suaranya, kita mungkin tidak boleh menggunakannya, kan? Yah tidak cukup.

Anda bisa mengatakan hal serupa tentang mobil. Di tangan yang salah, mereka adalah senjata mematikan. Orang-orang menggunakannya dalam ram-razia dan sebagai kendaraan untuk melarikan diri. Haruskah kita semua berhenti menggunakan mobil? Tidak, tentu saja tidak. Tetapi mereka harus digunakan dengan benar, dan oleh orang-orang yang tahu cara mengemudikannya.

Cara Bekerja dengan Variabel di Bash
TERKAIT Cara Bekerja dengan Variabel di Bash

Kata sifat yang biasa diterapkan pada eval adalah "jahat." Tapi itu semua bermuara pada bagaimana itu digunakan. Perintah eval menyusun nilai dari satu atau lebih variabel. Ini menciptakan string perintah. Kemudian menjalankan perintah itu. Ini membuatnya berguna ketika Anda perlu mengatasi situasi di mana konten perintah diturunkan secara dinamis selama eksekusi skrip Anda.

Masalah muncul ketika skrip ditulis untuk menggunakan eval pada string yang telah diterima dari suatu tempat di luar skrip. Ini dapat diketik oleh pengguna, dikirim melalui API, ditandai ke permintaan HTTPS, atau di mana pun di luar skrip.

Jika string yang akan dikerjakan eval tidak diturunkan secara lokal dan terprogram, ada risiko bahwa string tersebut mungkin berisi instruksi berbahaya yang disematkan atau input dengan format buruk lainnya. Jelas, Anda tidak ingin eval menjalankan perintah jahat. Jadi untuk amannya, jangan gunakan eval dengan string atau input pengguna yang dibuat secara eksternal.

Langkah Pertama Dengan eval

Perintah eval adalah perintah shell Bash bawaan. Jika Bash hadir, eval akan hadir.

eval menggabungkan parameternya menjadi satu string. Ini akan menggunakan satu ruang untuk memisahkan elemen gabungan. Ini mengevaluasi argumen dan kemudian meneruskan seluruh string ke shell untuk dieksekusi.

Mari kita buat sebuah variabel bernama wordcount .

 wordcount="wc -w raw-notes.md"

Variabel string berisi perintah untuk menghitung kata dalam file bernama “raw-notes.md.”

Kita dapat menggunakan eval untuk menjalankan perintah itu dengan memberikan nilai variabelnya.

 eval " $wordcount "

Menggunakan eval dengan variabel string untuk menghitung kata-kata dalam file

Perintah dijalankan di shell saat ini, bukan di subkulit. Kita dapat dengan mudah menunjukkan ini. Kami memiliki file teks pendek bernama “variables.txt”. Ini berisi dua baris ini.

 pertama=Bagaimana caranya
detik=Geek

Kami akan menggunakan cat untuk mengirim baris ini ke jendela terminal. Kemudian kita akan menggunakan eval untuk mengevaluasi perintah cat sehingga instruksi di dalam file teks ditindaklanjuti. Ini akan mengatur variabel untuk kita.

 variabel kucing.txt
eval "$(variabel kucing.txt)"
echo $pertama $detik 

Mengakses variabel yang diatur oleh eval di shell saat ini

Dengan menggunakan echo untuk mencetak nilai variabel, kita dapat melihat bahwa perintah eval berjalan di shell saat ini, bukan subkulit.

Proses dalam subkulit tidak dapat mengubah lingkungan shell induknya. Karena eval berjalan di shell saat ini, variabel yang ditetapkan oleh eval dapat digunakan dari shell yang meluncurkan perintah eval .

Perhatikan bahwa jika Anda menggunakan eval dalam skrip, shell yang akan diubah oleh eval adalah subkulit yang menjalankan skrip, bukan shell yang meluncurkannya.

TERKAIT: Cara Menggunakan Perintah kucing dan tac Linux

Menggunakan Variabel dalam String Perintah

Kita dapat memasukkan variabel lain dalam string perintah. Kami akan menetapkan dua variabel untuk menampung bilangan bulat.

 nomor1=10 
bilangan2=7

Kami akan membuat variabel untuk menampung perintah expr yang akan mengembalikan jumlah dua angka. Ini berarti kita perlu mengakses nilai dari dua variabel integer dalam perintah. Perhatikan tanda backtick di sekitar pernyataan expr .

 add="`expr $num1 + $num2`"

Kami akan membuat perintah lain untuk menunjukkan kepada kami hasil dari pernyataan expr .

 tampilkan = "gema"

Perhatikan bahwa kita tidak perlu menyertakan spasi di akhir string echo , atau di awal string expr . eval menangani itu.

Dan untuk menjalankan seluruh perintah yang kami gunakan:

 eval $tampilkan $tambahkan 

Menggunakan variabel dalam string perintah

Nilai variabel di dalam string expr diganti ke dalam string dengan eval , sebelum diteruskan ke shell untuk dieksekusi.

TERKAIT: Cara Bekerja dengan Variabel di Bash

Mengakses Variabel Di Dalam Variabel

Anda dapat menetapkan nilai ke variabel, lalu menetapkan nama variabel tersebut ke variabel lain. Menggunakan eval , Anda dapat mengakses nilai yang disimpan dalam variabel pertama, dari namanya yang merupakan nilai yang disimpan dalam variabel kedua. Sebuah contoh akan membantu Anda menguraikannya.

Salin skrip ini ke editor, dan simpan sebagai file bernama “assign.sh.”

 #!/bin/bash

title="How-To Geek"
halaman web=judul
perintah = "gema"
eval $command \${$halaman web}

Kita perlu membuatnya dapat dieksekusi dengan perintah chmod .

 chmod +x assign.sh 

Menggunakan chmod untuk membuat skrip dapat dieksekusi

Anda harus melakukan ini untuk skrip apa pun yang Anda salin dari artikel ini. Cukup gunakan nama skrip yang sesuai dalam setiap kasus.

Ketika kita menjalankan skrip kita, kita melihat teks dari title variabel meskipun perintah eval menggunakan webpage variabel.

 ./assign.sh 

Mengakses nilai variabel dari namanya yang disimpan di variabel lain

Tanda dolar yang lolos “ $ ” dan kurung kurawal “ {} ” menyebabkan eval melihat nilai yang disimpan di dalam variabel yang namanya disimpan dalam variabel webpage .

Menggunakan Variabel yang Dibuat Secara Dinamis

Kita dapat menggunakan eval untuk membuat variabel secara dinamis. Skrip ini disebut "loop.sh."

 #!/bin/bash

jumlah = 0
label="Perulangan selesai. Total:"

untuk n dalam {1..10}
melakukan
  evaluasi x$n=$n
  echo "Lingkaran" $x$n
  ((total+=$x$n))
selesai

echo $x1 $x2 $x3 $x4 $x5 $x6 $x7 $x8 $x9 $x10

echo $label $total

Itu menciptakan variabel yang disebut total yang menampung jumlah nilai dari variabel yang kita buat. Kemudian membuat variabel string yang disebut label . Ini adalah string teks sederhana.

Kita akan mengulang 10 kali dan membuat 10 variabel yang disebut x1 hingga x10 . Pernyataan eval di badan loop menyediakan "x" dan mengambil nilai penghitung loop $n untuk membuat nama variabel. Pada saat yang sama, ia menetapkan variabel baru ke nilai penghitung loop $n .

9 Contoh For Loops di Linux Bash Script
TERKAIT 9 Contoh for Loops di Linux Bash Script

Ini mencetak variabel baru ke jendela terminal dan kemudian menambah variabel total dengan nilai variabel baru.

Di luar loop, 10 variabel baru dicetak sekali lagi, semuanya dalam satu baris. Perhatikan bahwa kita juga dapat merujuk ke variabel dengan nama aslinya, tanpa menggunakan versi yang dihitung atau diturunkan dari namanya.

Akhirnya, kami mencetak nilai variabel total .

 ./loop.sh 

Menggunakan eval untuk membuat variabel secara dinamis

TERKAIT: Primer: Bash Loops: untuk, sementara, dan sampai

Menggunakan eval Dengan Array

Bayangkan sebuah skenario di mana Anda memiliki skrip yang berjalan lama dan melakukan beberapa pemrosesan untuk Anda. Itu menulis ke file log dengan nama yang dibuat dari cap waktu. Kadang-kadang, itu akan memulai file log baru. Ketika skrip selesai, jika tidak ada kesalahan, itu menghapus file log yang telah dibuatnya.

Anda tidak ingin hanya rm *.log , Anda hanya ingin menghapus file log yang telah dibuatnya. Script ini mensimulasikan fungsionalitas itu. Ini adalah "clear-logs.sh."

 #!/bin/bash

mendeklarasikan -a logfiles

jumlah file = 0 
rm_string = "gema"

fungsi create_logfile() {
  ((++ jumlah file))
  namafile=$(tanggal +"%Y-%m-%d_%H-%M-%S").log
  logfiles[$filecount]=$namafile
  echo $filecount "Dibuat" ${logfiles[$filecount]}
}

# isi skrip. Beberapa pemrosesan dilakukan di sini
# secara berkala menghasilkan file log. Kami akan mensimulasikannya
buat_logfile
tidur 3
buat_logfile
tidur 3
buat_logfile
tidur 3
buat_logfile

# apakah ada file yang harus dihapus?
untuk ((file=1; file<=$filecount; file++))
melakukan
  # hapus file log
  eval $rm_string ${logfiles[$file]} "dihapus..."
  file log[$file]=""
selesai

Script mendeklarasikan sebuah array yang disebut logfiles . Ini akan menyimpan nama file log yang dibuat oleh skrip. Ini mendeklarasikan variabel yang disebut filecount . Ini akan menampung jumlah file log yang telah dibuat.

Itu juga mendeklarasikan string yang disebut rm_string . Dalam skrip dunia nyata, ini akan berisi perintah rm , tetapi kami menggunakan echo sehingga kami dapat mendemonstrasikan prinsip dengan cara yang tidak merusak.

Fungsi create_logfile() adalah tempat setiap file log diberi nama, dan di mana akan dibuka. Kami hanya membuat nama file , dan berpura-pura telah dibuat di sistem file.

Fungsi menambah variabel jumlah filecount . Nilai awalnya adalah nol, jadi nama file pertama yang kita buat disimpan di posisi satu dalam array. Ini dilakukan dengan sengaja, juga lihat nanti.

Nama file dibuat menggunakan perintah date , dan ekstensi ".log". Nama disimpan dalam array pada posisi yang ditunjukkan oleh filecount . Nama dicetak ke jendela terminal. Dalam skrip dunia nyata, Anda juga akan membuat file yang sebenarnya.

Cara Menjeda Skrip Bash Dengan Perintah Tidur Linux
TERKAIT Cara Menjeda Skrip Bash Dengan Perintah Tidur Linux

Tubuh skrip disimulasikan menggunakan perintah sleep . Itu membuat file log pertama, menunggu tiga detik, dan kemudian membuat yang lain. Itu membuat empat file log, diberi jarak sehingga cap waktu dalam nama file mereka berbeda.

Akhirnya, ada loop yang menghapus file log. File penghitung loop diatur ke satu. Itu menghitung hingga dan termasuk nilai filecount , yang menampung jumlah file yang dibuat.

Jika filecount masih disetel ke nol—karena tidak ada file log yang dibuat—badan loop tidak akan pernah dieksekusi karena satu tidak kurang dari atau sama dengan nol. Itu sebabnya variabel jumlah filecount disetel ke nol ketika dideklarasikan dan mengapa itu bertambah sebelum file pertama dibuat.

Di dalam loop, kami menggunakan eval dengan rm_string non-destruktif kami dan nama file yang diambil dari array. Kami kemudian mengatur elemen array ke string kosong.

Inilah yang kami lihat ketika kami menjalankan skrip.

 ./clear-logs.sh 

Menghapus file yang namanya disimpan dalam array

Tidak Semuanya Buruk

Eval yang banyak eval pasti ada gunanya. Seperti kebanyakan alat, digunakan sembarangan itu berbahaya, dan dalam lebih dari satu cara.

Jika Anda memastikan string yang digunakannya dibuat secara internal dan tidak diambil dari manusia, API, atau hal-hal seperti permintaan HTTPS, Anda akan menghindari perangkap utama.

TERKAIT: Cara Menampilkan Tanggal dan Waktu di Terminal Linux (dan Menggunakannya Dalam Skrip Bash)