DEV Community

Cover image for Shell scriptleri ile SQLite.
Son Penguen
Son Penguen

Posted on

Shell scriptleri ile SQLite.

Nedir? Neden? Nasıl?

Merhaba değerli arkadaşlar,

bu yazıda sizlerle birlikte posix uyumlu bir shell kullanarak basit SQLite işlemleri gerçekleştireceğiz. Malumunuz SQLite diğer SQL sağlayıcılarına kıyasla çok daha minimal bir yapıya sahiptir; ne bir daemon, ne bir sunucu, ne de karmaşık bir veri formatı barındırır. Tek başına çalışan bir binary olarak gelir ve aldığı parametrelerle veritabanını doğrudan ikili (binary) bir dosyaya yazar. Bunları örneklerle birlikte göreceğiz.

İşte tam da bu yüzden, özellikle minimal programlar yazarken SQLite’a ihtiyaç duymamız gayet olası.

Peki nerelerde işimize yarar?

Basit migrasyon işlemleri, varsayılan değer atamaları (defaulting), CI/CD süreçleri ya da arka planda otomasyon gerektiren ama göz önünde olmayan işlerde vakit ve efor kazanmak istediğimiz her yerde SQLite tercih edilebilir.

Ayrıca isterseniz, burada yapacağımız işlemleri sadece dash değil; tercihinize göre bash, fish, hatta powershell gibi farklı kabuklarla da gerçekleştirebilirsiniz.

Bugün, bu işin en sade ve genel kabul görmüş yöntemine beraber bakacağız.

Kurulum.

SQLite görece kolay bir kuruluma sahiptir, çalıştırılabilir ikili dosyayı path'e göndermek yeterli. Ben bu işlemleri Linux Mint dağıtımında yapacağım için Ubuntu kurulumunu yaptım 👇.

Debian / Ubuntu.

sudo apt update
sudo apt install -y sqlite3
Enter fullscreen mode Exit fullscreen mode

Arch Linux

sudo pacman -Sy sqlite
Enter fullscreen mode Exit fullscreen mode

Fedora

sudo dnf install sqlite
Enter fullscreen mode Exit fullscreen mode

Windows (winget ile)

winget install --id=SQLite.sqlite --source=winget
Enter fullscreen mode Exit fullscreen mode

Ilk Veritabanı.

artık SQLite kuruldu ve pathe gönderildi sqlite3 --version yazdığımda 3.37.2 2022-01-06 .... gibi bir çıktı alıyorum.

Şimdi boş bir veritabanı dosyası oluşturalım, bunun için;
> sqlite3 mydb.db " " ; echo $?
< 0

yazdığımızda 0 çıktısını aldıysak ve mydb.db dosyasını çalıştırma dizininde görebiliyorsak sorun yok demektir, file komutu ile

dosyayı kontrol edelim;
> file mydb.db
< mydb.db: empty

boş bir dosya oluşturmuş olduk şimdi headerı da ekleyelim.
> sqlite3 mydb.db "VACUUM;" ; echo $?
< 0

tekrardan file ile kontrol edelim;
> file mydb.db
< mydb.db: SQLite 3.x database, last written using SQLite version 30....

şeklinde devam eden bir çıktı var ise temel olarak yapmamız gereken işlemleri öğrendik demektir, sqlite komutunun ilk parametresi veritabanı dosyasıdır ikinci parametresi ise SQL kodudur, sqlite programının diğer SQL sağlayıcılarına göre daha operasyonel ifadesi ve daha az veri tipi vardır bu yüzden kafamız rahat. Artık script yazma kısmına geçebiliriz.

Kullanıcı tablosu.

Artık ilk scriptimizi yazalım, örnek senaryo üzerinden gidelim, kullanıcı tablomuz olsun kullanıcı adı, mail ve parola yer alsın, ön tanımlı kullanıcılarımız olsun. Öncelikle bize gerekli olacak fonksiyonları oluşturalım.

read_file() {
  if [ ! -f "${1}" ] ; then 
    echo "file \"${1}\" not found."
    return 1
  fi

  while IFS= read -r line ; do
    echo "$line"
  done < "${1}"
}

sqlite_comm() {
  if [ "${#}" -lt 2 ] ; then
    echo "sqlite_comm: required 2 parameters which is file and sql context, usage: sqlite_comm <file> <sql>"
    return 1
  fi

  if ! command -v sqlite3 > /dev/null ; then
    echo "sqlite not found in your path, please install or link it as sqlite3"
    return 1
  fi

  sqlite3 "${1}" "${2}"
}
Enter fullscreen mode Exit fullscreen mode

Basit bir sql çalıştırma kodumuz var dosyayı da sabit yapacağız şimdi.

DATABASE="${1:-mydb.db}"

sqlite_wrapper() {
  _default_comm="VACUUM;"
  sqlite_comm "${DATABASE}" "${1:-$_default_comm}"
}
Enter fullscreen mode Exit fullscreen mode

Artık tabloları oluşturabiliriz, bunu yapmanın farklı yolları var elbette lakin biz raw sql şeklinde yazılan dosyaları arayacağız ve onları sqlite_wrapper fonksiyonumuz ile birlikte çalıştıracağız, bunun için schemes diye bir dizin ekliyoruz.

mkdir -p schemes

Artık proje yapımız şu şekilde:

.
├── sqlite.sh
├── scheme/
└── mydb.db
Enter fullscreen mode Exit fullscreen mode

Şimdi kullanıcı tablomuzu scheme dizininin altına oluşturalım ben user.sql adında bir dosya oluşturacağım.

CREATE TABLE IF NOT EXISTS user (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE,
  password TEXT NOT NULL,
  created_at TEXT DEFAULT CURRENT_TIMESTAMP
);
Enter fullscreen mode Exit fullscreen mode

Harika, artık .sql dosyalarımızı alıp çalıştıralım, burada unutmamamız gereken bir husus var sql kodunu type-safe yazmamız gerekli yoksa sqlite bize kızabilir, kızmazsa bu sefer projede sorunlar ortaya çıkabilir.

for s in "scheme/"*".sql" ; do
  if [ -f "${s}" ] ; then
    printf "${s##*/}...["
    sqlite_wrapper "$(read_file ${s})"
    echo "done]"
  fi
done
Enter fullscreen mode Exit fullscreen mode

Mükemmel, hadi ufak bir deneme yapalım bakalım nasıl gidiyoruz;

> ls
< mydb.db  scheme  sqlite.sh

> sh sqlite.sh
< user.sql...[done]

# Elle kontrol edelim
> sqlite3 "mydb.db" ".tables"
< user
Enter fullscreen mode Exit fullscreen mode

Gibi bir çıktı alıyorsanız doğru yoldasınız demektir, artık defaulting yapabiliriz bunu shell scriptleri ile sağlayacağız, scripts diye bir dizin oluşturalım.

mkdir -p scripts, artık proje dizin yapımız şu şekilde gözükecek:

.
├── mydb.db
├── scheme
│   └── user.sql
├── scripts
└── sqlite.sh
Enter fullscreen mode Exit fullscreen mode

Şimdi ise ön tanımlı kullanıcılar oluşturmak için dosyalarımızı ayarlayalım, ben admin ve ahmet isimli iki adet kullanıcı ekleyeceğim bu yüzden scripts dizini içerisine ahmet_user.sh ve admin_user.sh ekliyorum, burada basit bir dosya formatı kullanmamız gerekli oldu her seferinde tüm scriptleri çalıştırmaktan ziyade gerekli olanları çalıştıracağız, _user.sh şeklinde bir yapı takip edelim, diğerlerinde daha farklı formatlar uydurabiliriz, şimdi defaulting için fonksiyonumuzu ekleyelim:

default_user() {
  if [ "${#}" -lt 3 ] ; then
    echo "default_user: need to specify 3 parameters: <username> <mail> <password>."
    return 1
  fi

  printf "%s...[" "${1}"
  if ! sqlite_comm "$DATABASE" "SELECT 1 FROM user WHERE username = '${1}' LIMIT 1;" | grep -q 1 > /dev/null ; then
    sqlite_wrapper "INSERT INTO user (username, email, password) VALUES ('${1}', '${2}', '${3}');"
    echo "added]"
  else
    echo "exists]"
  fi
}

for d in "scripts/"*"_user.sh" ; do
  ( . "./${d}" )
done
Enter fullscreen mode Exit fullscreen mode

Artık ön tanımlı kullanıcılarımızı ekleyebiliriz;

scripts/admin_user.sh dosyamızın içeriği şu şekilde:

# File: scripts/admin_user.sh
default_user "admin" "admin@mail.domain" "1234"
Enter fullscreen mode Exit fullscreen mode

scripts/ahmet_user.sh dosyamızın içeriği şu şekilde:

# File: scripts/ahmet_user.sh
default_user "ahmet" "ahmet@mail.domain" "password"
Enter fullscreen mode Exit fullscreen mode

Test zamanı geldi, projemizin son yapısı şu şekilde:

.
├── mydb.db
├── scheme
│   └── user.sql
├── scripts
│   ├── admin_user.sh
│   └── ahmet_user.sh
└── sqlite.sh
Enter fullscreen mode Exit fullscreen mode

Hadi çalıştıralım.

> sh sqlite.sh
< user.sql...[done]
< admin...[added] # veya exists
< ahmet...[added] # veya exists
Enter fullscreen mode Exit fullscreen mode

yukarıdaki gibi bir çıktı alıyorsak büyük ihtimalle başarılı olduk, emin olmak için veritabanını kontrol edelim:

> sqlite3 mydb.db "SELECT * FROM user;"
< 1|admin|admin@mail.domain|1234|2025-07-20 15:40:38
< 2|ahmet|ahmet@mail.domain|password|2025-07-20 15:40:38
Enter fullscreen mode Exit fullscreen mode

Harika oldu! SQLite öğrenmek ve scriptin tam haline erişmek için kaynaklar kısmına bakabilirsiniz, hoşçakalın ☺️.

Kaynaklar

Top comments (0)