Topik ini membahas kendali pekerjaan (job control), yaitu kemampuan shell mengatur beberapa perintah pada satu terminal: melihat daftarnya dengan jobs, menahan pekerjaan dengan Ctrl-Z, melanjutkannya di latar belakang atau latar depan dengan bg dan fg, serta membuatnya bertahan dari penutupan terminal dengan nohup. Setelah membacanya, perintah panjang yang terlanjur berjalan tidak perlu dihentikan paksa hanya karena terminalnya dibutuhkan untuk pekerjaan lain.
Pekerjaan dan daftar jobs#
Setiap perintah yang dilahirkan shell dari satu baris disebut pekerjaan (job). Shell memberi nomor pekerjaan mulai dari satu, menandai pekerjaan terbaru dengan tanda + dan pekerjaan sebelumnya dengan tanda -, lalu mencatat keadaannya. Daftar itu ditampilkan oleh jobs, dan contoh berikut merekam dua pekerjaan latar belakang sekaligus.
sleep 300 &
P1=$!
sleep 301 &
P2=$!
jobs
kill "$P1"
wait "$P1" 2>/dev/null
kill "$P2"
wait "$P2" 2>/dev/null
echo "kedua pekerjaan dihentikan"[1]- Running sleep 300 &
[2]+ Running sleep 301 &
kedua pekerjaan dihentikanSetiap baris memuat nomor pekerjaan dalam kurung siku, tanda + atau -, keadaan pekerjaan, dan perintah pembentuknya yang diakhiri &. Keadaan Running berarti prosesnya sedang berjalan di latar belakang. Pada shell interaktif, daftar yang sama juga menampilkan keadaan lain seperti Done untuk pekerjaan yang selesai dan Stopped untuk pekerjaan yang sedang ditahan. Nomor pekerjaan ini menjadi sasaran perintah bg dan fg dalam bentuk seperti %1.
Pekerjaan dan proses berhubungan erat tetapi tidak identik. Satu pekerjaan berpadanan dengan satu proses untuk perintah sederhana, sedangkan baris perintah yang memakai pipe membentuk beberapa proses dalam satu pekerjaan yang sama. Shell mencatat hubungan itu sendiri, sedangkan ps hanya mengenal nomor proses, sehingga nomor %1 tidak berarti apa pun di luar shell yang mencatatnya. Opsi -l pada jobs menambahkan nomor PID setiap anggota pekerjaan, yang menjembatani keduanya ketika sinyal perlu dikirim langsung kepada prosesnya.
Menahan dan melanjutkan pekerjaan#
Tekanan Ctrl-Z mengirim sinyal SIGTSTP kepada proses latar depan, dan proses itu berpindah ke keadaan ditahan. Proses yang ditahan tidak memakai waktu prosesor, tetapi memorinya dan seluruh keadaannya tetap utuh, sehingga dapat dilanjutkan persis dari titik berhentinya. Perintah bg melanjutkan pekerjaan itu di latar belakang, sedangkan fg membawanya kembali ke latar depan, dan keduanya bekerja dengan mengirim sinyal SIGCONT.
Pasangan sinyal itu dapat diamati langsung pada kolom STAT milik ps, yang berubah dari S menjadi T ketika proses ditahan.
sleep 300 &
PID=$!
# jeda singkat agar proses anak selesai mengganti citranya
sleep 0.3
# kolom PID dan PPID ditandai N karena nilainya berbeda di setiap sesi
ps -o pid,ppid,stat,cmd -p "$PID" | awk 'NR>1{$1="N"; $2="N"} {$1=$1; print}'
# menahan proses, setara dengan menekan Ctrl-Z
kill -STOP "$PID"
ps -o pid,ppid,stat,cmd -p "$PID" | awk 'NR>1{$1="N"; $2="N"} {$1=$1; print}'
# melanjutkan proses, setara dengan bg atau fg
kill -CONT "$PID"
sleep 0.2
ps -o pid,ppid,stat,cmd -p "$PID" | awk 'NR>1{$1="N"; $2="N"} {$1=$1; print}'
kill "$PID"
wait "$PID" 2>/dev/null
echo "proses dihentikan dengan status $?"PID PPID STAT CMD
N N S sleep 300
PID PPID STAT CMD
N N T sleep 300
PID PPID STAT CMD
N N S sleep 300
proses dihentikan dengan status 143Huruf T pada listing kedua adalah keadaan yang dilihat jobs sebagai Stopped pada terminal interaktif. Setelah kill -CONT dikirim, keadaannya kembali ke S dan proses melanjutkan hitungan mundurnya tanpa kehilangan apa pun. Pemetaan lengkapnya dirangkum pada tabel berikut.
| Tindakan pada terminal | Sinyal yang bekerja | Akibat |
|---|---|---|
| Ctrl-Z | SIGTSTP | Proses latar depan ditahan, jobs menampilkan Stopped |
bg %1 | SIGCONT | Pekerjaan 1 dilanjutkan di latar belakang |
fg %1 | SIGCONT | Pekerjaan 1 dilanjutkan di latar depan |
kill -STOP PID | SIGSTOP | Proses ditahan, terlihat sebagai T pada ps |
kill -CONT PID | SIGCONT | Proses dilanjutkan |
bg dan fg pada shell interaktif#
Pemakaian bg dan fg baru terasa pada shell interaktif yang memiliki terminal, karena kendali pekerjaan dikelola shell bersama terminal. Alur kerja yang lazim: perintah panjang sedang berjalan di latar depan ketika terminal dibutuhkan untuk hal lain. Ctrl-Z ditekan sehingga prompt kembali dan jobs menampilkan pekerjaan dalam keadaan Stopped. Perintah bg %1 kemudian melanjutkan pekerjaan di latar belakang tanpa menghalangi prompt. Ketika hasil pekerjaan dibutuhkan, fg %1 membawanya kembali ke latar depan sampai benar-benar selesai.
Penomoran pekerjaan mengikuti urutan pelahirkan dalam satu sesi, dan tanda %1 boleh disingkat menjadi %+ untuk pekerjaan terbaru atau %- untuk pekerjaan sebelumnya. Pada skrip dan sesi tanpa terminal, kedua perintah ini melaporkan pesan error no job control karena shell semacam itu tidak menyalakan kendali pekerjaan, sehingga contoh pada halaman ini memakai pasangan sinyalnya secara langsung. Untuk pekerjaan yang ditahan, bg dan fg menjadi satu-satunya cara yang tepat untuk melanjutkan, karena SIGCONT membangunkan proses tanpa memutus apa pun.
nohup dan pekerjaan yang bertahan#
Ketika sesi terminal ditutup, shell mengirim SIGHUP kepada pekerjaan-pekerjaannya, dan pekerjaan biasa ikut berakhir. Perintah nohup menyiapkan pekerjaan agar sinyal itu diabaikan, sehingga prosesnya bertahan setelah terminal ditutup, dan keluaran standarnya dialihkan ke berkas nohup.out apabila masih menempel ke terminal. Contoh berikut membandingkan pekerjaan dengan dan tanpa nohup ketika SIGHUP dikirim secara eksplisit.
mkdir -p /tmp/kerja-kendali-pekerjaan
cd /tmp/kerja-kendali-pekerjaan
nohup sleep 300 > catatan.txt 2>&1 &
PID=$!
sleep 0.3
# SIGHUP yang biasanya menutup pekerjaan tidak berdampak
kill -HUP "$PID"
sleep 0.2
ps -o stat=,cmd= -p "$PID"
test -f catatan.txt && echo "catatan.txt dibuat"
kill -9 "$PID"
wait "$PID" 2>/dev/null
echo "proses nohup dihentikan"S sleep 300
catatan.txt dibuat
proses nohup dihentikanProses yang dilindungi nohup tetap terdaftar pada ps dengan keadaan S setelah menerima SIGHUP, dan berkas catatan.txt terbentuk karena pengalihan keluarannya dinyatakan secara eksplisit. Pembandingnya memakai proses biasa dengan sinyal yang sama.
cd /tmp/kerja-kendali-pekerjaan
sleep 300 &
PID=$!
sleep 0.3
kill -HUP "$PID"
wait "$PID" 2>/dev/null
echo "tanpa nohup, status keluar: $?"tanpa nohup, status keluar: 129Tanpa perlindungan, proses yang sama berakhir oleh SIGHUP dengan status keluar 129, yaitu 128 ditambah nomor sinyal 1. Perbedaan keduanya adalah inti nohup: sinyalnya sama, tetapi sikap prosesnya berbeda karena pekerjaan yang dilindungi nohup telah menetapkan SIGHUP untuk diabaikan.
Pengalihan berkas keluaran pada nohup layak diperhatikan karena ada dua kemungkinannya. Apabila keluaran standar pekerjaan masih menempel ke terminal, nohup mengarahkannya sendiri ke berkas nohup.out di direktori kerja, sedangkan pengalihan eksplisit seperti > catatan.txt 2>&1 pada contoh menggantikan perilaku itu. Pekerjaan yang menghasilkan keluaran besar tanpa pengalihan apa pun membuat isi nohup.out membesar tanpa terkendali, sehingga arah keluarannya sebaiknya ditentukan sejak awal. Untuk kebutuhan yang lebih lama dari satu sesi, layanan systemd pada bagian akhir jalur menyediakan mekanisme yang lebih rapi.
Kesalahan umum#
- Mengira akhiran
&membuat pekerjaan kebal penutupan terminal. Tanda itu hanya memindahkan pekerjaan ke latar belakang, sedangkan SIGHUP dari sesi yang ditutup tetap mengakhirinya. Gunakannohupuntuk pekerjaan yang harus bertahan. - Memanggil
bgataufgdari dalam skrip. Shell non-interaktif melaporkan pesan errorno job control, dan perintah semacam ini memang hanya berarti pada sesi yang memiliki terminal. - Mengirim SIGTERM kepada pekerjaan yang sedang ditahan. Proses dalam keadaan
Tmenunda penanganan sinyal sampai dilanjutkan, sehingga sinyal itu belum berdampak apa pun. Lanjutkan dulu dengankill -CONTatau akhiri langsung dengankill -9. - Menahan pekerjaan lalu melupakannya. Pekerjaan dalam keadaan
Stoppedtetap memegang memorinya, dan daftarjobsyang menumpuk adalah tanda pekerjaan yang perlu dilanjutkan atau dihentikan.
Ringkasan#
- Shell memberi nomor pada setiap pekerjaan dan
jobsmenampilkannya beserta keadaanRunning,Done, atauStopped. - Ctrl-Z menahan proses latar depan melalui SIGTSTP, dan pasangan
kill -STOPdengankill -CONTmemberi keadaanTdanSyang sama pada kolom STAT milikps. bg %ndanfg %nmelanjutkan pekerjaan dengan SIGCONT di latar belakang atau latar depan, dan keduanya hanya aktif pada shell interaktif yang memiliki terminal.nohupmenjadikan SIGHUP diabaikan sehingga pekerjaan bertahan dari penutupan terminal, sementara pekerjaan biasa berakhir dengan status 129.
Referensi#
- bash(1) — Linux man-pages project — Bagian job control yang menjelaskan pekerjaan, Ctrl-Z, jobs, bg, dan fg.
- nohup(1) — Ubuntu manpages — Cara nohup mengabaikan SIGHUP dan mengalihkan keluaran ke nohup.out.
- signal(7) — Linux man-pages project — Nomor dan perilaku bawaan SIGTSTP, SIGSTOP, SIGCONT, dan SIGHUP.