Linux’ta bir şeyleri yapılandırırken en çok başvurduğumuz ama derinlemesine anlamadan kullandığımız komutların başında export gelir. “PATH’e bir şeyler ekle, export et, tamam” mantığıyla geçiştirilen bu komut, aslında shell’in çalışma mantığını doğrudan etkileyen kritik bir yapı taşıdır. Bu yazıda export komutunu sıfırdan ele alıyor, ortam değişkenlerinin nasıl çalıştığını anlıyor ve gerçek dünya senaryolarıyla pekiştiriyoruz.
Ortam Değişkeni Nedir, Shell Değişkeninden Farkı Ne?
Bash’te iki tür değişken vardır: shell değişkenleri ve ortam değişkenleri (environment variables).
Shell değişkeni tanımladığınızda, bu değişken sadece mevcut shell oturumunda yaşar. Alt süreçlere, yani çalıştırdığınız programlara veya script’lere geçmez.
# Shell değişkeni tanımlama
PROJE_ADI="webserver"
echo $PROJE_ADI # Çıktı: webserver
# Alt process bu değişkeni göremez
bash -c 'echo $PROJE_ADI' # Çıktı: (boş)
export komutu devreye girdiğinde ise değişken ortam değişkenine dönüşür ve alt süreçler tarafından miras alınır:
export PROJE_ADI="webserver"
# Artık alt process görebilir
bash -c 'echo $PROJE_ADI' # Çıktı: webserver
İşte temel fark bu. Ortam değişkenleri, süreçler arası iletişimin en ilkel ama en etkili yollarından biridir. Bir program çalıştırdığınızda, o programın ortam tablosuna mevcut tüm export edilmiş değişkenleriniz kopyalanır.
export Komutunun Kullanım Biçimleri
export komutunun birkaç farklı kullanım şekli vardır.
Doğrudan tanımlama ve export etme:
export DEGISKEN="deger"
Önce tanımlayıp sonra export etme:
DEGISKEN="deger"
export DEGISKEN
Birden fazla değişkeni aynı anda export etme:
export DB_HOST="localhost" DB_PORT="5432" DB_NAME="mydb"
Mevcut ortam değişkenlerini listeleme:
export -p
# veya kısaca
env
printenv
export Parametreleri
-p: Mevcut shell’deki tüm export edilmiş değişkenleri declare -x formatında listeler. Script içinde ortam dump’ı almak için kullanışlıdır.
-n: Bir değişkenin export özelliğini kaldırır, değeri silmez. Değişken shell değişkeni olarak kalır.
-f: Değişken değil, fonksiyon export eder. Alt shell’lerde fonksiyonun kullanılabilmesini sağlar.
# -n kullanımı: export özelliğini kaldırma
export TEST="merhaba"
export -n TEST
bash -c 'echo $TEST' # Çıktı: (boş), değişken artık alt sürece geçmiyor
echo $TEST # Çıktı: merhaba, yerel olarak hala var
# -f kullanımı: fonksiyon export etme
selamla() {
echo "Merhaba, $1!"
}
export -f selamla
bash -c 'selamla Ahmet' # Çıktı: Merhaba, Ahmet!
PATH Değişkeni ve Yaygın Kullanım Senaryoları
PATH, muhtemelen en sık manipüle ettiğiniz ortam değişkenidir. Bash bir komut çalıştırdığınızda, bu değişkende yer alan dizinleri soldan sağa doğru tarar.
# Mevcut PATH'i görme
echo $PATH
# Örnek çıktı: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# PATH'e dizin ekleme (başa ekleme - öncelikli)
export PATH="/opt/myapp/bin:$PATH"
# PATH'e dizin ekleme (sona ekleme - düşük öncelikli)
export PATH="$PATH:/opt/myapp/bin"
Önemli not: $PATH kısmını unutursanız mevcut PATH’i silersiniz ve sistemdeki hiçbir komut çalışmaz. Bu durumda tam yol kullanmanız gerekir:
# PATH'i yanlışlıkla sildiniz
export PATH="/opt/myapp/bin" # $PATH olmadan!
# Artık ls, cd gibi komutlar çalışmaz
# Kurtarma:
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Gerçek Dünya Senaryosu: Java Kurulumu Sonrası PATH Ayarı
Bir Java uygulaması sunucusu kuruyorsunuz ve JAVA_HOME ile PATH’i kalıcı olarak ayarlamanız gerekiyor:
# /etc/profile.d/java.sh dosyasına ekliyoruz
sudo nano /etc/profile.d/java.sh
# İçerik:
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
export PATH="$JAVA_HOME/bin:$PATH"
export CLASSPATH=".:$JAVA_HOME/lib"
Bu dosyayı /etc/profile.d/ altına koymanın avantajı, sistem genelinde tüm kullanıcılar için geçerli olması ve sistematik bir yapı oluşturmasıdır.
Kalıcı ve Geçici Ortam Değişkenleri
Terminal’de doğrudan çalıştırdığınız export komutları sadece o oturum için geçerlidir. Kabuğu kapattığınızda uçup giderler. Kalıcı hale getirmek için yapılandırma dosyalarına yazmanız gerekir.
Kullanıcı Bazlı Kalıcı Değişkenler
# ~/.bashrc - interaktif shell'ler için (her terminal açılışında çalışır)
echo 'export EDITOR="vim"' >> ~/.bashrc
echo 'export HISTSIZE=10000' >> ~/.bashrc
# ~/.bash_profile veya ~/.profile - login shell için (SSH girişlerinde çalışır)
echo 'export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"' >> ~/.bash_profile
# Değişiklikleri hemen aktif etme
source ~/.bashrc
# veya
. ~/.bashrc
Sistem Geneli Kalıcı Değişkenler
# /etc/environment - tüm kullanıcılar için, shell bağımsız
# Bu dosyada export komutu KULLANILMAZ, sadece KEY=VALUE formatı geçerli
sudo nano /etc/environment
# İçerik örneği:
# LANG="tr_TR.UTF-8"
# TZ="Europe/Istanbul"
# /etc/profile - login shell'ler için sistem geneli
sudo nano /etc/profile
# /etc/profile.d/ altında uygulama bazlı dosyalar (tavsiye edilen yöntem)
sudo nano /etc/profile.d/custom_env.sh
# İçerik:
export CORP_PROXY="http://proxy.sirket.local:8080"
export NO_PROXY="localhost,127.0.0.1,.sirket.local"
Uygulama Konfigürasyonu İçin Ortam Değişkenleri
Modern uygulamalar, özellikle 12-factor app prensibine uyanlar, konfigürasyonlarını ortam değişkenlerinden okur. Bu yaklaşımın en büyük avantajı hassas bilgilerin kod içine gömülmemesidir.
Gerçek Dünya Senaryosu: Django Uygulaması Konfigürasyonu
# Uygulama başlatma script'i: /opt/myapp/start.sh
#!/bin/bash
export DJANGO_SETTINGS_MODULE="myapp.settings.production"
export DATABASE_URL="postgresql://dbuser:gizlisifre@localhost:5432/mydb"
export SECRET_KEY="uzun-ve-rastgele-bir-anahtar-buraya"
export ALLOWED_HOSTS="myapp.example.com"
export DEBUG="False"
export REDIS_URL="redis://localhost:6379/0"
cd /opt/myapp
exec gunicorn myapp.wsgi:application --bind 0.0.0.0:8000
Bu script’i doğrudan dosyaya yazmak yerine, hassas bilgileri ayrı bir dosyada tutmak daha güvenlidir:
# /etc/myapp/env.conf (izinler: 600, sahip: myapp kullanıcısı)
# Bu dosyayı asla git'e eklemeyin!
export DATABASE_URL="postgresql://dbuser:gizlisifre@localhost:5432/mydb"
export SECRET_KEY="uzun-ve-rastgele-bir-anahtar-buraya"
# Start script'inde bu dosyayı source ediyoruz
# /opt/myapp/start.sh
#!/bin/bash
source /etc/myapp/env.conf
export DJANGO_SETTINGS_MODULE="myapp.settings.production"
exec gunicorn myapp.wsgi:application --bind 0.0.0.0:8000
Proxy Ayarları: Kurumsal Ortamların Kurtarıcısı
Kurumsal ağlarda çalışıyorsanız proxy ayarları hayatınızın bir parçasıdır. apt, curl, wget, git gibi araçların büyük çoğunluğu şu değişkenlere bakar:
# Proxy ayarları
export http_proxy="http://proxy.sirket.local:8080"
export https_proxy="http://proxy.sirket.local:8080"
export ftp_proxy="http://proxy.sirket.local:8080"
export no_proxy="localhost,127.0.0.1,10.0.0.0/8,.sirket.local"
# Büyük harfli versiyonlar da bazı uygulamalar tarafından kullanılır
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export NO_PROXY="$no_proxy"
Bu ayarları /etc/profile.d/proxy.sh dosyasına koyarak sistem genelinde aktif hale getirebilirsiniz.
Ortam Değişkenlerini Debug Etme
Bir şeyler çalışmıyorsa ortam değişkenlerini incelemek ilk adım olmalıdır.
# Tüm ortam değişkenlerini listele
env
printenv
# Belirli bir değişkeni sorgula
printenv PATH
echo $PATH
printenv JAVA_HOME
# Bir komutun hangi ortamla çalıştığını görme
# strace ile de bakılabilir ama env ile daha pratik:
env -i PATH=/usr/bin:/bin HOME=/tmp /bin/bash --norc
# Bir process'in mevcut ortam değişkenlerini görme (PID ile)
cat /proc/12345/environ | tr '' 'n'
# Belirli değişkenler set mi kontrol etme
if [ -z "${DATABASE_URL+x}" ]; then
echo "DATABASE_URL tanımlanmamış!"
exit 1
fi
Gerçek Dünya Senaryosu: Script’lerde Değişken Kontrolü
Production ortamında çalışan script’lerde eksik değişkenleri erken yakalamak kritiktir:
#!/bin/bash
# Zorunlu değişkenleri kontrol eden fonksiyon
zorunlu_degisken_kontrol() {
local eksik=0
for degisken in "$@"; do
if [ -z "${!degisken}" ]; then
echo "HATA: $degisken ortam değişkeni tanımlanmamış!" >&2
eksik=1
fi
done
return $eksik
}
# Kullanım
zorunlu_degisken_kontrol DATABASE_URL SECRET_KEY REDIS_URL || exit 1
echo "Tüm değişkenler mevcut, uygulama başlatılıyor..."
Tek Seferlik Ortam Değişkeni Verme
Bir komutu geçici olarak farklı bir ortam değişkeniyle çalıştırmak istediğinizde export kullanmak zorunda değilsiniz. Komutun önüne KEY=VALUE formatında yazabilirsiniz:
# Sadece bu komut için geçerli
DEBUG=true ./uygulama.sh
# Birden fazla değişken
NODE_ENV=production PORT=3000 node server.js
# env komutuyla daha açık sözdizimi
env NODE_ENV=production PORT=3000 node server.js
# Mevcut ortamı temizleyerek çalıştırma (izole test için)
env -i HOME=/tmp PATH=/usr/bin:/bin node server.js
Bu yöntem özellikle test senaryolarında ve Makefile’larda çok kullanışlıdır.
Fonksiyon Export Etme
export -f ile fonksiyonları alt shell’lere aktarabilirsiniz. Bu özellik özellikle paralel çalışan script’lerde işe yarar:
#!/bin/bash
# Yardımcı fonksiyon
log_yaz() {
local seviye=$1
local mesaj=$2
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$seviye] $mesaj"
}
# Fonksiyonu export et
export -f log_yaz
# xargs veya parallel ile alt process'lerde kullanım
echo "sunucu1 sunucu2 sunucu3" | xargs -P3 -n1 bash -c '
log_yaz "INFO" "$1 kontrol ediliyor"
ping -c1 "$1" > /dev/null 2>&1 && log_yaz "OK" "$1 erişilebilir" || log_yaz "HATA" "$1 erişilemiyor"
' _
Systemd Servislerinde Ortam Değişkenleri
Servis yönetirken export doğrudan işe yaramaz çünkü systemd kendi ortam yönetim mekanizmasına sahiptir:
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
# Doğrudan tanımlama
Environment="NODE_ENV=production"
Environment="PORT=3000"
# Dosyadan okuma (tavsiye edilen yöntem)
EnvironmentFile=/etc/myapp/env.conf
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=always
[Install]
WantedBy=multi-user.target
EnvironmentFile kullandığınızda dosya formatı /etc/environment gibidir, yani KEY=VALUE formatında ve export anahtar kelimesi olmadan yazılır. Bu ince farka dikkat edin.
Sık Yapılan Hatalar
Boşluk bırakmak: Değişken tanımlamada = işaretinin etrafında boşluk bırakmak syntax hatasıdır.
# YANLIŞ
export DEGISKEN = "deger"
# DOĞRU
export DEGISKEN="deger"
Değerlerde tırnak kullanımını unutmak: Boşluk içeren değerleri tırnaksız bırakmak sorun yaratır.
# Sorunlu
export ACIKLAMA=merhaba dunya # Bash bunu iki ayrı argüman olarak görür
# Doğru
export ACIKLAMA="merhaba dunya"
Döngüsel referans:
# Bu istediğinizi yapmaz, PATH'i yalnızca /yeni/dizin yapar
export PATH="/yeni/dizin"
# Doğrusu
export PATH="/yeni/dizin:$PATH"
source ve exec farkını karıştırmak: Bir script’i normal çalıştırdığınızda alt shell oluşur ve o shell’de export edilen değişkenler ana shell’e geri dönmez:
# degisken_sec.sh dosyası:
export SECILEN_ENV="production"
# YANLIŞ kullanım - değişken ana shell'e geçmez
./degisken_sec.sh
echo $SECILEN_ENV # Boş!
# DOĞRU kullanım - script mevcut shell'de çalışır
source ./degisken_sec.sh
echo $SECILEN_ENV # production
Güvenlik Notları
Ortam değişkenleri konusunda güvenliği es geçmemek gerekir:
- Şifreler ve API anahtarları gibi hassas bilgileri history’de görünmemesi için doğrudan terminalden değil, dosyadan source ederek yükleyin.
~/.bashrciçine koyduğunuz değişkenlerps auxeile başkası tarafından görülebilir; root process olarak çalışan uygulamalarda bu özellikle kritiktir.- Systemd servislerinde
EnvironmentFilekullanın ve dosya izinlerini600yapıp sahipliğini servis kullanıcısına verin. - Docker ortamlarında
ENVdirektifi ile set edilen değişkenler image içinde kalır; sırları bu şekilde image’a gömmekten kaçının.
Sonuç
export komutu basit görünse de Linux sistem yönetiminin temel yapı taşlarından biridir. Shell değişkeni ile ortam değişkeni arasındaki farkı kavradığınızda, uygulamaların birbirinden nasıl bilgi alıp verdiğini, script’lerin neden bazen beklediğiniz gibi davranmadığını ve servis konfigürasyonlarının nasıl çalıştığını çok daha net görürsünüz.
Kalıcılık için doğru dosyayı seçmek, yani kullanıcı mı sistem mi, interaktif mi login shell mi, bunları ayırt etmek başlangıçta kafa karıştırıcı olabilir. Ama kural basit: sadece kendiniz için geçerliyse ~/.bashrc, tüm kullanıcılar için geçerliyse /etc/profile.d/ altına bir dosya, uygulama servisleriyse EnvironmentFile.
Gerçek ortamlarda en çok işinize yarayacak alışkanlık şu olacak: her yeni uygulamayı veya servisi konfigüre ederken ortam değişkenlerini ayrı bir dosyaya yazın, bu dosyanın izinlerini kısıtlayın ve asla version control’e eklemeyin. Bu tek alışkanlık, ileride yaşanacak pek çok baş ağrısını önler.