fg, bg ve jobs Komutları ile Linux’ta Arka Plan ve Ön Plan Süreç Yönetimi
Terminal başlatıyorsunuz, bir komut çalıştırıyorsunuz ve beklenmedik bir şey oluyor: süreç takılıp kalıyor ya da çok uzun sürüyor. Ya da tam tersine, birden fazla işi aynı anda yürütmeniz gerekiyor ama yeni bir terminal sekmesi açmak istemiyorsunuz. İşte tam bu noktada fg, bg ve jobs üçlüsü devreye giriyor. Bu komutları gerçekten kavrayıp sindirdiğinizde, terminal kullanım şekliniz köklü biçimde değişiyor.
Temel Kavramlar: Ön Plan ve Arka Plan Nedir?
Linux’ta her süreç, terminal ile olan ilişkisi açısından iki farklı modda çalışabilir. Ön plan (foreground) modunda çalışan bir süreç, terminali tamamen ele geçirir. Siz de o süreç bitene kadar başka komut çalıştıramazsınız. Arka plan (background) modundaki süreç ise sessiz sedasız işini yaparken terminaliniz serbest kalır.
Burada önemli bir ayrımı hemen yapmak gerekiyor: arka planda çalışmak, suspend edilmek (askıya alınmak) ile aynı şey değil. Askıya alınan süreç durur ve bekler; arka planda çalışan süreç ise gerçekten CPU kullanmaya devam eder, sadece terminal çıktısını kapamamıştır.
Bu farkı unutursanız, “neden CPU’yu hâlâ yiyor?” diye şaşırırsınız. Daha fazla detaya girmeden önce, bu üç komutu pratikte görelim.
jobs Komutu: Mevcut Durumu Anlamak
jobs, mevcut shell oturumundaki tüm arka plan ve askıya alınmış süreçleri listeler. Basit ama bilgi yoğun bir komuttur.
$ sleep 500 &
[1] 14823
$ sleep 300 &
[2] 14824
$ jobs
[1]- Running sleep 500 &
[2]+ Running sleep 300 &
Buradaki köşeli parantez içindeki sayılar job numaralarıdır, PID değil. + işareti en son işleme alınan (current) işi, - işareti ise bir önceki işi gösterir. Bu işaretler fg ve bg komutlarına argüman vermezseniz hangi işin seçileceğini belirler.
jobs komutunun işinize yarayacak bazı parametreleri:
- -l: Job numarasının yanına PID’i de gösterir
- -p: Sadece PID’leri listeler
- -r: Sadece çalışan (running) işleri gösterir
- -s: Sadece durdurulmuş (stopped/suspended) işleri gösterir
- -n: Son
jobsçağrısından bu yana durumu değişen işleri gösterir
$ jobs -l
[1]- 14823 Running sleep 500 &
[2]+ 14824 Running sleep 300 &
$ jobs -p
14823
14824
Özellikle -l parametresi gerçek dünyada çok kullanışlı. Hem job numarasını hem de PID’i görmek, gerektiğinde kill komutuna argüman geçebilmek için hayat kurtarıcı.
Ctrl+Z ile Askıya Alma: Her Şeyin Başladığı Yer
fg ve bg komutlarını anlamak için önce Ctrl+Z kısayolunu kavramak gerekiyor. Ön planda çalışan bir sürece Ctrl+Z gönderdiğinizde, o sürece SIGTSTP sinyali gider ve süreç duraklatılır.
$ top
# top çalışırken Ctrl+Z basıyoruz
^Z
[1]+ Stopped top
$
Artık terminaliniz serbest ve top askıda. Ama dikkat: top artık güncellenmıyor, gerçekten durdu. Bunu bir daha vurgulayalım çünkü yeni başlayanlar buraya takılıyor: Ctrl+Z = durdur, & ile başlatmak = arka planda çalıştır. İkisi farklı şeyler.
bg Komutu: Askıdakini Arka Plana Al
Askıya aldığınız bir süreci arka planda çalışmaya devam ettirmek için bg kullanıyorsunuz.
$ ping -c 1000 google.com > /tmp/ping_test.txt
^Z
[1]+ Stopped ping -c 1000 google.com > /tmp/ping_test.txt
$ bg
[1]+ ping -c 1000 google.com > /tmp/ping_test.txt &
$ jobs
[1]+ Running ping -c 1000 google.com > /tmp/ping_test.txt &
bg komutuna argüman vermezseniz + işaretli, yani en son durdurulan iş seçilir. Belirli bir işi arka plana almak için job numarasını % ile birlikte kullanıyorsunuz:
$ bg %2
Gerçek dünyada bu çok işe yarar. Diyelim ki büyük bir rsync işlemi başlattınız ve terminali meşgul ettiğini fark ettiniz:
$ rsync -avz /home/mehmet/ [email protected]:/backup/mehmet/
# Çok zaman alacak, Ctrl+Z ile durduralım
^Z
[1]+ Stopped rsync -avz /home/mehmet/ [email protected]:/backup/mehmet/
$ bg %1
[1]+ rsync -avz /home/mehmet/ [email protected]:/backup/mehmet/ &
Artık rsync arka planda devam ederken siz başka komutlar çalıştırabilirsiniz.
fg Komutu: Arka Plandan Ön Plana Getir
fg komutu, arka planda veya askıda olan bir işi tekrar ön plana alır. Yani terminalinizi o işe verir ve sonuçlanana kadar beklemeniz gerekir.
$ jobs
[1]- Running sleep 500 &
[2]+ Stopped vim /etc/nginx/nginx.conf
$ fg %2
vim /etc/nginx/nginx.conf
# vim tekrar açılır, devam edebilirsiniz
Bir job numarası belirtmezseniz + işaretli iş ön plana alınır:
$ fg
# En son durdurulan veya arka plana alınan iş ön plana gelir
Birden fazla iş arasında gidip gelmek de mümkün:
$ vim dosya1.txt &
[1] 15001
$ vim dosya2.txt
^Z
[2]+ Stopped vim dosya2.txt
$ fg %1
# dosya1.txt'e geç
^Z
[1]+ Stopped vim dosya1.txt
$ fg %2
# dosya2.txt'e geç
Başlatırken Arka Plana Almak: & Operatörü
Bir komutu baştan arka planda çalıştırmak için sonuna & ekliyorsunuz. Bu, özellikle uzun süren işlemlerde standart bir alışkanlık haline gelmelidir.
$ tar -czf /backup/etc_backup.tar.gz /etc/ &
[1] 15123
$ # Terminal hemen serbest kalır
$ find / -name "*.log" -mtime +30 -delete &
[2] 15124
$ jobs
[1]- Running tar -czf /backup/etc_backup.tar.gz /etc/ &
[2]+ Running find / -name "*.log" -mtime +30 -delete &
Arka planda çalışan sürecin çıktısı terminale gelmeye devam edebilir ve bu can sıkıcı olabilir. Özellikle uzun soluklu işlemlerde çıktıyı yönlendirmek iyi pratik:
$ ./uzun_sure_calisacak_script.sh > /tmp/script_output.log 2>&1 &
[1] 15200
Böylece hem stdout hem stderr bir log dosyasına gider, terminal temiz kalır.
Pratik Senaryo: Sistem Yöneticisinin Günlük İş Akışı
Şimdi gerçeğe yakın bir senaryo düşünelim. Sunucuda birden fazla iş aynı anda yapmanız gerekiyor ve tek bir SSH oturumunuz var (ya da sadece bir terminal penceresi kullanmayı tercih ediyorsunuz):
# 1. Önce büyük bir log dosyasını analiz etmeye başlayalım
$ grep -r "ERROR" /var/log/app/ > /tmp/errors.txt &
[1] 16001
# 2. Nginx konfigürasyonunu düzenliyoruz
$ vim /etc/nginx/sites-available/yeni-site.conf
^Z
[1]+ Stopped vim /etc/nginx/sites-available/yeni-site.conf
# Dikkat: burada [1] değişti çünkü grep bitti
# 3. Durumu kontrol edelim
$ jobs
[1]+ Stopped vim /etc/nginx/sites-available/yeni-site.conf
# 4. Bir şeyleri test etmemiz gerekiyor
$ curl -I http://localhost &
[2] 16002
# 5. vim'e geri dönelim
$ fg %1
# vim açılır, düzenlemeye devam...
Bu iş akışını bir kez içselleştirince, çok terminalli kurulum ihtiyacı önemli ölçüde azalıyor. Tabii tmux veya screen daha güçlü alternatifler, ama basit durumlar için fg/bg/jobs üçlüsü fazlasıyla yeterli.
Job Numarasıyla Çalışmak: % Sözdizimi
Job numaralarını kullanırken % öneki zorunlu. Ama bazı kısayollar da var:
- %1: 1 numaralı iş
- %+ veya %%: En son işleme alınan iş (current job)
- %-: Bir önceki iş
- %ping: İsmi “ping” ile başlayan iş
- %?ping: İsminde “ping” geçen iş
$ sleep 100 &
[1] 17001
$ sleep 200 &
[2] 17002
$ jobs
[1]- Running sleep 100 &
[2]+ Running sleep 200 &
$ kill %1
[1] Terminated sleep 100 &
$ jobs
[2]+ Running sleep 200 &
kill komutunun da job numaralarıyla çalıştığını görmek önemli. Her zaman PID bulmanıza gerek yok.
Arka Planda Çalışan Süreci Sonlandırmak
Arka planda çalışan bir işi durdurmak için birkaç yol var:
# Yöntem 1: fg ile ön plana alıp Ctrl+C
$ fg %1
# Ctrl+C
# Yöntem 2: kill ile direkt job numarasına sinyal gönder
$ kill %1
# Yöntem 3: jobs -l ile PID alıp kill'e ver
$ jobs -l
[1]+ 17050 Running python3 uzun_script.py &
$ kill 17050
# Yöntem 4: SIGKILL gerekiyorsa
$ kill -9 %1
Genellikle kill %1 yeterlidir ve süreci düzgün biçimde sonlandırır. kill -9 ise son çare olarak kalmalı.
disown: Shell’den Koparmak
Bu konuyu işlerken disown komutundan da bahsetmemek olmaz. Arka planda çalışan bir işi shell oturumundan koparmanıza yarar. Peki bu ne zaman gerekli?
Diyelim ki arka planda uzun sürecek bir iş başlattınız, ama SSH oturumunuzu kapatmanız gerekiyor. Normal şartlarda shell kapanınca tüm child process’lere SIGHUP gönderilir ve onlar da ölür. disown bunu engeller:
$ tar -czf /backup/full_backup.tar.gz /home/ &
[1] 18001
$ disown %1
$ jobs
# Boş! Artık bu shell'in job listesinde yok
$ exit
# Ama tar hâlâ çalışıyor
disown -h ise süreci job listesinden çıkarmaz ama SIGHUP’tan korur:
$ long_running_job.sh &
[1] 18100
$ disown -h %1
# Hâlâ jobs listesinde görünür ama shell kapansa da çalışmaya devam eder
Tabii bunun için en doğru araç nohup ya da screen/tmux, ama acil durumlarda disown hayat kurtarır.
wait Komutu ile Arka Plan İşlerini Beklemek
Script yazarken arka plan işlerini senkronize etmeniz gerekebilir. wait komutu tam bu iş için:
#!/bin/bash
# Paralel olarak üç yedekleme başlat
tar -czf /backup/home.tar.gz /home/ &
PID1=$!
tar -czf /backup/etc.tar.gz /etc/ &
PID2=$!
tar -czf /backup/var.tar.gz /var/www/ &
PID3=$!
echo "Yedekleme işlemleri arka planda çalışıyor..."
echo "PID'ler: $PID1, $PID2, $PID3"
# Hepsinin bitmesini bekle
wait $PID1 $PID2 $PID3
echo "Tüm yedeklemeler tamamlandı."
$! değişkeni en son başlatılan arka plan sürecinin PID’ini tutar. Bu script olmadan yazsaydınız, üç tar işlemi sırayla çalışırdı. Paralel çalıştırarak toplam süreyi önemli ölçüde kısaltabilirsiniz.
# Belirli bir işi beklemek yerine hepsini bekleyebilirsiniz
wait
echo "Tüm arka plan işleri bitti"
Yaygın Hatalar ve Dikkat Edilmesi Gerekenler
Arka plan süreci ile terminal çıktısı: Arka planda çalışan bir süreç hâlâ stdout’a yazmaya devam edebilir. Bu, terminalinizi kirletir. Her zaman çıktıyı yönlendirin:
# Kötü
$ python3 script.py &
# İyi
$ python3 script.py > /tmp/script.log 2>&1 &
stdin sorunu: Arka planda çalışan bir süreç stdin okumaya çalışırsa otomatik olarak durur ve Stopped (tty input) mesajı görürsünüz. Bu sık karşılaşılan ama anlaşılması zor bir durumdur:
$ cat &
[1] 19001
# Biraz bekleyin...
[1]+ Stopped cat
$ jobs
[1]+ Stopped cat
Bu durumda ya /dev/null‘dan yönlendirin ya da süreci sonlandırın:
$ cat < /dev/null &
Script içinde job kontrolü: Bash scriptlerinde varsayılan olarak job kontrolü devre dışıdır. Etkinleştirmek için:
#!/bin/bash
set -m # job control'ü aç
Sonuç
fg, bg ve jobs komutları, Linux terminalinde gerçek anlamda verimli çalışmanın temel taşları. Yıllarca bu komutları bilmeden Ctrl+C yapıp komutu yeniden yazanlar, ya da sadece birden fazla terminal penceresi açarak idare edenler olur. Oysa tek bir terminal oturumunda birden fazla işi yönetmek, işin içine girince son derece doğal ve pratik hissettiriyor.
Özellikle uzak sunucularda çalışırken, bant genişliği kısıtlı SSH bağlantılarında ya da sadece tek pencereyle iş yapmayı tercih ettiğinizde bu üçlü gerçekten işe yarıyor. jobs -l ile duruma bakıp bg %2 ile bir işi yeniden canlandırmak, ya da fg %vim ile editörünüze geri dönmek, bir süre sonra düşünmeden yapılan refleks hareketler haline geliyor.
disown ve wait ile birlikte düşündüğünüzde bu araçlar, hem interaktif kullanımda hem de script yazımında güçlü bir süreç yönetim katmanı oluşturuyor. tmux veya screen öğrenmeden önce bu temelleri oturtmanızı tavsiye ederim; çünkü o araçların neden var olduğunu ancak bu temel araçlarla belli bir sınıra ulaştıktan sonra gerçekten anlıyorsunuz.
