Bütün Linux kullanıcıları veya sistem yöneticileri için güçlü bir araç olan Bash, tekrarlı işlemleri otomatikleştirmeyi sağlar.

Bash, Brian FoxFree tarafından 1989 yılında SH (Bourne shell) yerine “Free Software” olarak UNIX sisteminin komut satırındaki komutları işlemekten sorumlu bir yorumlayıcı olarak piyasaya sürülmüştür. İsmini Bourne Again Shell kelimelerinin ilk harflerinin kısaltmasından almaktadır.

Bash, geliştiriciler, veri bilimcileri, sistem yöneticileri, ağ mühendisleri kısacası günlük işlerinde büyük ölçüde UNIX işletim sistemine kullanan herkes tarafından kullanılır. Genel olarak Bash betikleri tekrarlı şekilde yapılması gerekli işleri otomatikleştirerek kullanıcıları için kolaylık sağlar. Günümüzde ise Bash sadece UNIX sistemlerde değil; Windows, Mac OS ve Android gibi işletim sistemlerinde de kullanılmaktadır. Bash genellikle, kullanıcıların işlemleri gerçekleştirmesine izin vermek için komutlar yazabilecekleri bir metin penceresinde çalışır.

Temelde Bash betiği, bir dizi komut içeren düz bir metin dosyasıdır. Bu komutlar, normalde komut satırına yazacağımız komutların (örneğin ls veya cp gibi) ve komut satırına yazabileceğimiz ancak genellikle yazmayacağımız komutların bir karışımıdır. Kısacası

Normal olarak komut satırında çalıştırabileceğiniz herhangi bir şey bir Bash betiği dosyasına yerleştirilebilir ve komut satırında yaptığı şeyin tam olarak aynısını yapar. Benzer şekilde, bir Bash betiği dosyasına koyabileceğiniz her şey komut satırında normal şekilde çalıştırılabilir ve Bash Betiği dosyasında yaptığı işin tam olarak aynısını yapar.

Hiçbir şeyi değiştirmenize gerek yok. Bash betiği içine komutları normalde yaptığınız gibi yazın ve komut satırında olduğu gibi sonuç alacaksınız. İşlerimizi hızlandırmak ve tekrarlarını sağlamak için bunları komut satırına yazmak yerine şimdi düz metin dosyasına giriyoruz. Bu anlamda, komut satırında bir şeyler yapmayı biliyorsanız, o zaman Bash betik dosyası oluşturma konusunda zaten bir miktar bilginiz vardır.

Bash betik dosyalarına .sh uzantısı vermek “gelenekseldir”. Bildiğiniz gibi Linux dosya uzantılarına bakmaksızın çalışan bir işletim sistemdir. Bu nedenle yazdığınız bir Bash betik dosyasının çalışması için mutlaka .sh uzantısına sahip olması gerekmez.

Bash betiği nasıl çalışır?

Nasıl çalıştığını bilmek Bash betiği yazmanız için olmazsa olmazınız değildir. Daha karmaşık Bash Betikleri yazmaya başladığınızda (Diğer betik dosyalarını çağıran ve bun dosyalardan aldığı çıkılar ile iş yapan Bash betik dosyaları gibi) nasıl çalıştığını bilmek faydalı olacaktır.

Bir program CPU ve muhtemelen diğer kaynaklar (görüntü, ses ya da herhangi bir dosya) için bir dizi talimattan oluşan, bir paket halinde düzenlenen ve sabit diskinizde depolanan ikili bir veri bloğudur. Bir program çalıştırdığımızı söylediğimizde, aslında yaptığımız şey; bu talimatları ve kaynakları sabit diskten çalışan belleğe (veya RAM’e) kopyalamaktır. Aynı zamanda bu işlemin komutlarının ve değişkenlerinin depolanması için RAM’de yer ayırıyor ve işletim sisteminin bu bu işlem sırasında süreci yürütmesi ve gözlemlemesi için birkaç “flag” oluşturuyoruz.

Kısacası her bir süreç, bir programın çalışan bir örneğidir.

Bellekte aynı anda çalışan aynı programı temsil eden birkaç işlem olabilir. Örneğin, iki terminali açabilir ve her ikisinde de cp komutunu çalıştırabiliriz. Bu durumda, sistemde hali hazırda mevcut olan iki cp işlemi olacaktır. Sistemi çalıştırmayı bitirdikten sonra onları yok eder ve artık cp programını temsil eden herhangi bir işlem kalmaz.

Terminal üzerindeyken bizi karşılayan Bash kabuğu için arkada çalışan bir Bash process’i vardır. Bash betiğini çalıştırdığımızda o süreç çalışmaz, bunun yerine onun içinde çalışan yeni bir Bash process’i başlatılır.

Nasıl çalıştırırız?

Bir terminaliniz varsa Bash betiğini çalıştırmanız epey basittir. Bash betiğini çalıştırmadan önce ilk yapmanız gereken şey çalıştırma iznine sahip olup olmadığının kontrolüdür. Güvenlik nedeniyle çalıştırma izni genellikle varsayılan olarak ayarlanmaz. Komut dosyasını çalıştırmadan önce bu izni vermeyi unutursanız, size aşağıdaki şekilde bildiren bir hata mesajı alırsınız. Bu bir sorun yaratmadığı gibi programınızın çalışmasına engel olur.

bahdem@bahdems ~ % ./topluluk.sh
bash: permission denied: ./topluluk.sh

Bu Bash betik dosyasını iki şekilde çalıştırabiliriz.

  1. Dosyaya çalışma izni vermek
bahdem@bahdems ~ % ls -al topluluk.sh 
-rw-r--r--  1 bahdem  staff  5 Feb 21 12:24 topluluk.sh
bahdem@bahdems ~ % chmod +x topluluk.sh 
bahdem@bahdems ~ % ls -al topluluk.sh  
-rwxr-xr-x  1 bahdem  staff  5 Feb 21 12:24 topluluk.sh
bahdem@bahdems ~ % ./topluluk.sh 
Sen nerdeysen orada özgürlük!
  1. Betik dosyası önüne bash komutunu yazmak
bahdem@bahdems ~ % ls -al topluluk.sh 
-rw-r--r--  1 bahdem  staff  5 Feb 21 12:50 topluluk.sh
bahdem@bahdems ~ % bash topluluk.sh 
Sen nerdeysen orada özgürlük!

Kullandığımız betik dosyası;

#!/bin/bash
# A sample Bash script

echo "Sen nerdeysen orada özgürlük!"

Betik dosyasını satır satır açıklamak gerekirse;

  • Satır 1 – Shebang olarak adlandırılan satırdır.
  • Satır 2 – Yorum satırıdır. #‘den sonraki hiçbir şey yürütülmez. Sadece açıklama içindir.
  • Satır 4 – Ekrana bir mesaj yazdıracak olan komut satırıdır. Bu komutu komut satırına kendiniz yazabilirsiniz ve tamamen aynı şekilde çıktı alırsınız.

Neden ./ kullanıyoruz?

Terminalde herhangi bir komutu (ls, cp, mkdir ..) sadece adını yazarak çalıştırdığımızı ancak betik dosyamızı çalıştırmak için ise başına ./ koyduğumuzu fark etmişsinizdir. Komut satırına bir komut yazdığımızda Bash PATH ismini verdiğimiz değişkende saklanan konum bilgisinde bu komutu arar. Terminalimizde bu PATH değerini echo komutu ile görebiliriz.

bahdem@bahdems ~ % echo $PATH
/usr/local/opt/openjdk@11/bin:/Users/bahdem/.local/share/gem/ruby/3.0.0/bin:/usr/local/opt/ruby/bin:/usr/local/opt/nmap/bin:
/Users/bahdem/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

Yukarıda da farkettiğiniz gibi birden fazla dizin aralarına “:” konularak yazılmıştır. Bu da PATH değişkenine birden fazla dizinin eşlik ettiğini göstermektedir. Bash yalnızca bu belirli dizinlere bakar ve alt dizinleri veya mevcut dizininizi dikkate almaz. Bu dizinleri sırayla inceleyecek ve bulduğu programın veya komut dosyasının ilk örneğini yürütecektir.

$PATH değişkeni bireysel bir kullanıcı değişkenidir. Bu nedenle sistemdeki her kullanıcı bunu kendisine uyacak şekilde ayarlayabilir.

Bu, birkaç farklı nedenden dolayı yapılır.

  • Bir programın birkaç farklı sürümünün kurulu olmasını sağlar. Hangisinin yürütüleceğini $PATH‘imizde nerede olduğuna bağlı olarak kontrol edebiliriz.
  • Sistemin neresinde olursanız olun kendi betik ve programlarınızı sadece isimlerini yazarak çalıştırmanızı sağlar.
  • Güvenliği artırır. Örneğin, kötü niyetli bir kullanıcı, ana dizininizdeki her şeyi gerçekten silen ls adlı bir komut dosyası oluşturabilir. Bu betiği istemeden çalıştırmak istemezsiniz. $PATH‘inizde olmadığı sürece bu olmayacak.

Bir program veya betik dosyası $PATH‘inizdeki dizinlerden birinde değilse, Bash’e onu bulmak için nereye bakacağını söyleyerek çalıştırabilirsiniz. Bunu, programın veya betik dosyasının adının önüne mutlak veya göreli bir yol ekleyerek yaparsınız. Noktanın ( . ) aslında mevcut dizininize bir referans olduğunu söyleyebiliriz. Aşağıda görüldüğü gibi iki şekilde de çalışacaktır.

bahdem@bahdems ~ % /Users/bahdem/topluluk.sh 
Sen neredeysen orada özgürlük!
bahdem@bahdems ~ % ./topluluk.sh 
Sen neredeysen orada özgürlük!

The Shebang (#!)

Betik dosyamızın ilk satırında da yer aldığı gibi #! ile başlayan satıra Shebang ismi verilir. Bu karakterleri takiben betik dosyası içindekileri çalıştıracak/yorumlayacak program/yorumlayıcının yolu bulunur. Bu satır bash betik dosyaları için Bash’e giden yol olacaktır. Başka birçok komut betik türü vardır ve her birinin kendi yorumlayıcısı vardır.

Burada biçimlendirme çok önemlidir.

  • Shebang, dosyanın ilk satırında olmalıdır. 2. satır, ilk satır boş olsa bile işe yaramaz.
  • # işaretinden önce veya ! işareti arasında boşluk olmamalıdır.
  • Yorumlayıcı yolu doğru tanımlanmalıdır. Muhtemelen komut dosyasını çeşitli konumlardan çalıştıracağınız için yorumlayıcı için göreli bir dizin yerine mutlak bir dizin kullanacaksınız.