Yeni başlayanlar için bash script: ilk betik, değişkenler, koşullar, döngüler ve cron
Bash script, #!/bin/bash satırıyla başlayan, chmod +x ile çalıştırma izni alan ve ./script.sh biçiminde çalıştırılan, kabuk komutlarından oluşan düz bir metin dosyasıdır. Betiklerde değişkenler, $1 ve $2 argümanları, if koşulları, for ve while döngüleri kullanılır; düzenli zamanlama ise crontab -e ile ayarlanır.
Bash script, terminalde tek tek yazacağınız komutların yer aldığı düz bir metin dosyasıdır. Betik, #!/bin/bash shebang satırıyla başlar, chmod +x ile çalıştırma iznini alır ve ./script.sh olarak çalıştırılır. Bu rehber, yeni başlayanlar için bash script'i ilk satırdan zamanlanmış çalıştırmaya kadar anlatır: değişkenler, argümanlar, koşullar, döngüler, hata yönetimi ve cron.
Bir dakikada ilk bash script'iniz
Herhangi bir editörde dosya oluşturun, örneğin nano ile:
nano hello.sh
#!/bin/bash
# İlk betik: karşılama ve sistem hakkında biraz bilgi
echo "Merhaba, $USER!"
echo "Bugün: $(date +%Y-%m-%d)"
echo "Şu anda buradasınız: $(pwd)"
Kaydedin (Ctrl+O, Enter, Ctrl+X), çalıştırma izni verin ve çalıştırın:
$ chmod +x hello.sh
$ ./hello.sh
Merhaba, alice!
Bugün: 2026-10-12
Şu anda buradasınız: /home/alice
# ile başlayan satırlar yorumdur. $(komut), komutun çıktısını doğrudan satıra yerleştirir.
Shebang: ilk satır neden önemli
#!/bin/bash satırı, sisteme dosyayı hangi yorumlayıcıyla çalıştıracağını söyler. Bu satır olmadan betik, o an hangi kabuk bulunursa onunla çalışır. Bazı sistemlerde /bin/sh bash değil, daha sade olan dashtır ve bazı yapılar orada çalışmaz.
Sık görülen bir başka biçim #!/usr/bin/env bash'tır: bash'i PATH içinde arar; bash /bin içinde değilse kullanışlıdır.
Betik nasıl çalıştırılır ve neden ./
İki yol vardır:
./hello.sh— shebang vexizni gerekir../öneki zorunludur, çünkü geçerli dizin PATH'te yer almaz.bash hello.sh— çalıştırma izni gerekmez, yorumlayıcı açıkça belirtilmiştir.
Eğer ./ olmadan command not found, chmod +x olmadan Permission denied görüyorsanız, nedenler tam olarak bunlardır. Kendi betiklerinizi her yerden adıyla çağırmak için ~/bin veya /usr/local/bin dizinine koyun.
Değişkenler
Değişken, = işaretinin etrafında boşluk olmadan tanımlanır ve $ ile okunur:
#!/bin/bash
name="backup"
dir="/var/backups"
today=$(date +%F)
echo "Dosya: ${dir}/${name}-${today}.tar.gz"
Süslü parantezler değişken adını çevresindeki metinden ayırır. Boşluklu name = "backup" satırı hatalıdır: bash name adında bir komut çalıştırmaya çalışır.
Tırnak işaretleri önemlidir
Çift tırnak içinde değişkenler yerine konur, tek tırnak içinde konmaz. Değişkenleri neredeyse her zaman çift tırnak içine alın; aksi halde boşluk içeren bir dosya adı iki argümana bölünür.
file="rapor notu.txt"
rm $file # hata: «rapor» ve «notu.txt» adlı dosyaları silmeye çalışır
rm "$file" # doğru
echo '$HOME' # olduğu gibi $HOME yazar
echo "$HOME" # /home/alice yazar
Ortam değişkenleri
$HOME, $USER, $PATH gibi değişkenleri sistem tanımlar. Kendi değişkeninizi export ile alt süreçlere aktarabilirsiniz. Kalıcı ayarlar ~/.bashrc veya ~/.profile dosyasına yazılır.
Betik argümanları
Çalıştırırken verilen değerlere $1, $2 vb. ile erişilir.
| ead> | |
|---|---|
| Değişken | İçeriği |
$0 | betiğin adı |
$1, $2… | birinci, ikinci argüman |
$# | argüman sayısı |
"$@" | tüm argümanlar ayrı ayrı |
$? | son komutun çıkış kodu |
$$ | çalışan betiğin PID'si |
#!/bin/bash
echo "Betik $0, $# argüman aldı"
echo "Birinci: $1"
$ ./args.sh nginx 80
Betik ./args.sh, 2 argüman aldı
Birinci: nginx
Kullanıcıdan girdi almak için read komutu kullanılır: read -p "Adınızı girin: " name.
if koşulları
Her komut bir çıkış kodu döndürür: 0 başarı, diğer her değer hata demektir. if yapısı tam olarak bu kodu denetler. Karşılaştırmalar için [[ ... ]] kullanılır ve parantezlerin içindeki boşluklar zorunludur.
#!/bin/bash
if [[ $# -eq 0 ]]; then
echo "Kullanım: $0 <dizin>"
exit 1
fi
if [[ -d "$1" ]]; then
echo "Dizin $1 mevcut"
elif [[ -f "$1" ]]; then
echo "$1 bir dosya, dizin değil"
else
echo "$1 bulunamadı"
fi
| ead> | |
|---|---|
| Denetim | Anlamı |
-f file | normal dosya var |
-d dir | dizin var |
-e path | yol var |
-x file | dosya çalıştırılabilir |
-z "$var" / -n "$var" | metin boş / boş değil |
"$a" == "$b", != | metin karşılaştırması |
-eq -ne -lt -le -gt -ge | sayı karşılaştırması |
Doğrudan herhangi bir komutu da koşul olarak denetleyebilirsiniz:
if systemctl is-active --quiet nginx; then
echo "nginx çalışıyor"
else
echo "nginx durmuş"
fi
Birçok seçenek için case kullanışlıdır:
case "$1" in
start) echo "Başlatılıyor" ;;
stop) echo "Durduruluyor" ;;
*) echo "Bilinmeyen komut: $1"; exit 1 ;;
esac
for ve while döngüleri
for: bir listeyi dolaşmak
for host in web1 web2 db1; do
echo "$host kontrol ediliyor"
ping -c 1 -W 1 "$host" > /dev/null && echo " erişilebilir" || echo " erişilemiyor"
done
for file in /var/log/*.log; do
echo "$file: $(wc -l < "$file") satır"
done
for i in {1..5}; do
echo "Deneme $i"
done
while: koşul doğru olduğu sürece
Bir dosyayı satır satır okumanın klasik örneği:
while read -r user; do
echo "Kullanıcı: $user"
done < users.txt
Ve bir servisin ayağa kalkmasını beklemek:
count=0
until curl -sf http://localhost:8080/health > /dev/null; do
count=$((count + 1))
if [[ $count -ge 10 ]]; then
echo "Servis ayağa kalkmadı"
exit 1
fi
sleep 3
done
echo "Servis hazır"
Bash'te aritmetik çift parantezle yazılır: $((a + b)). Yalnızca tam sayılarla çalışır.
Fonksiyonlar
Tekrarlanan kodlar fonksiyonlara taşınır. Fonksiyon içindeki argümanlar yine $1, $2'dir ve local değişkenin dışarı sızmasını engeller.
log() {
local level="$1"; shift
echo "$(date '+%F %T') [$level] $*"
}
log INFO "Yedekleme başlıyor"
log ERROR "Diskte yer kalmadı"
Hataları yönetmek: set -euo pipefail
Varsayılan olarak bash, başarısız bir komuttan sonra da çalışmaya devam eder; yedekleme betiği hiçbir şey kopyalamadan «başarıyla» bitebilir. Bu yüzden betiklerin başına sıkı mod eklenir:
#!/bin/bash
set -euo pipefail
-e— ilk hatada dur.-u— tanımlanmamış bir değişkene başvuruyu hata say (boş birDIRilerm -rf "$DIR/"yazılmasını engeller).-o pipefail— bir borunun herhangi bir parçası başarısız olursa, tüm boru başarısız sayılır.
Hata ayıklamak için betiği bash -x script.sh ile çalıştırın: bash her komutu çalıştırmadan önce yazdırır. Çalıştırmadan önce tipik hataları bulmak için shellcheck aracı yardımcı olur.
Uygulamalı örnek: yedekleme betiği
#!/bin/bash
set -euo pipefail
SRC="${1:-/var/www}"
DST="/var/backups/site"
KEEP_DAYS=7
STAMP=$(date +%F_%H-%M)
mkdir -p "$DST"
tar -czf "$DST/site-$STAMP.tar.gz" -C "$(dirname "$SRC")" "$(basename "$SRC")"
echo "Arşiv oluşturuldu: $DST/site-$STAMP.tar.gz"
# KEEP_DAYS günden eski arşivleri sil
find "$DST" -name "site-*.tar.gz" -mtime +"$KEEP_DAYS" -delete
${1:-/var/www} ifadesi şu anlama gelir: «birinci argüman; yoksa /var/www». Betiği /usr/local/bin/backup-site.sh olarak kaydedin ve çalıştırılabilir yapın: sudo chmod +x /usr/local/bin/backup-site.sh.
Zamanlanmış çalıştırma: cron
Cron, komutları belirli zamanlarda çalıştıran servistir. Kullanıcının görevleri crontab -e ile düzenlenir, crontab -l ile listelenir; root'un görevleri için sudo crontab -e kullanılır.
Bir cron satırı beş zaman alanı ve ardından komuttan oluşur:
# dakika saat gün_ayın ay haftanın_günü komut
30 2 * * * /usr/local/bin/backup-site.sh >> /var/log/backup.log 2>&1
| ead> | |
|---|---|
| Zamanlama | Ne zaman çalışır |
*/5 * * * * | her 5 dakikada bir |
0 * * * * | her saatin başında |
30 2 * * * | her gün 02:30'da |
0 9 * * 1-5 | hafta içi 09:00'da |
0 3 1 * * | her ayın 1'inde 03:00'te |
@reboot | açılıştan sonra bir kez |
Betik elle çalışıyor, cron'da neden çalışmıyor
- Farklı ortam. Cron görevleri minimal bir
PATHile ve~/.bashrcolmadan çalıştırır. Komutların ve dosyaların tam yollarını yazın veya crontab'ın başındaPATHtanımlayın. - Farklı geçerli dizin. Görev ev dizininden başlar, betiğin bulunduğu dizinden değil. Mutlak yollar kullanın.
- % işareti. crontab'ta
%yeni satır anlamına gelir; bu yüzden görev satırındakidate +%Fifadesinin\%olarak kaçırılması gerekir. Daha kolayı, komutu betiğe koymaktır. - Çıktı kaybolur. Çıktıyı bir günlük dosyasına yönlendirin (
>> file 2>&1), yoksa hatayı göremezsiniz. Cron çalışmalarıjournalctl -u cronile görünür (RHEL türevlerinde servis adıcrond'dur).
systemd olan sistemlerde cron'a alternatif olarak systemd zamanlayıcıları vardır: çıktılarını günlüğe yazarlar ve kaçırılan çalışmaları telafi edebilirler.
Sonuç
Yeni başlayanlar için bash script, #!/bin/bash shebang satırıyla başlayan, çalıştırma iznine sahip ve komutların sırasını içeren bir dosyadır. Tırnaklı değişkenleri, if ile argüman denetimini, for ve while döngülerini ve set -euo pipefail sıkı modunu ekleyin; cron'un zamanında çalıştıracağı güvenilir bir otomasyon aracı elde edersiniz. Bash betikleri, ortam ve cron, kurs içinde uygulamalı olarak işlenmektedir.
Sık sorulan sorular
bash ile sh arasındaki fark nedir?
sh standart bir POSIX kabuğudur; bash ise dizi, çift parantez ve başka kolaylıklar içeren genişletilmiş sürümüdür. Bash yapıları içeren betiği sh ile değil, bash ile çalıştırın.
Bash betiğinin uzantısı ne olmalı?
Linux uzantıya bakmaz; yorumlayıcıyı shebang belirler. <code>.sh</code> yalnızca bir gelenektir ve dosyanın betik olduğunu insanlara gösterir.
Betiğe parolayı güvenli biçimde nasıl veririm?
Argüman olarak vermeyin, çünkü argümanlar <code>ps</code> ile diğer kullanıcılar tarafından görülebilir. 600 izinli bir dosyadaki ortam değişkenini kullanın ya da <code>read -s</code> ile ekrana yansımadan girdi alın.
Betiğin root olarak çalışıp çalışmadığını nasıl anlarım?
Kullanıcı kimliğini sıfırla karşılaştırın: <code>if [[ $EUID -ne 0 ]]; then echo "root gerekli"; exit 1; fi</code>.
SSH'den çıktıktan sonra da çalışması için betiği nasıl başlatırım?
<code>nohup ./script.sh &</code> kullanın ya da bir tmux veya screen oturumunda çalıştırın. Kalıcı çalışma için betiği bir systemd servisine dönüştürün.
Bu konu “Linux: с нуля до уверенного администрирования” kursunda uygulamalı olarak ayrıntılı işleniyor.
- Bash-скрипты: от команды в терминале до рабочего скрипта автоматизации
- Пакеты, окружение и первая автоматизация: apt, профиль и cron