Linux Bash Komut Dosyalarında eval Nasıl Kullanılır

Yayınlanan: 2022-08-22
Bir bash istemi gösteren Linux dizüstü bilgisayar
fatmawati achmad zaenuri/Shutterstock.com

Tüm Bash komutları arasında, zavallı eski eval muhtemelen en kötü itibara sahiptir. Haklı mı yoksa sadece kötü basın mı? Bu en az sevilen Linux komutlarının kullanımını ve tehlikelerini tartışıyoruz.

Eval Hakkında Konuşmalıyız

eval kullanıldığında, değerlendirme öngörülemeyen davranışlara ve hatta sistem güvensizliklerine yol açabilir. Seslerine bakılırsa muhtemelen kullanmamalıyız, değil mi? Pek iyi değil.

Otomobiller için de benzer bir şey söyleyebilirsiniz. Yanlış ellerde, ölümcül bir silahtırlar. İnsanlar onları baskınlarda ve kaçış araçları olarak kullanıyor. Hepimiz araba kullanmayı bırakmalı mıyız? Hayır tabii değil. Ancak doğru şekilde ve onları sürmeyi bilen kişiler tarafından kullanılmaları gerekir.

Bash'de Değişkenlerle Nasıl Çalışılır
İLGİLİ Bash'de Değişkenlerle Nasıl Çalışılır

eval için kullanılan genel sıfat “kötülük”tür. Ama her şey nasıl kullanıldığına bağlı. eval komutu, bir veya daha fazla değişkenden gelen değerleri toplar. Bir komut dizisi oluşturur. Daha sonra bu komutu yürütür. Bu, komut dosyanızın yürütülmesi sırasında bir komutun içeriğinin dinamik olarak türetildiği durumlarla başa çıkmanız gerektiğinde kullanışlı hale getirir.

Bir komut dosyası, komut dosyasının dışında bir yerden alınan bir dizede eval kullanmak üzere yazıldığında sorunlar ortaya çıkar. Bir kullanıcı tarafından yazılabilir, bir API aracılığıyla gönderilebilir, bir HTTPS isteğine etiketlenebilir veya komut dosyasının dışında herhangi bir yerde olabilir.

eval üzerinde çalışacağı dize yerel ve programlı olarak türetilmediyse, dizenin gömülü kötü niyetli yönergeler veya diğer hatalı biçimlendirilmiş girdiler içerme riski vardır. Açıkçası, eval kötü amaçlı komutları yürütmesini istemezsiniz. Güvende olmak için, harici olarak oluşturulmuş dizeler veya kullanıcı girişi ile eval kullanmayın.

Eval ile İlk Adımlar

eval komutu, yerleşik bir Bash kabuk komutudur. Bash varsa, eval mevcut olacaktır.

eval , parametrelerini tek bir dizede birleştirir. Birleştirilmiş öğeleri ayırmak için tek bir boşluk kullanır. Argümanları değerlendirir ve ardından tüm dizeyi yürütülecek kabuğa iletir.

Şimdi wordcount adında bir değişken oluşturalım.

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

Dize değişkeni, "raw-notes.md" adlı bir dosyadaki sözcükleri saymak için bir komut içerir.

Bu komutu, değişkenin değerini ileterek yürütmek için eval kullanabiliriz.

 eval " $wordcount "

Bir dosyadaki kelimeleri saymak için bir dize değişkeni ile eval kullanma

Komut, bir alt kabukta değil, geçerli kabukta yürütülür. Bunu kolayca gösterebiliriz. “variables.txt” adında kısa bir metin dosyamız var. Bu iki satırı içerir.

 first=Nasıl Yapılır
ikinci = Geek

Bu satırları terminal penceresine göndermek için cat kullanacağız. Ardından, metin dosyasının içindeki talimatların yerine getirilmesi için bir cat komutunu değerlendirmek için eval kullanacağız. Bu bizim için değişkenleri ayarlayacaktır.

 kedi değişkenleri.txt
değerlendirme "$(kedi değişkenleri.txt)"
echo $ilk $saniye 

Geçerli kabukta eval tarafından ayarlanan değişkenlere erişme

Değişkenlerin değerlerini yazdırmak için echo kullanarak, eval komutunun bir alt kabukta değil, geçerli kabukta çalıştığını görebiliriz.

Alt kabuktaki bir işlem, üst öğenin kabuk ortamını değiştiremez. eval geçerli kabukta çalıştığından, eval tarafından ayarlanan değişkenler, eval komutunu başlatan kabuktan kullanılabilir.

Bir komut dosyasında eval kullanırsanız, eval tarafından değiştirilecek kabuğun, onu başlatan kabuk değil, komut dosyasının içinde çalıştığı alt kabuk olduğunu unutmayın.

İLGİLİ: Linux cat ve tac Komutları Nasıl Kullanılır

Komut Dizisinde Değişkenleri Kullanma

Komut dizelerine diğer değişkenleri dahil edebiliriz. Tamsayıları tutmak için iki değişken ayarlayacağız.

 sayı1=10 
sayı2=7

İki sayının toplamını döndürecek bir expr komutunu tutacak bir değişken oluşturacağız. Bu, komuttaki iki tamsayı değişkeninin değerlerine erişmemiz gerektiği anlamına gelir. expr ifadesinin etrafındaki geri dönüşlere dikkat edin.

 add="`expr $sayı1 + $sayı2`"

Bize expr ifadesinin sonucunu göstermek için başka bir komut oluşturacağız.

 göster="eko"

echo dizesinin sonuna veya expr dizesinin başına bir boşluk eklememiz gerekmediğine dikkat edin. eval bununla ilgilenir.

Ve kullandığımız tüm komutu yürütmek için:

 değerlendirme $göster $ekle 

Komut dizesinde değişkenleri kullanma

expr dizesindeki değişken değerleri, yürütülecek kabuğa iletilmeden önce eval tarafından dizeye değiştirilir.

İLGİLİ: Bash'de Değişkenlerle Nasıl Çalışılır

Değişkenlerin İçindeki Değişkenlere Erişme

Bir değişkene bir değer atayabilir ve ardından o değişkenin adını başka bir değişkene atayabilirsiniz. eval kullanarak, ikinci değişkende saklanan değer olan adından birinci değişkende tutulan değere erişebilirsiniz. Bir örnek bunu çözmenize yardımcı olacaktır.

Bu komut dosyasını bir düzenleyiciye kopyalayın ve "assign.sh" adlı bir dosya olarak kaydedin.

 #!/bin/bash

title="Nasıl Yapılır Meraklısı"
web sayfası=başlık
komut = "eko"
eval $command \${$web sayfası}

chmod komutu ile çalıştırılabilir hale getirmemiz gerekiyor.

 chmod +x atama.sh 

Bir betiği çalıştırılabilir yapmak için chmod kullanma

Bu makaleden kopyaladığınız tüm komut dosyaları için bunu yapmanız gerekir. Her durumda uygun komut dosyası adını kullanın.

Komut dosyamızı çalıştırdığımızda, eval komutu webpage değişkenini kullanıyor olsa da, title değişkenindeki metni görüyoruz.

 ./atama.sh 

Başka bir değişkende saklanan adından bir değişkenin değerine erişme

Kaçan dolar işareti “ $ ” ve kaşlı ayraçlar “ {} ”, eval'in adı webpage değişkeninde saklanan değişkenin içinde tutulan değere bakmasına neden olur.

Dinamik Olarak Oluşturulmuş Değişkenleri Kullanma

Değişkenleri dinamik olarak oluşturmak için eval kullanabiliriz. Bu komut dosyası "loop.sh" olarak adlandırılır.

 #!/bin/bash

toplam=0
label="Döngü tamamlandı. Toplam:"

{1..10} içindeki n için
yapmak
  değerlendir x$n=$n
  echo "Döngü" $x$n
  ((toplam+=$x$n))
tamamlamak

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

echo $etiket $toplam

Oluşturduğumuz değişkenlerin değerlerinin toplamını tutan total adında bir değişken oluşturur. Daha sonra label adında bir dize değişkeni oluşturur. Bu basit bir metin dizisidir.

10 kez döngü yapacağız ve x10 x1 kadar 10 değişken oluşturacağız. Döngünün gövdesindeki eval ifadesi “x”i sağlar ve değişken adını oluşturmak için $n döngü sayacının değerini alır. Aynı zamanda, yeni değişkeni $n döngü sayacının değerine ayarlar.

9 Linux Bash Komut Dosyalarında Döngüler İçin Örnekler
İLGİLİ 9 Linux Bash Komut Dosyalarında Döngüler İçin Örnekler

Yeni değişkeni terminal penceresine yazdırır ve ardından total değişkeni yeni değişkenin değeriyle artırır.

Döngünün dışında, 10 yeni değişken bir kez daha, hepsi bir satırda yazdırılır. Değişkenlere, adlarının hesaplanmış veya türetilmiş bir versiyonunu kullanmadan gerçek adlarıyla da başvurabileceğimizi unutmayın.

Son olarak, total değişkenin değerini yazdırıyoruz.

 ./loop.sh 

Değişkenleri dinamik olarak oluşturmak için eval kullanma

İLGİLİ: Primer: Bash Döngüler: için, süre ve kadar

Dizilerle eval kullanma

Uzun süredir çalışan ve sizin için bazı işlemler gerçekleştiren bir komut dosyanızın olduğu bir senaryo hayal edin. Bir zaman damgasından oluşturulan bir adla bir günlük dosyasına yazar. Bazen yeni bir günlük dosyası başlatır. Script bittiğinde herhangi bir hata yoksa oluşturduğu log dosyalarını siler.

Basitçe rm *.log olmasını istemezsiniz, yalnızca oluşturduğu günlük dosyalarını silmesini istersiniz. Bu komut dosyası, bu işlevi simüle eder. Bu "clear-logs.sh".

 #!/bin/bash

-a günlük dosyalarını bildir

dosya sayısı=0 
rm_string="eko"

function create_logfile() {
  ((++dosya sayısı))
  dosyaadı=$(tarih +"%Y-%m-%d_%H-%M-%S").log
  günlük dosyaları[$filecount]=$dosyaadı
  echo $filecount "Oluşturuldu" ${logfiles[$filecount]}
}

# betiğin gövdesi. Burada bazı işlemler yapılır.
# periyodik olarak bir günlük dosyası oluşturur. bunu simüle edeceğiz
create_logfile
uyku 3
create_logfile
uyku 3
create_logfile
uyku 3
create_logfile

# kaldırılacak dosya var mı?
için ((dosya=1; dosya<=$dosya sayısı; dosya++))
yapmak
  # günlük dosyasını kaldır
  eval $rm_string ${logfiles[$file]} "silindi..."
  günlük dosyaları[$dosya]=""
tamamlamak

Komut dosyası, logfiles adlı bir dizi bildirir. Bu, komut dosyası tarafından oluşturulan günlük dosyalarının adlarını tutacaktır. filecount adında bir değişken bildirir. Bu, oluşturulan günlük dosyalarının sayısını tutacaktır.

Ayrıca rm_string adında bir dize bildirir. Gerçek dünya komut dosyasında, bu rm komutunu içerir, ancak ilkeyi tahribatsız bir şekilde gösterebilmek için echo kullanıyoruz.

create_logfile() işlevi, her bir günlük dosyasının adlandırıldığı ve açılacağı yerdir. Yalnızca dosya adını oluşturuyoruz ve dosya sisteminde oluşturulmuş gibi davranıyoruz.

İşlev, filecount değişkenini artırır. Başlangıç ​​değeri sıfırdır, bu nedenle oluşturduğumuz ilk dosya adı dizide birinci konumda saklanır. Bu bilerek yapılır, daha sonra bakınız.

Dosya adı, date komutu ve “.log” uzantısı kullanılarak oluşturulur. Ad, dizide filecount tarafından belirtilen konumda saklanır. Ad, terminal penceresine yazdırılır. Gerçek dünya komut dosyasında, gerçek dosyayı da yaratırsınız.

Linux Uyku Komutuyla Bash Komut Dosyası Nasıl Duraklatılır
İLGİLİ Linux Uyku Komutuyla Bash Komut Dosyasını Duraklatma

Komut dosyasının gövdesi, sleep komutu kullanılarak simüle edilir. İlk günlük dosyasını oluşturur, üç saniye bekler ve ardından bir başkasını oluşturur. Dosya adlarındaki zaman damgalarının farklı olması için aralıklı dört günlük dosyası oluşturur.

Son olarak, günlük dosyalarını silen bir döngü vardır. Döngü sayacı dosyası bire ayarlanır. Oluşturulan dosya sayısını tutan filecount değerine kadar ve buna kadar sayar.

filecount sayısı hala sıfıra ayarlanmışsa (çünkü hiçbir günlük dosyası oluşturulmamıştır), bir sıfırdan küçük veya sıfıra eşit olmadığı için döngü gövdesi hiçbir zaman yürütülmez. Bu nedenle filecount değişkeni bildirildiğinde sıfıra ayarlandı ve bu nedenle ilk dosya oluşturulmadan önce artırıldı.

Döngünün içinde, tahribatsız rm_string ve diziden alınan dosyanın adıyla eval kullanıyoruz. Ardından dizi öğesini boş bir dizeye ayarladık.

Komut dosyasını çalıştırdığımızda gördüğümüz şey budur.

 ./clear-logs.sh 

Adları bir dizide saklanan dosyaları silme

Her Şey Kötü Değil

Çok kötü eval değerlendirme kesinlikle kullanımlarına sahiptir. Çoğu araç gibi, dikkatsizce kullanıldığında tehlikelidir ve birden fazla şekilde.

Üzerinde çalıştığı dizelerin dahili olarak oluşturulduğundan ve insanlardan, API'lerden veya HTTPS istekleri gibi şeylerden alınmadığından emin olursanız, büyük tuzaklardan kaçınırsınız.

İLGİLİ: Linux Terminalinde Tarih ve Saat Nasıl Görüntülenir (ve Bash Komut Dosyalarında Kullanılır)