Super saveti komande fg: kada Ctrl+Z čuva vašu sesiju terminala
Објављено 18 April 2026
- Problem: zauzet terminal
- Tri neophodne komande
- Scenarij 1: dugi build
- Scenario 2: Zaboravljeni urednik
- Сценарио 3: Процесс opencode приостановљен
- Сценарио 4: Управљати више послова у истом времену
- Razlike između fg, bg, Ctrl+Z, Ctrl+C i &
- Potpun životni ciklus posla
- Napredni saveti
- ловушке и честе грешке
- Сводни дијаграм
- Zašto fg je podocenjen
- Tehnička memorija: signali
- Zaključak
- Референце
Vi bacate`./gradlew build`, terminal je blokiran za 3 minute, i vi trebate da uradite nešto drugo čekajući? Ne treba da otvorite novu karticu.`Ctrl+Z`zaustavljuje proces,`fg`Vraća vas tačno na mesto gde ste ga ostavili. To je najmanje cenjen Unix savet u svakodnevnom životu programera.
- так
-
[]
Problem: zauzet terminal
Svaki programer je doživio ovu situaciju:
$ ./gradlew build
> Building...
Терминал је блокиран. Више не можете укуцати ниједну команду. И вам је потребно прегледати датотеку, покренути`git status`, или проверити заузети порт.
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "Терминал" as term participant "Gradle ( proces )" 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
Većina programera otvara novi terminal. Ipak postoji rešenje koje je elegantnija, brža i prirodna: upravljanje poslovima.
Tri neophodne komande
Ctrl+Z — Zaustavi (SIGTSTP)
`Ctrl+Z`Šalje signal`SIGTSTP`процесу у передњем плану. Процес јеsuspendovan— ne ubijen — i terminal vraća svoj prompt.
$ ./gradlew build
> Building...
^Z
[1]+ Stoppé ./gradlew build
$
Број између заграда`[1]`јеbroj posla. Le `+`ukazuje na podrazumevani posao
fg — Врати на предњи план
`fg`vraća zaustavljen posao u primarni plan. Proces se nastavlja tačno gde se je zaustavio.
$ fg
./gradlew build
> Building... (reprend où il en était)
Sa specifičnim brojem posla :
$ fg %2
bg — Nastavi u pozadini
`bg`Uzima proces bez blokiranja terminala. Idealno za dugograjde gradnje.
$ bg
[1]+ ./gradlew build &
$
Le `&`Na kraju znači da se proces izvršava u pozadini.
jobs — Lista poslova u shellu
$ jobs
[1]- Stoppé vim README.md
[2]+ En cours ./gradlew build
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif state "prednji plan\n(blokiran terminal)" as fg #LightCoral state "Заустavljen\n(Ctrl+Z)" as stopped #LightYellow state "Фон\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
Scenarij 1: dugi build
Ovo je najčešći slučaj korištenja. Pokrenete Gradle build, terminal je blokiran, i morate da uradite nešto drugo.
@startuml skinparam backgroundColor #FEFEFE autonumber actor Développeur as dev participant "terminal" as term participant "Gradle" as gradle database "stanje\nproces" 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
Korak po korak
$ ./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
Scenario 2: Zaboravljeni urednik
Vi ste u`vim`, trebate da pogledate drugi fajl bez napuštanja`vim`.
# Dans vim, en mode commande :
:shell
$ cat /path/to/other/file.txt
$ exit
# Retour dans vim
Ali je teško. Sa`Ctrl+Z`, to je odmah :
# 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 "vim" as vim participant "lupija" 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
Белешка:`vim`savršeno vraća svoje stanje nakon`fg`: pozicija kurzora, sadržaj bafera, istorija poništavanja — sve je sačuvano.
Сценарио 3: Процесс opencode приостановљен
Ово је сценариј који је мотивао ovaj чланак. Ви користите`opencode`(CLI alat za pokretanje LLM na vašem kodu), a proces je zaustavljen.
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif skinparam componentStyle rectangle actor Développeur as dev participant "opencode (агент 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é
Предност је двострука :
-
Нет губитка контекста: сесија LLM, историја разговора, отварені датотеке — све је сачувано
-
Никаког рестартане треба покретати опенкоде, не треба поновити контекст, не треба поново обяснити проблематицу LLM-у
Сценарио 4: Управљати више послова у истом времену
fg et `bg`Prihvataju broj posla za ciljanje specifičnog procesa kada je više procesa pozastavljen.
$ 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 "Pozastavljeni poslovi" as jobs #LightYellow {
card "[1] vim config.yml" as j1
card "[2] ./gradlew test" as j2
card "[3] htop" as j3
}
rectangle "Akcije" as actions #LightGreen {
card "fg %2
→ предњи план" as a1
card "bg %3\n→ pozadina" as a2
card "fg %1\n→ prednji plan" 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
Свод наредби за poslove
| narudžba | efekat | primer |
|---|---|---|
|
Suspendiraj proces u prvom planu |
Slanje`SIGTSTP` |
|
Ponovo preuzima podrazumevani posao u primarnom planu |
|
|
Навести посао n у передњи план |
|
|
Продовити подразумевани задатак у позадини |
|
|
Врати посао n у позадни план |
|
|
Покажи радње текуће шелле |
|
|
Završi posao n |
|
Razlike između fg, bg, Ctrl+Z, Ctrl+C i &
Mnogo programera miješa ove mehanizme. Evo odlučnog objašnjenja.
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "**Ctrl+Z**\nSIGTSTP" as ctrlz #LightYellow {
card "Pauziraj proces\n(Još uvek je u memoriji)\nKoristivo sa fg/bg" as c1
}
rectangle "**Ctrl+C**\nSIGINT" as ctrlc #LightCoral {
card "Ubij proces
(ne moguće vratiti)
Gubitak celog stanja" as c2
}
rectangle "** & **\n(pozadina)" as ampersand #LightGreen {
card "Pokreni odmah
u pozadini
Slobodan terminal odmah" as c3
}
rectangle "**fg**
(предњи план)" as fg_ #SkyBlue {
card "Премени заустављени задатак у провид\nЗаузети терминал" as c4
}
rectangle "**bg**
(pozadina)" as bg_ #Lavender {
card "Nastavi posao
Suspendovan u pozadini
Slobodan terminal" 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
| Пречица/Команда | Signal | Efekat | Vratiti se nazad? |
|---|---|---|---|
|
|
Zaustavi proces (zamrznut, u memoriji) |
Да :`fg` ou |
|
|
Ubij proces (završen) |
Не : уништожен процес |
|
|
Zabij proces + core dump |
Ne: proces uništen |
|
— |
Pokreni u pozadini direktno |
`fg`da ga vrati u prednji plan |
Ctrl+Z`jeнедеструктиван. Proces je zaklepčen kako jest, u memoriji. Možete nastaviti odmah sa`fg. To je pauza, ne zaustavak.
|
Potpun životni ciklus posla
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif title Potpuni životni ciklus shell posla state "Nepostojeci" as none state "Prioritetno\n(zauzima terminal)" as foreground #LightCoral state "Zaustavljeno (Ctrl+Z / SIGTSTP)" as suspended #LightYellow state "Pozadina\n(bg ili &)" as background #LightGreen state "Завршено (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
Napredni saveti
fg sa najnovijim poslom i alternativom
fg`Без аргумента враћа означени посао+`(najnoviji). Ali možete Takođe koristiti
Wait: I accidentally capitalized "Takođe". Should be lowercase "takođe". So correct: " (najnoviji). Ali možete takođe koristiti". Ensure "takođe" is lowercase. Yes.
Thus final output.
</think>
(najnoviji). Ali možete takođe koristiti`%-`da se usmeri na prethodni posao :
$ 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)
убити посао на правилан начин
$ 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 : odvoji se od shell-a
disown`Ukloni posao iz tabele poslova shella. Proces nastavlja da se izvršava, ali ne može više biti vratio sa`fg:
$ ./gradlew build &
[1] 12345
$ disown %1
# Le processus continue mais n'est plus lié au shell
# Ça survives à la fermeture du terminal
Kombinirati sa nohup za dugoke procese
Da bi proces preživio zatvaranje terminala:
$ 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 "Vrati posao
najnoviji (+)" as f1
card "Целиј један посао
specifižno : fg %n" as f2
card "Алтерниши : fg %-" as f3
}
rectangle "убиј %n" as kill_ #LightCoral {
card "SIGTERM (čist)" as k1
card "SIGKILL -9 (prisilno)" as k2
}
rectangle "одрећи се" as disown #Lavender {
card "Одвој из шелла\n(остаје активан после одјаве)" as d1
}
rectangle "nohup + &" as nohup_ #LightGreen {
card "Imunizovani proces
protiv SIGHUP
(preživljava zatvaranje terminala)" 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
ловушке и честе грешке
Мешати Ctrl+Z и Ctrl+C
Ovo je najčešća greška.`Ctrl+C`ubija proces.`Ctrl+Z`Ga zaustavlja. Ako pritisnete na`Ctrl+C`iz refleksa, sve stanje je izgubljeno — otvoreni fajlovi, sesije LLM, gradnje u toku.
@startuml
skinparam backgroundColor #FEFEFE
rectangle "Ctrl+Z (SIGTSTP)" as z #LightGreen {
card "Zamrzli proces u memoriji" as z1
card "fg ga vraća nepovređen" as z2
card "Никаша губатак" as z3
}
rectangle "Ctrl+C (SIGINT)" as c #LightCoral {
card "Završen proces" as c1
card "Стажно загублено стање" as c2
card "Nemoguće vraćanje" as c3
}
note bottom of z
Pause → Reprendre
end note
note bottom of c
Kill → Perdu
end note
@enduml
Poslovi su lokalni u shellu
jobs, fg et `bg`ne funkcionišu samo u shellu koji je pokrenuo procese. Ako otvorite novi terminal, nećete videti jobove drugog.
# Terminal 1
$ vim file.txt
^Z
[1]+ Stoppé vim file.txt
# Terminal 2 (nouveau)
$ jobs
# (rien — les jobs sont locaux au shell)
Da biste videli sistemski procesi, koristite`ps` ou htop:
ps aux | grep vim
Poslovi ne preživljavaju zatvaranje shell-a
Ako zatvorite terminal, svi suspenirani ili pozadinski poslovi su uništeni. Da biste proces preživi, koristite`nohup`+disown :
$ nohup ./gradlew build &
[1] 12345
$ disown %1
# Fermer le terminal → le build continue
Interaktivni procesi i fg
Neki interaktivni programi nisu u dobrom stanju nakon jednog`Ctrl+Z`+fg. Ретко је, но дешава се :
-
Neki programi koji koriste signale (vim, htop, less) dobro upravljaju`Ctrl+Z`)
-
Дуготрајни мрежни програми (ssh, opencode) обично исправно опорављају
-
Programi koji modifikuju terminal (ncurses) mogu ponekad ostaviti terminal u neočekivanom stanju.
U slučaju oštećenog terminala nakon`fg`, ukucaj :
reset
Сводни дијаграм
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444
title "fg — Savet koji menja sve"
rectangle "**Problem**" as problem #LightCoral {
card "Terminal zaključan\nod jednog procesa" as p1
card "Отварање новог
терминала = тешко решење" as p2
}
rectangle "**rešenje**" as solution #LightGreen {
card "Ctrl+Z → pauziraj" as s1
card "fg → преузима" as s2
card "bg → у позадину" as s3
card "poslovi → pogledajte suspendovane" as s4
}
rectangle "Предности" as advantages #SkyBlue {
card "Нема губитка контекста" as a1
card "Није могуће рестартирати" as a2
card "Dovoljno je jedan terminal" as a3
}
problem -right-> solution : "Природно решение
Unix од 40 година"
solution -right-> advantages : "Резултат"
note bottom of advantages
fg n'est pas un tips obscur
C'est un mécanisme fondamental
du shell Unix
end note
@enduml
Zašto fg je podocenjen
Većina modernih programera otkriva`fg`kasno, ili čak nikada. Neki razlozi :
-
IDE sakrivaju terminal: VS Code nudi ugrađeni terminal, ali više kartica prave`fg`manje potrebno na prvi pogled
-
Grafički alati zamjenjuju CLI: управљачи фајловима, системски монитори, графички кlijenti Git
-
tmux i screen: ovi multipleskseri rešavaju isti problem na drugačiji način, ali`fg`je jednostavniji i uvek dostupan
Ipak,`fg`je :
-
универзалниprisutan u svim POSIX shell-ovima (bash, zsh, fish…)
-
Bez zavisnosti: нема потребе да инсталирате tmux или screen
-
Snimak: dva udara (
Ctrl+Z`zatim`fg) za zaustavljanje i nastavak -
Čuvac konteksta: stanje procesa je neporušeno
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "Zašto je fg\npodocenjen ?" as why #LightCoral {
card "IDE sa terminalom\nvišekartično" as w1
card "Графички алати
Који замњују CLI" as w2
card "tmux/screen
решају проблем на другом начин" as w3
}
rectangle "Zasto je fg
superior?" as superior #LightGreen {
card "Универзално : bash,\nzsh, fish, sh..." as s1
card "Bez zavisnosti:\nbez instalacije" as s2
card "Два натиска:\n`Ctrl+Z` затим fg" as s3
card "Kontekst sačuvan :
nula gubitka stanja" as s4
}
why -right-> superior : "Jednostavnost
uvijek pobeđuje"
@enduml
Tehnička memorija: signali
Za zainteresovane, voici signali koji su uključeni :
| Сигнал | Име | Poslao | Efekat |
|---|---|---|---|
2 |
|
|
Prekid — završava proces |
3 |
|
|
Napusti sa core dump |
18 |
|
|
Interaktivni stop — poništava proces |
19 |
|
|
Nastavi — ponovo pokreće suspendovan proces |
15 |
|
|
Правилан завршатак |
9 |
|
|
Prisilno završavanje (ne može se prekinuti) |
Потпун поток :
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif participant "Корисник" as user participant "lupina" as shell participant "Proces" 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
Zaključak
`fg`Nije sakriven savet — to je fundamentalni mehanizam Unix shella, dostupan od 70-h godina. Činjenica da većina razvojara to ignoriše je simptom našeg doba: IDE i multiplexeri nas su udaljiti od osnova.
Pero kada ste na SSH serveru, u minimalnom terminalu, ili jednostavno koristite`opencode`и да LLM је у полној раду —Ctrl+Z, fg, bg, `jobs`су ваши најбољи пријатели.
_ Ctrl+Z suspend, fg nastavlja. To je pauza-play terminala. _
Референце
-
man bash— sekcija JOB CONTROL -
man signal— lista POSIX signala