نکات فوقالعاده دستور fg : وقتی Ctrl+Z جلسه ترمینال شما را ذخیره میکند
منتشر شده در 18 April 2026
- مشکل: یک ترمینال مشغول
- سه دستور ضروری
- سناریو ۱ : ساخت طولانی
- سناریو ۲ : ویراستار فراموش شده
- سيناريو 3 : پردازش opencode معلق
- سناریو ۴ : مدیریت چندین کار بهصورت همزمان
- تفاوتها بین fg, bg, Ctrl+Z, Ctrl+C و &
- دورهٔ زندگی کامل یک کار
- نکات پیشرفته
- پنجهها و اشتباهات رایج
- نمودار خلاصه
- چرا fg کمارزشگذاری شده است؟
- ذاكرة فنی: ال سیگنالها
- نتیجه
- منابع
شما راهاندازی میکنید`./gradlew build`, ترمینال برای 3 دقیقه مسدود میشود، و شما نیاز دارید کاری دیگر انجام دهید در حال انتظار؟ لازم نیست یک تب جدید باز کنید.`Ctrl+Z`فرآیند را متوقف میکند،`fg`او را دقیقاً جایی که شما آن را ترک کرده بودید، باز میگرداند. این نکته Unix، کمتقویمترین نکته در زندگی روزانه یک توسعهدهنده است.
- تیک
-
[]
مشکل: یک ترمینال مشغول
هر توسعهدهنده این وضعیت را تجربه کرده است :
$ ./gradlew build
> Building...
ترمینال مسدود شده است. دیگر نمیتوانید هیچ دستوری وارد کنید. و شما به بررسی یک فایل و اجرای یک …git status، یا بررسی یک پورت اشغال.
@startuml skinparam backgroundColor #FEFEFE actor Développeur as dev participant "ترمینال" as term participant "Gradle\n( فرآیند )" 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
بسیاری از توسعهدهندگان یک ترمینال جدید باز میکنند. اما راهحلی بهتر، زیباتر، سریعتر و بومی وجود دارد: مدیریت کارها
سه دستور ضروری
Ctrl+Z — تعلیق (SIGTSTP)
`Ctrl+Z`سیگنال را میفرستد`SIGTSTP`به فرآیند پیشروی. فرآیند استمعلق— نکشته نشده — و ترمینال پرامپت خود را باز مییابد.
$ ./gradlew build
> Building...
^Z
[1]+ Stoppé ./gradlew build
$
عدد بین کروشه`[1]`استشماره شغل. Le `+`شغل پیشفرض را نشان میدهد.
fg — آوردن به پیشزمینه
`fg`شغل معلق را به پیشزمینه میآورد. فرآیند دقیقاً جایی که متوقف شده بود، ادامه میدهد.
$ fg
./gradlew build
> Building... (reprend où il en était)
با یک شماره کار مخصوص :
$ fg %2
bg — ادامه در پسزمینه
`bg`فرآیند را بدون مسدود کردن ترمینال ادامه میدهد. مناسب برای ساختهای طولانی.
$ bg
[1]+ ./gradlew build &
$
Le `&`در پایان، این به این معناست که پردازش در پسزمینه در حال اجرا است.
jobs — لیست کارهای شل
$ jobs
[1]- Stoppé vim README.md
[2]+ En cours ./gradlew build
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif state "پیشزمینه (ترمینال مسدود)" as fg #LightCoral state "متوقف (Ctrl+Z)" as stopped #LightYellow state "پسزمینه (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
سناریو ۱ : ساخت طولانی
این مورد استفاده رایجترین است. شما یک ساخت Gradle اجرا میکنید، ترمینال مسدود میشود و شما نیاز دارید کاری دیگر انجام دهید.
@startuml skinparam backgroundColor #FEFEFE autonumber actor Développeur as dev participant "ترمینال" as term participant "گریڈل" as gradle database "وضعیت فرآیند" 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
قدم به قدم
$ ./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
سناریو ۲ : ویراستار فراموش شده
شما در`vim`, شما نیاز دارید تا یک فایل دیگر را مشاهده sans خروج کنید.vim.
# Dans vim, en mode commande :
:shell
$ cat /path/to/other/file.txt
$ exit
# Retour dans vim
اما این سنگین است. با`Ctrl+Z`، این بلافاصله است :
# 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 "حیویت" as vim participant "شل" 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`وضعیتش را بهصورت کامل پس از یک بازگردانده میشود`fg: موقعیت کورسور، محتوی بافر، تاریخ لغو — همه چیز حفظ شده است.
|
سيناريو 3 : پردازش opencode معلق
این سناریویی است که این مقاله را ترغیب کرده است. شما استفاده میکنید`opencode`(ابزار CLI برای کنترل یک LLM بر روی کد شما)، و عملية معلق است
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif skinparam componentStyle rectangle actor Développeur as dev participant "opencode (نماینده LLM)" as agent participant "قشر" as shell participant "گیت" 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، تاریخچه گفتگو، فایلهای باز شده — همه حفظ شده است
-
بدون راهاندازی مجدد: نیازی نیست opencode را دوباره راهاندازی کنیم، زمینه را بارگذاری مجدد کنیم، یا مشکل را به مدل زبانی بزرگ (LLM) توضیح دهیم.
سناریو ۴ : مدیریت چندین کار بهصورت همزمان
fg et `bg`قبول میکنند یک شماره کار برای هدفگیری یک فرآیند خاص هنگامی که چند مورد معلق هستند.
$ 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 "شغلهای معلق" as jobs #LightYellow {
card "[1] vim config.yml" as j1
card "[2] ./gradlew test" as j2
card "[3] htop" as j3
}
rectangle "اقدامات" as actions #LightGreen {
card "fg %2
→ پیشزمینه" as a1
card "bg %3\n→ background" as a2
card "fg %1\n→ پیشزمینه" 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
خلاصه از دستورات کار
| دستور | اثر | مثال |
|---|---|---|
|
فرآیند پیشزمینه را تعلیق میدهد |
ارسال`SIGTSTP` |
|
کار پیشفرض را درforeground بگیرید |
|
|
کار n را در پیشزمین ادامه دهید |
|
|
بازگشت به کار پیشفرض در پسزمینه |
|
|
ادامه job n در پسزمینه |
|
|
وظائف شل جاری را فهرست کنید |
|
|
کار n را تمام کن |
|
تفاوتها بین fg, bg, Ctrl+Z, Ctrl+C و &
چندین توسعهدهنده این مکانیزمها را اشتباه میفهمند. این یک توضیح قطعی است.
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "**Ctrl+Z**\nSIGTSTP" as ctrlz #LightYellow {
card "فرآیند را متوقف کنید
(هنوز در حافظه است)
قابل استفاده با fg/bg" as c1
}
rectangle "**Ctrl+C**\nSIGINT" as ctrlc #LightCoral {
card "فرآیند را بکش
(بازگشت ممکن نیست)
از دست دادن کل وضعیت" as c2
}
rectangle "**& **\n(پسزمینه)" as ampersand #LightGreen {
card "مستقیماً اجرا کن
در پسزمینه
ترمینال آزاد فوراً" as c3
}
rectangle "**fg**
(پیشزمینه)" as fg_ #SkyBlue {
card "یک کار را بیار
در حالت تعلقی در پیشزمینه
ترمینال مشغول" as c4
}
rectangle "**bg**
(پیشزمینه)" as bg_ #Lavender {
card "ادامه دادن به یک کار معلق در پسزمینه
ترمینال آزاد" 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
| میانبر/دستور | سیگنال | اثر | بازگشت به عقب؟ |
|---|---|---|---|
|
|
فرآیند را متوقف کند (مجمد، در حافظه) |
بله:`fg` ou |
|
|
فرآیند را بکشید (پایان یافت) |
نه: فرآیند تخریب شده |
|
|
فرآیند را متوقف کنید + core dump |
نه : فرایند تخریب شده |
|
— |
مستقیم در پسزمینه اجرا کن |
`fg`برایBring it به پیشpland برگرداندن |
Ctrl+Z`استغیرمخرب.فرآیند به همان صورتی که است، در حافظه، منجمد شده است. میتوانید بلافاصله آن را ادامه دهید با`fg. این یک pause است، نه stop .
|
دورهٔ زندگی کامل یک کار
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif title دوره کامل زندگی یک کار شِل state "غیر موجود" as none state "پیشزمینه (ترمینال را اشغال میکند)" as foreground #LightCoral state "متوقف\n(Ctrl+Z / SIGTSTP)" as suspended #LightYellow state "پسزمینه\n(bg یا &)" as background #LightGreen state "تمام (kod خروج 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
نکات پیشرفته
fg با کار جدیدترین و تناوب
fg`بدون آرگومان، کار علامتگذاریشده برمیگردد+(جدیدترین). اما شما نیز میتوانید از آن استفاده کنید%-`برای هدفگیری به کار قبلی :
$ 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 : جدا کردن از شل
disown`یک کار از جدول کارهای شل حذف میشود. فرآیند همچنان در حال اجراست اما دیگر نمیتواند با بازگردانده شود.`fg(Note: a single space character)
$ ./gradlew build &
[1] 12345
$ disown %1
# Le processus continue mais n'est plus lié au shell
# Ça survives à la fermeture du terminal
ترکیب با nohup برای پردازشهای طولانی
به منظور اینکه یک پروسه پس از بستن ترمینال زنده بماند :
$ 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 "کار را بیاور
جدیدترین (+)" as f1
card "یک شغل\nخاص : fg %n" as f2
card "متناوب : fg %-%" as f3
}
rectangle "کش %n" as kill_ #LightCoral {
card "SIGTERM (پاک)" as k1
card "SIGKILL -9 (بهصورت اجباری)" as k2
}
rectangle "انکار" as disown #Lavender {
card "از شل جدا شو
(در قطع اتصال زنده میماند)" as d1
}
rectangle "nohup + &" as nohup_ #LightGreen {
card "فرآیند ضد SIGHUP
(باقی میماند هنگام بستن ترمینال)" 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
این اشتباه رایجترین است.`Ctrl+C`فرآیند را میکشد.`Ctrl+Z`به متوقف میکند. اگر شما فشار دهید بر`Ctrl+C`به طور انعکاسی، تمام وضعیت از دست رفته است — فایلهای باز، جلسات LLM، ساختهای در حال انجام.
@startuml
skinparam backgroundColor #FEFEFE
rectangle "Ctrl+Z (SIGTSTP)" as z #LightGreen {
card "فرآیند منجمد در حافظه" as z1
card "fg او را بهسلامت برمیگرداند" as z2
card "هیچ ضرر" as z3
}
rectangle "Ctrl+C (SIGINT)" as c #LightCoral {
card "فرآیند به پایان رسید" as c1
card "وضعیت بهطور دائم گم شده" as c2
card "بازگشت ممکن نیست" as c3
}
note bottom of z
Pause → Reprendre
end note
note bottom of c
Kill → Perdu
end note
@enduml
کارها محلی به شل هستند
jobs, fg et `bg`فقط در شل که процесها را راهاندازی کردهاند، کار میکنند. اگر یک ترمینال جدید باز کنید، jobs دیگر را نخواهید دید.
# Terminal 1
$ vim file.txt
^Z
[1]+ Stoppé vim file.txt
# Terminal 2 (nouveau)
$ jobs
# (rien — les jobs sont locaux au shell)
برای دیدن فرآیندهای system-wide، استفاده کنید`ps` ou htop:
ps aux | grep vim
کارها پس از بستن شِل، به بقا نمیمانند
اگر ترمینال را ببندید، تمام کارهای موقفهدار یا در پسزمینه حذف میشوند. برای بقاوندن یک فرآیند، استفاده کنید`nohup` + disown :
$ nohup ./gradlew build &
[1] 12345
$ disown %1
# Fermer le terminal → le build continue
فرآیندهای تعاملی و fg
برخی برنامههای تعاملی نه به خوبی عمل میکنند پس از یک`Ctrl+Z`+fg. نادر است اما این اتفاق میافتد :
-
برخی برنامههایی که از سیگنالها استفاده میکنند (vim, htop, less به خوبی مدیریت میشوند`Ctrl+Z`)
-
برنامههای شبکهای طولانی (ssh, opencode) معمولاً بهدرستی بازیابی میشوند
-
برنامههایی که ترمینال را (ncurses) تغییر میدهند گاهی اوقات ترمینال را در وضعیت نامنتظر باقی میگذارند
در صورت خراب شدن ترمینال پس از یک`fg`, تایپ کنید :
reset
نمودار خلاصه
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444
title "fg — نکتی که همه چیز را تغییر میدهد"
rectangle "**مشکل**" as problem #LightCoral {
card "ترمینال مسدود\nتوسط یک پردازش" as p1
card "باز کردن یک\nترمینال = راه حل سنگین" as p2
}
rectangle "حل" as solution #LightGreen {
card "Ctrl+Z → تعلیق" as s1
card "fg → ادامه میدهد" as s2
card "bg → پسزمینه" as s3
card "وظائف → معلقها را ببینید" as s4
}
rectangle "مزایا" as advantages #SkyBlue {
card "هیچ از دست رفتن زمینه" as a1
card "بدون راهاندازی مجدد" as a2
card "یک ترمینال کافی است" as a3
}
problem -right-> solution : "راهحل بومی
یونیکس به مدت ۴۰ سال"
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
چرا fg کمارزشگذاری شده است؟
اکثر توسعه دهندگان معاصر کشف میکنند`fg`دیر، شاید هرگز. چند دلیل :
-
IDEها ترمینال را پنهان میکنند: VS Code یک ترمینال داخلی ارائه میدهد، اما تبهای多let`fg`بهنظر کمتر لازم
-
ابزارهای گرافیکی CLI را جایگزین میکنند: مدیران فایل، مانیتورهای سیستم، کلاینتهای گرافیکی Git
-
tmux و screen: این مولติپلکسورها همان مشکل را به شکل متفاوتی حل میکنند، اما`fg`سادهتر و همیشه در دسترس است
اما,`fg`است :
-
عالمی: موجود در همه شلهای POSIX (bash, zsh, fish…)
-
بدون وابستگی: لازم نیست tmux یا screen را نصب کنید
-
لحظهای: دو ضربات (
Ctrl+Z`سپس`fg) برای تعلیق و ادامه -
نگهدارنده زمینهوضعیت فرآیند سالم است
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
rectangle "چرا fg است
تقلیلقدر شده؟" as why #LightCoral {
card "IDE با ترمینال\nچند برگه" as w1
card "ابزارهای گرافیکی
که CLI را جایگزین میکنند" as w2
card "tmux/screen
مشکل را حل میکنند
به طور دیگر" as w3
}
rectangle "چرا fg بهتر\nاست؟" as superior #LightGreen {
card "عالمی : bash,
zsh, fish, sh..." as s1
card "بدون وابستگی:
بدون نصب" as s2
card "دو ضربه:\nCtrl+Z سپس fg" as s3
card "محیط حفظشده :\nبدون فقدان وضعیت" as s4
}
why -right-> superior : "سادهگی
همیشه برنده است"
@enduml
ذاكرة فنی: ال سیگنالها
برای کسانی که سوال دارند، این است:
| سیگنال | نام | ارسال شده توسط | اثر |
|---|---|---|---|
2 |
|
|
انقطاع — فرآیند را پایان میدهد |
3 |
|
|
خروج با core dump |
18 |
|
|
Stop تعاملی — فرآیند را متوقف کنید |
19 |
|
|
ادامه — فرآیند معلق را ادامه میدهد |
15 |
|
|
پایان تمیز |
9 |
|
|
پایانگیری اجباری (امکان interceptions نیست) |
جريان کامل :
@startuml skinparam backgroundColor #FEFEFE skinparam defaultFontName sans-serif participant "کاربر" as user participant "شل" as shell participant "فرآیند" 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
نتیجه
`fg`این یک نکته مبهم نیست — این مکانیزم اساسی شل یونیکس است که از دههٔ ۱۹۷۰ در دسترس بوده است. این که اکثر توسعهدهندگان آن را نادیده میگیرند، نشانهای از زمان ماست: IDEها و مولتیپلکسورها ما را از اصول پایه دور کردهاند.
اما وقتی که روی یک سرور SSH هستید، در یک ترمینال کمینه، یا صرفاً در حال استفاده`opencode`و که LLM به شدت در حال کار است—Ctrl+Z, fg, bg, `jobs`بهترین دوستان شما هستند
__ Ctrl+Z متوقف میشود, fg ادامه میدهد. این pause-play ترمینال است. </think>
منابع
-
man bash— بخش JOB CONTROL -
man signal— فهرست سیگنالهای POSIX