Tips super dari perintah fg: ketika Ctrl+Z menyelamatkan sesi terminal Anda
Diterbitkan 18 April 2026
- Masalah: terminal yang sibuk
- tiga perintah esensial
- Skenario 1: Build yang panjang
- Skenario 2: editor yang dilapkan
- Scenario 3 : Proses opencode ditangguhkan
- Skenario 4: Mengelola beberapa pekerjaan secara bersamaan
- Perbedaan antara fg, bg, Ctrl+Z, Ctrl+C dan &
- Siklus hidup lengkap dari sebuah pekerjaan
- Tips lanjut
- Jebakan dan kesalahan umum
- Diagram Ringkasan
- Mengapa fg dianggap kurang?
- Catatan teknis : sinyal
- Kesimpulan
- Referensi
Anda melempar`./gradlew build`, terminal terblokir selama 3 menit, dan Anda perlu melakukan sesuatu yang lain menunggu ? Tidak perlu membuka tab baru.`Ctrl+Z`menangguhkan proses,`fg`Dia mengembalikannya tepat di tempat Anda meninggalkan. Ini adalah tips Unix yang paling kurang dihargai dalam kehidupan sehari-hari seorang pengembang.
- toc
-
[]
Masalah: terminal yang sibuk
Setiap developer telah menjalani situasi ini:
$ ./gradlew build
> Building...
Terminal terblokir. Anda tidak dapat lagi mengetik perintah apa pun. Dan Anda perlu melihat sebuah file, menjalankan sebuah`git status`, atau memeriksa port yang sedang digunakan.
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "Terminal" as term participant "Gradle\n( proses )" as gradle dev -> term : ./gradlew build term -> gradle : Lance le build gradle -> term : Occupe le terminal\n(pas de prompt) dev -> term : veut taper une commande term --> dev : ❌ Terminal bloqué note right of dev Le développeur est paralysé pendant toute la durée du build end note @enduml
Kebanyakan pengembang membuka terminal baru. Namun ada solusi yang lebih elegan, lebih cepat, dan bawaan: manajemen pekerjaan.
tiga perintah esensial
Ctrl+Z — Menangguhkan (SIGTSTP)
`Ctrl+Z`mengirim sinyal`SIGTSTP`ke proses latar depan. Prosesnya adalahditangguhkan— tidak terbunuh — dan terminal kembali mendapatkan prompt-nya.
$ ./gradlew build
> Building...
^Z
[1]+ Stoppé ./gradlew build
$
Angka di antara tanda kurung`[1]`adalahnomor pekerjaan. Le `+`menunjukkan pekerjaan default
fg — Membawa ke depan
`fg`Memulihkan job yang dijeda ke latar depan. Proses melanjutkan tepat dari tempat ia berhenti.
$ fg
./gradlew build
> Building... (reprend où il en était)
Dengan nomor pekerjaan spesifik:
$ fg %2
bg — Lanjutkan di latar belakang
`bg`lanjutkan proses tanpa memblokir terminal. Ideal untuk build yang panjang.
$ bg
[1]+ ./gradlew build &
$
Le `&`pada akhirnya berarti bahwa proses berjalan di latar belakang.
jobs — Daftar pekerjaan shell
$ jobs
[1]- Stoppé vim README.md
[2]+ En cours ./gradlew build
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif state "Depan (terminal diblokir)" as fg #LightCoral state "Ditangguhkan\n(Ctrl+Z)" as stopped #LightYellow state "Latar belakang\n(bg)" as bg_ #LightGreen [*] --> fg : Lance une commande fg --> stopped : Ctrl+Z\n(SIGTSTP) stopped --> fg : fg\nreprend en avant-plan stopped --> bg_ : bg\nreprend en arrière-plan bg_ --> fg : fg\nramène en avant-plan fg --> [*] : Commande terminée note right of stopped Le processus est figé mais _pas_ tué end note note left of bg_ Le terminal est libre le build continue end note @enduml
Skenario 1: Build yang panjang
Ini adalah kasus penggunaan yang paling umum. Anda menjalankan build Gradle, terminal terblokir, dan Anda perlu melakukan hal lain.
@startuml skinparam backgroundColor #FEFEFE autonumber actor Développeur as dev participant "Terminal" as term participant "Gradle" as gradle database "kondisi proses" as state dev -> term : ./gradlew build term -> gradle : Lance le build gradle -> state : En cours (FG) dev -> term : Ctrl+Z term -> state : Suspendu (job [1]) term --> dev : Prompt libre $ dev -> term : git status term --> dev : working tree clean dev -> term : fg term -> state : Reprend (FG) gradle --> dev : Build réussi ✓ note right of state Le processus Gradle n'a jamais été tué Il reprend exactement où il s'était arrêté end note @enduml
langkah demi langkah
$ ./gradlew build
> Building...
^Z
[1]+ Stoppé ./gradlew build
$ git status
On branch main
nothing to commit, working tree clean
$ fg
./gradlew build
> Building...
BUILD SUCCESSFUL in 2m 34s
Skenario 2: editor yang dilapkan
Anda berada di`vim`, Anda perlu membuka file lain tanpa meninggalkan`vim`.
# Dans vim, en mode commande :
:shell
$ cat /path/to/other/file.txt
$ exit
# Retour dans vim
Tetapi ini berat. Dengan`Ctrl+Z`, ini langsung :
# Dans vim, n'importe quel moment :
Ctrl+Z
[1]+ Stoppé vim README.md
$ cat /path/to/other/file.txt
# ... lire le fichier ...
$ fg
vim README.md
# Retour exact là où on en était, curseur en place
@startuml skinparam backgroundColor #FEFEFE autonumber actor Développeur as dev participant "semangat" as vim participant "Kerang" as shell dev -> vim : édition en cours dev -> vim : Ctrl+Z vim -> shell : Suspendu (job [1]) dev -> shell : cat autre_fichier.txt shell --> dev : contenu du fichier dev -> shell : fg shell -> vim : Reprend (job [1]) vim --> dev : Curseur exactement\nà la même position note right of vim vim restaure intégralement l'état : position du curseur, buffer, undo stack end note @enduml
</think> </think> (No content to translate)vim`mengembalikan dengan sempurna keadaan setelah sebuah`fg: posisi kursor, isi buffer, riwayat pembatalan — semua dipertahankan.
Scenario 3 : Proses opencode ditangguhkan
Ini adalah skenario yang memotivasi artikel ini. Anda menggunakan`opencode`(alat CLI untuk mengendalikan LLM pada kode Anda), dan prosesnya ditangguhkan.
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif skinparam componentStyle rectangle actor Développeur as dev participant "opcode\n(agen LLM)" as agent participant "Shell" as shell participant "git" as git dev -> agent : Session active agent -> agent : Tour de parole\ndu LLM en cours note over agent Ctrl+Z arrive en plein milieu d'une analyse de code end note dev -> agent : Ctrl+Z agent -> shell : Suspendu (job [1]) dev -> git : git diff git --> dev : changements visibles dev -> shell : fg shell -> agent : Reprend (job [1]) agent --> dev : Reprend exactement\nl'analyse en cours note right of agent Aucune perte de contexte Le LLM reprend sa réponse exactement où il en était end note @enduml
$ opencode
# ... session en cours, LLM analyse le code ...
^Z
[1]+ Stoppé opencode
$ git diff HEAD~1
# vérifier les changements récents
$ fg
opencode
# Le LLM reprend là où il s'était arrêté
Keuntungannya adalah ganda:
-
Tidak ada kehilangan konteks: sesi LLM, riwayat percakapan, file yang terbuka — semuanya dipertahankan
-
Tidak ada restart: tidak perlu menjalankan ulang opencode, tidak perlu memuat ulang konteks, tidak perlu menjelaskan ulang masalah kepada LLM
Skenario 4: Mengelola beberapa pekerjaan secara bersamaan
fg et `bg`Menerima nomor pekerjaan untuk menargetkan proses tertentu ketika beberapa proses ditangguhkan.
$ vim config.yml
^Z
[1]+ Stoppé vim config.yml
$ ./gradlew test
^Z
[2]+ Stoppé ./gradlew test
$ htop
^Z
[3]+ Stoppé htop
$ jobs
[1] Stoppé vim config.yml
[2]- Stoppé ./gradlew test
[3]+ Stoppé htop
$ fg %2
./gradlew test
# Le build reprend en avant-plan
$ bg %3
[3] htop &
# htop reprend en arrière-plan
@startuml
skinparam backgroundColor #FEFEFE
rectangle "Pekerjaan ditangguhkan" as jobs #LightYellow {
card "[1] vim config.yml" as j1
card "[2] ./gradlew test" as j2
card "[3] htop" as j3
}
rectangle "Tindakan" as actions #LightGreen {
card "fg %2\n→ latar depan" as a1
card "bg %3\n→ arrière-plan" as a2
card "fg %1\n→ latar depan" as a3
}
jobs --> actions : fg/bg + numéro de job
actions --> j2 : Reprend
actions --> j3 : En arrière-plan
note bottom of jobs
Chaque job conserve
son état exact
entre les suspend/resume
end note
@enduml
Ringkasan perintah pekerjaan
| Pesanana | Efek | Contoh |
|---|---|---|
|
Jeda proses latar depan |
Pengiriman`SIGTSTP` |
|
Mengambil kembali pekerjaan default ke latar depan |
|
|
Lanjutkan pekerjaan n di latar depan |
|
|
Melanjutkan job default di latar belakang |
|
|
Meneruskan pekerjaan n di latar belakang |
|
|
Daftar pekerjaan shell saat ini |
|
|
Selesaikan pekerjaan n |
|
Perbedaan antara fg, bg, Ctrl+Z, Ctrl+C dan &
Banyak pengembang bingung dengan mekanisme ini. Ini adalah penjelasan yang penting.
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "**Ctrl+Z**\nSIGTSTP" as ctrlz #LightYellow {
card "Menjeda proses
(masih berada di memori)
Dapat digunakan dengan fg/bg" as c1
}
rectangle "**Ctrl+C**\nSIGINT" as ctrlc #LightCoral {
card "Bunuh proses
(Tidak ada kemungkinan kembali)
Kehilangan seluruh status" as c2
}
rectangle "**& **
(latar belakang)" as ampersand #LightGreen {
card "Mulai langsung
di latar belakang
Terminal gratis segera" as c3
}
rectangle "**fg**
(lat depan)" as fg_ #SkyBlue {
card "Bawa pekerjaan
ditangguhkan di latar depan
Terminal sibuk" as c4
}
rectangle "**bg**
(lat belakang)" as bg_ #Lavender {
card "Mengambil kembali pekerjaan
ditangguhkan di latar belakang
Terminal bebas" as c5
}
ctrlz -right-> fg_ : fg pour reprendre
ctrlz -right-> bg_ : bg pour continuer\nen arrière-plan
ctrlc -right-> c2 : Pas de retour\nprocessus tué
note bottom of ctrlz
Le processus est **figé**
mais **pas tué**
end note
note bottom of ampersand
Alternative : lancer
./gradlew build &
directement en arrière-plan
end note
@enduml
| Pintasan/Perintah | sinyal | Efek | Kembali? |
|---|---|---|---|
|
|
Menjeda proses (beku, di memori) |
Ya :`fg` ou |
|
|
Matikan proses (selesai) |
Tidak : proses dihancurkan |
|
|
Membunuh proses + core dump |
Tidak: proses dihancurkan |
|
— |
Jalankan langsung di latar belakang |
`fg`untuk membawakannya kembali ke lat depan |
Ctrl+Z`adalahnon destruktif. Prosesnya beku seperti yang ada, dalam memori. Anda dapat melanjutkan segera dengan`fg. Ini adalah jeda, bukan berhenti.
|
Siklus hidup lengkap dari sebuah pekerjaan
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif title Siklus hidup lengkap dari pekerja shell state "tidak ada" as none state "Foreground\n(menempati terminal)" as foreground #LightCoral state "Dijeda\n(Ctrl+Z / SIGTSTP)" as suspended #LightYellow state "Latar belakang\n(bg atau &)" as background #LightGreen state "Selesai\n(exit code 0)" as done #LightGray [*] --> none none --> foreground : tape une commande foreground --> suspended : Ctrl+Z foreground --> done : fin normale suspended --> foreground : fg suspended --> background : bg suspended --> done : kill %n background --> foreground : fg background --> done : fin normale\n(en arrière-plan) background --> suspended : Ctrl+Z\n(si fg puis Ctrl+Z) done --> [*] note right of suspended L'état suspendu est le pivot de tout le système de jobs end note @enduml
Tips lanjut
fg dengan pekerjaan paling baru dan pertukaran
fg`tanpa argumen mengembalikan pekerjaan yang ditandai+(terbaru). Anda juga dapat menggunakan%-`untuk menargetkan pekerjaan sebelumnya :
$ vim file1.txt
^Z
[1]+ Stoppé vim file1.txt
$ vim file2.txt
^Z
[2]+ Stoppé vim file2.txt
$ fg # ramène job [2] (le plus récent)
$ fg %- # ramène job [1] (le précédent)
Mengerjakan pekerjaan dengan baik
$ jobs
[1]- Stoppé vim config.yml
[2]+ Stoppé ./gradlew test
$ kill %2 # envoie SIGTERM au job 2
$ kill -9 %1 # envoie SIGKILL au job 1 (force)
disown : melepaskan dari shell
disown`Menghapus satu pekerjaan dari tabel pekerjaan shell. Proses terus berjalan tetapi tidak dapat lagi dikembalikan dengan`fg</think> (empty output)
$ ./gradlew build &
[1] 12345
$ disown %1
# Le processus continue mais n'est plus lié au shell
# Ça survives à la fermeture du terminal
Gabungkan dengan nohup untuk proses-proses yang lama
Agar proses dapat bertahan saat terminal ditutup:
$ nohup ./gradlew build &
[1] 12345
$ disown %1
# Le build continue même si vous fermez le terminal
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "fg" as fg_ #SkyBlue {
card "Bawa pekerjaan
terbaru (+)" as f1
card "Sasarkan pekerjaan\nspesifik: fg %n" as f2
card "Beralih : fg %-" as f3
}
rectangle "membunuh %n" as kill_ #LightCoral {
card "SIGTERM (bersih)" as k1
card "SIGKILL -9 (paksa)" as k2
}
rectangle "mengalakkan" as disown #Lavender {
card "Lepaskan dari shell
(Bertahan saat putus koneksi)" as d1
}
rectangle "nohup + &" as nohup_ #LightGreen {
card "Proses yang diimmunisasi
terhadap SIGHUP
(masih berjalan saat penutupan
terminal)" as n1
}
fg_ -right-> kill_ : si faut\nterminer
kill_ -right-> disown_ : ou détacher
nohup_ -left-> fg_ : fg ramène en\navant-plan
note bottom of disown_
Après disown, fg ne peut
plus ramener le job
end note
@enduml
Jebakan dan kesalahan umum
Mengalirkan Ctrl+Z dan Ctrl+C
Ini adalah kesalahan yang paling sering.`Ctrl+C`menghentikan proses`Ctrl+Z`Dia menangguhkannya. Jika Anda menekan`Ctrl+C`Secara refleks, seluruh keadaan hilang — file terbuka, sesi LLM, build sedang berlangsung.
@startuml
skinparam backgroundColor #FEFEFE
rectangle "Ctrl+Z (SIGTSTP)" as z #LightGreen {
card "Proses yang membeku di memori" as z1
card "fg membawanya kembali utuh" as z2
card "Tidak ada kerugian" as z3
}
rectangle "Ctrl+C (SIGINT)" as c #LightCoral {
card "Proses selesai" as c1
card "Kondisi hilang secara permanen" as c2
card "Tidak dapat dikembalikan" as c3
}
note bottom of z
Pause → Reprendre
end note
note bottom of c
Kill → Perdu
end note
@enduml
Pekerjaan-pekerjaan adalah lokal untuk shell
jobs, fg et `bg`Berfungsi hanya di shell yang meluncurkan proses-proses tersebut. Jika Anda membuka terminal baru, Anda tidak akan melihat pekerjaan dari yang lain.
# Terminal 1
$ vim file.txt
^Z
[1]+ Stoppé vim file.txt
# Terminal 2 (nouveau)
$ jobs
# (rien — les jobs sont locaux au shell)
Untuk melihat proses system-wide, gunakan`ps` ou htop(empty)
ps aux | grep vim
Pekerjaan tidak bertahan saat shell ditutup
Jika Anda menutup terminal, semua pekerja yang ditangguhkan atau yang berjalan di latar belakang akan dihancurkan. Agar sebuah proses tetap hidup, gunakan`nohup`+disown :
$ nohup ./gradlew build &
[1] 12345
$ disown %1
# Fermer le terminal → le build continue
Proses interaktif dan fg
Beberapa program interaktif tidak berjalan baik setelah satu`Ctrl+Z`+fg. Ini jarang tetapi terjadi :
-
Beberapa program yang menggunakan sinyal (vim, htop, less menangani dengan baik`Ctrl+Z`)
-
Program jaringan yang berjalan lama (ssh, opencode) biasanya pulih dengan benar
-
Program yang memodifikasi terminal (ncurses) terkadang dapat meninggalkan terminal dalam keadaan yang tidak terduga
Jika terminal rusak setelah satu`fg`, ketik :
reset
Diagram Ringkasan
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444
title "fg — Tips yang mengubah semuanya"
rectangle "Masalah" as problem #LightCoral {
card "Terminal diblokir\noleh proses" as p1
card "Buka sebuah baru
terminal = solusi berat" as p2
}
rectangle "**Solusi**" as solution #LightGreen {
card "Ctrl+Z → menangguhkan" as s1
card "fg → melanjutkan" as s2
card "bg → di latar belakang" as s3
card "jobs → lihat yang ditangguhkan" as s4
}
rectangle "**Kelebihan**" as advantages #SkyBlue {
card "Tidak ada kehilangan konteks" as a1
card "Tidak ada restart" as a2
card "Satu terminal cukup" as a3
}
problem -right-> solution : "Solusi asli\nUnix selama 40 tahun"
solution -right-> advantages : "Hasil"
note bottom of advantages
fg n'est pas un tips obscur
C'est un mécanisme fondamental
du shell Unix
end note
@enduml
Mengapa fg dianggap kurang?
Kebanyakan pengembang modern menemukan`fg`lambat, bahkan tidak pernah. Beberapa alasan :
-
IDE menyembunyikan terminal: VS Code menyediakan terminal terintegrasi, tetapi tab-tab banyak membuat`fg`Terlihat kurang diperlukan
-
Alat grafis mengganti CLI: manajer file, pemantau sistem, klien Git grafis
-
tmux dan screen: multiplexer ini menyelesaikan masalah yang sama dengan cara yang berbeda, tapi`fg`lebih sederhana dan selalu tersedia
Namun,`fg`adalah :
-
Universal: ada di semua shell POSIX (bash, zsh, fish…)
-
Tanpa ketergantungan: tidak perlu menginstal tmux atau screen
-
seketika: dua pukulan (
Ctrl+Z`lalu`fg) untuk menangguhkan dan melanjutkan -
Penyimpan konteks: keadaan proses masih utuh
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "Mengapa fg adalah
diperkirakan terlalu rendah ?" as why #LightCoral {
card "IDE dengan terminal\nmulti-tab" as w1
card "Outils graphiques\nqui remplacent le CLI" as w2
card "tmux/screen\nrésolvent le problème\nautrement" as w3
}
rectangle "Mengapa fg adalah
lebih baik ?" as superior #LightGreen {
card "Universal : bash,\nzsh, fish, sh..." as s1
card "Tanpa ketergantungan:
tidak ada instalasi" as s2
card "Dua pukulan:
Ctrl+Z lalu fg" as s3
card "Konteks yang terpreservasi :\nnol kehilangan status" as s4
}
why -right-> superior : "Kesederhanaan
selalu menang"
@enduml
Catatan teknis : sinyal
Untuk yang penasaran, berikut sinyal yang terlibat:
| sinyal | nama | Dikirim oleh | Efek |
|---|---|---|---|
2 |
|
|
Interupsi — menghentikan proses |
3 |
|
|
Keluar dengan core dump |
18 |
|
|
Berhenti interaktif — menghentikan proses |
19 |
|
|
Continue — melanjutkan proses yang ditangguhkan |
15 |
|
|
Penghentian bersih |
9 |
|
|
Pengakhiran paksa (tidak dapat diintersep) |
Alur lengkap :
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif participant "pengguna" as user participant "cangkang" as shell participant "Proses" as proc user -> shell : Ctrl+Z shell -> proc : SIGTSTP (signal 18) note right of proc : Processus figé\nen mémoire user -> shell : fg shell -> proc : SIGCONT (signal 19) note right of proc : Processus reprend\nen avant-plan user -> shell : bg shell -> proc : SIGCONT (signal 19) note right of proc : Processus reprend\nen arrière-plan user -> shell : Ctrl+C shell -> proc : SIGINT (signal 2) note right of proc : Processus terminé\nétat perdu @enduml
Kesimpulan
`fg`Bukanlah sebuah tips yang tidak jelas — ini adalah mekanisme dasar dari Unix shell, yang tersedia sejak tahun 1970-an. Fakta bahwa kebanyakan pengembang mengabaikannya adalah gejala dari jaman kita : IDE dan multiplexer telah menjauhkan kita dari dasar.
Tetapi ketika Anda berada pada server SSH, di terminal minimal, atau sekadar sedang menggunakan`opencode`dan LLM sedang bekerja penuh —Ctrl+Z, fg, bg, `jobs`adalah teman terbaik Anda.
_ Ctrl+Z menghentikan, fg melanjutkan. Ini adalah pause-play terminal. _
Referensi
-
man bash— bagian KONTROL PEKERJAAN -
man signal— daftar sinyal POSIX