Bash Alt Kabukları: Değişkenleri ve Dizin Değişikliklerini İzole Etme

Bash komut dosyalarında değişken ve dizin değişikliklerinin diğer komutlara sızmasını önlemek için alt kabukları nasıl kullanabilirsiniz? Değişiklik geçicidir ve ana kabuğa etki etmez.

L
Linuxize
5 görüntülenme
Bash Alt Kabukları: Değişkenleri ve Dizin Değişikliklerini İzole Etme

Alt Kabuk Nedir ve Neden Kullanılır?

Bash komut dosyalarında cd, değişken atamaları veya geçici ortam değerleri gibi değişiklikler, komut dosyasının kalan kısmına kolayca sızabilir. Bu durum, beklenmeyen davranışlara yol açabilir. İşte burada alt kabuklar (subshells) devreye girer. Alt kabuk, komutları bağımsız bir kabuk ortamında çalıştırır ve bu kabuk kapandığında yapılan tüm değişiklikler otomatik olarak kaybolur.

Alt kabuklar sayesinde aşağıdaki durumları kontrol altına alabilirsiniz:

  • Değişkenlerin geçici olarak ayarlanması ve ardından ana kabuğun etkilenmemesi
  • Dizin değişikliklerinin (cd) sadece geçici olması ve ana dizine dönülmesi
  • Borulama (pipeline) işlemlerinde sayaç değerlerinin kaybolmasının önlenmesi
  • Geçici ortam değişkenlerinin (export) ana kabuğa etki etmemesi

Örnek Senaryo: Bir komut dosyasında geçici olarak LANG=C ayarlamanız gerektiğinde, bu ayar diğer komutlara etki etmemelidir. Alt kabuk kullanarak bu değişikliği izole edebilirsiniz.

Alt Kabukların Temel Sözdizimi

Alt kabuk oluşturmak için komutları parantezler (()) içine alın. Parantezler arasında birden fazla komut yer alabilir ve her komut noktalı virgül (;) ile ayrılır.

Tek Satırlık Alt Kabuk

(komut1; komut2; komut3)

Çok Satırlı Alt Kabuk (Önerilen Stil)

(
    komut1
    komut2
    komut3
)

Önemli Not: Alt kabuk, ana kabuğun bir kopyasıdır. Komutlar tamamlandığında, alt kabuk kapanır ve yapılan tüm değişiklikler kaybolur. Ana kabuk, alt kabuğun bitmesini bekler (arka planda çalıştırılmadığı sürece).

Alt Kabuk ile Dizin Değişikliklerini İzole Etme

Dizin değiştirmek için cd komutunu kullandığınızda, bu değişiklik ana kabuğa da yansıyabilir. Alt kabuk kullanarak bu sorunu çözebilirsiniz.

Örnek: Dizin Değişikliğinin İzole Edilmesi

# Ana kabuktaki mevcut dizin
pwd
# Çıktı: /home/kullanici

# Alt kabuk içinde dizin değiştirme
(/tmp && ls)

# Ana kabuktaki dizin hala aynı
pwd
# Çıktı: /home/kullanici

Karşılaştırma: Süslü Parantezler ({})

Eğer dizin değişikliğinin ana kabuğa etki etmesini istiyorsanız, süslü parantezler ({}) kullanın. Süslü parantezler, komutları ana kabukta çalıştırır.

{ cd /tmp && ls; }

# Ana kabuktaki dizin değişmiştir
pwd
# Çıktı: /tmp

İpucu: Süslü parantezler kullanırken son komuttan sonra noktalı virgül (;) veya yeni satır kullanın. Aksi takdirde, komut çalışmaz.

Değişken İzolasyonu: Değişkenlerin Geçici Olarak Ayarlanması

Alt kabuklar, değişkenlerin geçici olarak ayarlanması için idealdir. Alt kabuk içinde yapılan değişken değişiklikleri, ana kabuğu etkilemez.

Örnek: Değişkenin Geçici Olarak Değiştirilmesi

# Ana kabukta bir değişken tanımlama
x=10

# Alt kabuk içinde değişkeni değiştirme
(x=99; echo "Alt kabuk içinde x: $x")

# Ana kabukta değişken hala ilk değeriyle
echo "Ana kabukta x: $x"
# Çıktı: Ana kabukta x: 10

Uygulama Örneği: Geçici Ortam Değişkenleri

Bir komutun geçici olarak farklı bir dil ayarında çalıştırılması gerektiğinde, alt kabuk kullanabilirsiniz.

# Geçici olarak C dil ayarını kullanma
(
    export LANG=C
    export LC_ALL=C
    sort -k2 data.txt
)

# Ana kabukta dil ayarları değişmemiştir
echo $LANG
# Çıktı: tr_TR.UTF-8 (veya varsayılan ayar)

Komut Çıkışını Yakalama (Command Substitution)

$(...) sözdizimi, bir komutun çıktısını yakalamak için kullanılır. Bu komut, bir alt kabukta çalıştırılır ve çıktısı yakalanır. Değişken veya dizin değişiklikleri yakalanan çıktıya etki etmez.

Örnek: Komut Çıktısını Bir Değişkene Atama

# Geçici dizine geçip pwd komutunun çıktısını yakalama
current_tmp=$(cd /tmp && pwd)

# Ana kabukta dizin değişmemiştir
pwd
# Çıktı: /home/kullanici

# Yakalanan çıktıyı kullanma
echo "Geçici dizin: $current_tmp"
# Çıktı: Geçici dizin: /tmp

Önemli Not: Komut substitution ($(...)) ve `` işaretleri, alt kabuk benzeri bir ortamda çalışır. Bu nedenle, dizin değişiklikleri ana kabuğa yansımayacaktır.

Alt Kabukların Çıkış Kodları

Bir alt kabuğun çıkış kodu, içinde çalışan son komutun çıkış kodudur. Bu özellik, if koşullarında kullanılabilir.

Örnek: Alt Kabuğun Çıkış Kodunu Kontrol Etme

if (cd /nonexistent 2>/dev/null); then
    echo "Dizin mevcut"
else
    echo "Dizin mevcut değil"
fi
# Çıktı: Dizin mevcut değil

Bu yöntem, dizin değişikliğinin ana kabuğa etki etmesini engellerken, cd komutunun başarısını kontrol etmenizi sağlar.

Alt Kabukları Arka Planda Çalıştırma

Alt kabukları & operatörüyle birlikte kullanarak komutları arka planda çalıştırabilirsiniz. Bu, ana kabuğun hemen devam etmesini sağlar.

Örnek: Komutları Arka Planda Çalıştırma

# 5 saniye uyuma ve ardından mesaj yazdırma
(
    sleep 5
    echo "Arka plan görevi tamamlandı"
) &

# Ana kabuk hemen devam eder
echo "Ana kabuk devam ediyor"
# Çıktı: Ana kabuk devam ediyor
# 5 saniye sonra: Arka plan görevi tamamlandı

Not: Parantezler olmadan & kullanırsanız, sadece son komut arka planda çalışır. Tüm blokun arka planda çalışmasını istiyorsanız, parantezler kullanın.

Borulama (Pipeline) ve Alt Kabuklar

Bash, borulama işlemlerinde her komutu ayrı bir alt kabukta çalıştırır. Bu durum, özellikle borunun sağ tarafındaki komutlar değişkenleri değiştirdiğinde önem kazanır.

Sorun: Borulama ile Değişken Kaybı

Aşağıdaki örnekte, count değişkeni borulama nedeniyle kaybolacaktır.

count=0
printf '%s\n' alpha beta gamma | while read -r line; do
    count=$((count + 1))
done

echo "Satır sayısı: $count"
# Çıktı: Satır sayısı: 0

Nedeni: while döngüsü, borulama nedeniyle ayrı bir alt kabukta çalışır. Döngü tamamlandığında, count değişkeni kaybolur.

Çözüm: Process Substitution veya Girdi Yönlendirme

Borulama yerine process substitution (<(komut)) veya girdi yönlendirme (< dosya) kullanın.

Process Substitution Kullanımı

count=0
while read -r line; do
    count=$((count + 1))
done < <(printf '%s\n' alpha beta gamma)

echo "Satır sayısı: $count"
# Çıktı: Satır sayısı: 3

Girdi Yönlendirme Kullanımı

count=0
while read -r line; do
    count=$((count + 1))
done < /etc/passwd

echo "Satır sayısı: $count"
# Çıktı: Satır sayısı: (dosyadaki satır sayısı)

Not: lastpipe seçeneği, bazı Bash sürümlerinde borunun son komutunu ana kabukta çalıştırabilir. Ancak, bu seçenek taşınabilir değildir ve varsayılan olarak kapalıdır. Bu nedenle, process substitution veya girdi yönlendirme tercih edilmelidir.

Alt Kabuklar vs. source Komutu

source komutu, bir dosyayı ana kabukta çalıştırır. Bu, alt kabukların aksine, yapılan tüm değişikliklerin ana kabukta kalıcı olmasını sağlar.

Örnek: source Kullanımı

# script.sh dosyası içinde: x=10
echo "script.sh çalıştırılmadan önce x: $x"
source script.sh
echo "script.sh çalıştırıldıktan sonra x: $x"
# Çıktı:
# script.sh çalıştırılmadan önce x:
# script.sh çalıştırıldıktan sonra x: 10

Karşılaştırma:

  • Alt Kabuk: Geçici değişiklikler, ana kabuğa etki etmez.
  • source: Değişiklikler kalıcıdır ve ana kabuğu etkiler.

Sık Karşılaşılan Sorunlar ve Çözümleri

1. Borulama ile Değişken Kaybı

Sorun: Bir borulama işleminde (command | while read ...) değişkenler kayboluyor.

Çözüm: Process substitution (while ... done < <(command)) veya girdi yönlendirme kullanın.

2. cd Komutunun Dizin Değiştirmediği Görülmesi

Sorun: Parantezler içinde cd komutu çalıştırıldığında dizin değişmiyor.

Çözüm: Süslü parantezler ({ cd /path && komut; }) kullanın. Bu, komutları ana kabukta çalıştırır.

3. lastpipe Seçeneğinin Çalışmaması

Sorun: lastpipe seçeneği çalışmıyor.

Çözüm: Bu seçenek, eski Bash sürümlerinde (örn. macOS'un varsayılan Bash 3.2) desteklenmez. Taşınabilir komut dosyaları için process substitution veya girdi yönlendirme kullanın.

Pratik Kullanım Örnekleri

Örnek 1: Geçici Dizin Değişikliği ile Dosya İşlemleri

# Belirli bir dizinde dosya işlemleri yapıp ardından ana dizine dönme
(
    cd /var/log
    ls -l | grep "\.log$"
)

# Ana dizin hala aynı
echo "Mevcut dizin: $(pwd)"

Örnek 2: Geçici Ortam Değişkenleri ile Komut Çalıştırma

# Geçici olarak farklı bir dizinde çalıştırma
(
    export TMPDIR=/custom/tmp
    python3 script.py
)

# Ana ortam değişmemiştir
echo "TMPDIR: $TMPDIR"
# Çıktı: TMPDIR: /tmp (veya varsayılan değer)

Örnek 3: Borulama ile Değişken Kaybını Önleme

# Dosyadaki satır sayısını doğru şekilde sayma
count=0
while IFS= read -r line; do
    count=$((count + 1))
done < /etc/passwd

echo "Toplam satır sayısı: $count"
# Çıktı: Toplam satır sayısı: (dosyadaki satır sayısı)

Sonuç

Alt kabuklar, Bash komut dosyalarında geçici değişiklikler yapmak için güçlü bir araçtır. Değişkenlerin, dizinlerin ve ortam ayarlarının ana kabuğa sızmasını önler. İşte temel kurallar:

  • Geçici değişiklikler için: Parantezler (()) kullanın.
  • Kalıcı değişiklikler için: Süslü parantezler ({}) veya source komutunu kullanın.
  • Borulama ile değişken kaybını önlemek için: Process substitution (<(komut)) veya girdi yönlendirme kullanın.
  • Çıktı yakalamak için: $(komut) kullanın.

Alt kabukları doğru şekilde kullanarak, komut dosyalarınızı daha güvenilir ve tahmin edilebilir hale getirebilirsiniz.

Kaynak

Linuxize