% Linux Installation and Getting Started    -*- TeX -*-
% job-control.tex
% Copyright (c) 1992, 1993 by Matt Welsh, Larry Greenfield and Karl Fogel
%
% This file is freely redistributable, but you must preserve this copyright 
% notice on all copies, and it must be distributed only as part of "Linux 
% Installation and Getting Started". This file's use is covered by
% the copyright for the entire document, in the file "copyright.tex".
%
% Copyright (c) 1998 by Specialized Systems Consultants Inc. 
% <ligs@ssc.com>

\section{Nadzor opravil}\label{sec-job-control}
%\markboth{Učbenik Linuxa}{Nadzor opravil}

\index{nadzor opravil|(}
\subsection{Opravila in procesi}
\label{sec-process}\label{sec-processes}

\index{ukazne lupine!nadzor opravil, ki ga ponujajo}
\textbf{Nadzor opravil} (angl.\ job control) je lastnost, ki jo
ponuja mnogo ukaznih lupin (vključno z \texttt{bash} in
\texttt{tcsh}), ki vam omogoča nadzor več tekočih ukazov ali
\textbf{opravil} naenkrat.  Preden se potopimo globlje, moramo
spregovoriti o \textbf{procesih}.

\index{proces!definicija}
\index{ps@\texttt{ps}}
\index{proces!ps za spisek@\texttt{ps} za spisek}
Vsakič, ko poženete program, začnete to, kar se imenuje proces.  Ukaz
\texttt{ps} izpiše spisek procesov, ki trenutno tečejo, kot je
prikazano tukaj:
\begin{tscreen}
/home/larry\$ \emph{ps}\\
\verb!  PID TT STAT  TIME COMMAND!\\
\verb!   24  3 S     0:03 (bash)!\\ 
\verb!  161  3 R     0:00 ps!\\
/home/larry\$
\end{tscreen}
\index{proces!ID!definicija}
Številka \texttt{PID} v prvem stolpcu je \textbf{identifikacijska
številka procesa}, unikatna številka, dodeljena vsakemu tekočemu
procesu.  Zadnji stolpec, \texttt{COMMAND}, je ime tekočega ukaza.
Tukaj gledamo le procesa, ki ju trenutno poganja sam Larry.  (Na
sistemu obstajajo tudi drugi tekoči procesi -- >>\texttt{ps aux}<< jih
vse izpiše.)  To sta \texttt{bash} (Larryjeva ukazna lupina) in sam
ukaz \texttt{ps}.  Kot vidite, teče \texttt{bash} vzporedno z ukazom
\texttt{ps}.  \texttt{bash} je izvedel ukaz \texttt{ps}, ko ga je
Larry vtipkal.  Ko \texttt{ps} preneha delovati (po izpisu tabele
procesov), se nadzor vrne procesu \texttt{bash}, ki izpiše pozornik,
pripravljen na naslednji ukaz.

\index{opravilo!definicija}
Tekoči proces se tudi imenuje \emph{opravilo} (angl.\ job).  Izraza
\emph{proces} in \emph{opravilo} sta zamenljiva.  Vendar se o procesu
navadno govori kot o >>opravilu<<, ko se uporablja v povezavi z
\textbf{nadzorom opravil} -- značilnosti ukazne lupine, da vam omogoča
preklapljanje med različnimi neodvisnimi opravili.

V večini primerov uporabniki poganjajo le eno opravilo hkrati --
katerikoli ukaz so pač zadnji vnesli v ukazno lupino.  Vendar pa z
uporabo nadzora opravil lahko hkrati poganjate več opravil in po
potrebi preklapljate med njimi.

Kako je lahko to uporabno?  Denimo, da urejate tekstovno datoteko in
bi radi prekinili vaše urejanje in naredili nekaj drugega.  Z nadzorom
opravil lahko začasno odložite urejevalnik, se vrnete v pozornik
ukazne lupine in začnete delati na nečem drugem.  Ko ste opravili,
lahko preklopite nazaj v urejevalnik in ste tam, kjer ste bili, kot da
sploh ne bi zapustili urejevalnika.  Obstaja mnogo praktičnih uporab
nadzora opravil.

\subsection{Ospredje in ozadje}

\index{proces!ospredje}
\index{proces!ozadje}
\index{opravilo!ospredje}
\index{opravilo!ozadje}
\index{proces v ospredju}
\index{proces v ozadju}
Opravila so lahko v \textbf{ospredju} (angl.\ foreground) ali v
\textbf{ozadju} (angl.\ background).  Hkrati je lahko v ospredju le
eno opravilo.  Opravilo v ospredju je opravilo, s katerim vzajemno
delujete -- sprejema vhod s tipkovnice in pošilja izhod na zaslon
(razen seveda, če ste preusmerili vhod ali izhod, kot je opisano od
strani~\pageref{redirection} naprej).  Po drugi strani, opravila v
ozadju ne sprejemajo vhoda s terminala -- v splošnem tečejo tiho,
brez potrebe po interakciji.

Nekatera opravila potrebujejo dolgo časa, da se končajo, in ne počnejo
ničesar zanimivega, dokler tečejo.  Prevajanje programov je takšno
opravilo kot tudi komprimiranje velike datoteke.  Ni razloga, da bi
posedali naokrog in se dolgočasili, dokler ta opravila ne končajo
svojih nalog; preprosto jih poženite v ozadju.  Dokler opravila tečejo
v ozadju, lahko po mili volji poganjate druge programe.

\index{opravilo!odložitev}
Opravila so lahko \textbf{odložena}.  Odloženo opravilo (angl.\
suspended job) je opravilo, ki je le začasno ustavljeno.  Ko odložite
opravilo, mu lahko poveste, naj nadaljuje v ospredju ali ozadju, če je
to potrebno.  Nadaljevanje odloženega opravila nikakor ne spremeni
stanja opravila -- opravilo nadaljuje s tekom tam, kjer je ostalo.

\index{proces!prekinitev}
\index{opravilo!prekinitev}
Odložitev opravila ni enaka prekinitvi opravila.  Ko
\textbf{prekinete} (angl.\ interrupt) tekoči proces (s pritiskom
prekinitvene tipke, ki je navadno \key{Ctrl-C})\footnote{Prekinitveno
tipko lahko nastavite z ukazom \texttt{stty}.}, se proces ubije, za
vedno.  Ko se opravilo ubije, ni upanja za njegovo nadaljevanje.
Ponovno boste morali pognati ukaz.  Nekateri programi pa prestrežejo
prekinitev tako, da pritisk \key{Ctrl-C} ne ubije opravila takoj.  To
je zato, da se programu omogoči vse potrebne čistilne operacije,
preden se konča.  Pravzaprav vam nekateri programi sploh ne
dovoljujejo, da jih ubijete s prekinitvijo.

\subsection{Spravljanje v ozadje in ubijanje opravil}

Začnimo s preprostim zgledom.  Ukaz \texttt{yes} je navidezno
neuporaben ukaz, ki pošilja neskončen tok črk \texttt{y} na standardni
izhod.  (To je celo uporabno.  Če s cevjo povežete izhod ukaza
\texttt{yes} do drugega ukaza, ki vprašuje niz vprašanj tipa da/ne
(angl.\ \textbf{y}es/no), bo tok črk \texttt{y} potrdil vsa
vprašanja.)

Preizkusite:
\begin{tscreen}
/home/larry\$ \emph{yes} \\
y \\
y \\
y \\
y \\
y
\end{tscreen}
\index{proces!ubijanje}
\index{proces!prekinitev}
\index{opravilo!ubijanje}
\index{opravilo!prekinitev}
Izpis ipsilonov se bo nadaljeval \emph{ad infinitum}.  Proces lahko
ubijete s pritiskom na prekinitveno tipko, ki je navadno \key{Ctrl-C}.

Da nam ne bo treba spet shajati z mučnim tokom ipsilonov, preusmerimo
standardni izhod programa \texttt{yes} na napravo \texttt{/dev/null}.
Kot se spomnite, \texttt{/dev/null} deluje kot >>črna luknja<< za
podatke.  Vsi podatki, poslani vanjo, izginejo.  To je zelo učinkovita
metoda za utišanje sicer zgovornega programa.
\begin{tscreen}
/home/larry\$ \emph{yes $>$ /dev/null}
\end{tscreen}
Ah, veliko bolje.  Nič se ne izpiše, a pozornik ukazne lupine se ne
prikaže nazaj.  To je zato, ker \texttt{yes} še vedno teče, in pošilja
te nesmiselne ipsilone na \texttt{/dev/null}.  Spet za ubijanje
opravila pritisnite prekinitveno tipko.

Denimo, da želite, da ukaz \texttt{yes} nadaljuje s tekom, a želite
dobiti pozornik ukazne lupine nazaj, da boste lahko delali na drugih
zadevah.  Ukaz \texttt{yes} lahko postavite v ozadje, in mu s tem
omogočite tek brez potrebe za vzajemno delovanje.

\index{opravilo!ozadje}
\index{ozadje!spravljanje opravil vanj}
En način za postavljanje procesa v ozadje je, da pripnemo znak
>>\texttt{\&}<< na konec ukaza.
\begin{tscreen}
/home/larry\$ \emph{yes $>$ /dev/null \&} \\
\verb+[1] 164+ \\
/home/larry\$
\end{tscreen}
Kot lahko vidite, se je pozornik ukazne lupine vrnil.  A kaj pomeni ta
>>\verb+[1] 164+<<?  In ali ukaz \texttt{yes} zares teče?

Oznaka >>\verb+[1]+<< predstavlja \textbf{številko opravila} za
trenutni proces \texttt{yes}.  Ukazna lupina dodeli številko opravila
vsakemu tekočemu opravilu.  Ker je \texttt{yes} edino opravilo, ki
teče, mu je dodeljena številka opravila \texttt{1}.  Oznaka
>>\texttt{164}<< je ID procesa ali PID, številka, ki jo opravilu
dodeli sistem.  Katerokoli od teh dveh številk lahko uporabite za
sklicevanje na opravilo, kot boste videli pozneje.

\index{jobs@\texttt{jobs}}
Zdaj vam v ozadju teče proces \texttt{yes}, ki nenehno pošilja tok črk
\texttt{y} na \texttt{/dev/null}.  Za preverbo statusa tega procesa
uporabite notranji lupinski ukaz \texttt{jobs}.
\begin{tscreen}
/home/larry\$ \emph{jobs} \\
\verb-[1]+  Running                 yes >/dev/null  &- \\
/home/larry\$
\end{tscreen}
Tukaj je, dovolj prepričljivo.  Uporabili bi lahko tudi ukaz
\texttt{ps}, opisan zgoraj, za preverbo statusa opravila.

\index{kill@\texttt{kill}}
\index{proces!v ozadju!ubijanje}
\index{opravilo!v ozadju!ubijanje}
Za pokončanje opravila uporabite ukaz \texttt{kill}.  Ta ukaz vzame
za svoj argument bodisi številko opravila, bodisi številko ID procesa.
To je bilo opravilo številka 1, zato uporaba ukaza
\begin{tscreen}
/home/larry\$ \emph{kill \%1}
\end{tscreen}
pobije opravilo.  Ko se sklicujete na opravilo s številko opravila,
morate pred številko dodati znak za odstotek (>>\texttt{\%}<<).

Zdaj ko ste pobili opravilo, spet uporabite ukaz \texttt{jobs}
za njegovo preverbo:
\begin{tscreen}
/home/larry\$ \emph{jobs}\\
\verb![1]+  Terminated              yes >/dev/null!
/home/larry\$
\end{tscreen}
Opravilo je zares mrtvo, in če spet uporabite ukaz \texttt{jobs},
se ne bo izpisalo nič.

Opravilo lahko pobijete tudi z uporabo številke ID procesa (PID), ki
je prikazana poleg ID opravila, ko zaženete opravilo.  V našem primeru
je ID procesa 164, zato je ukaz
\begin{tscreen}
/home/larry\$ \emph{kill 164}
\end{tscreen}
ekvivalenten ukazu
\begin{tscreen}
/home/larry\$ \emph{kill \%1}
\end{tscreen}
Kadar se sklicujete na opravilo z njegovo številko ID procesa,
navedete številko PID brez znaka za odstotek.

\subsection{Ustavljanje in ponovno zaganjanje opravil}
\index{opravila!ustavljanje}
Obstaja tudi drug način za postavitev opravila v ozadje.  Opravilo
lahko zaženete kot običajno (v ospredju), \textbf{ustavite} opravilo
in ga ponovno zaženete v ozadju.

Najprej, poženite proces \texttt{yes} v ospredju, kot ste storili
že prej:
\begin{tscreen}
/home/larry\$ \emph{yes $>$ /dev/null}
\end{tscreen}
Spet, ker \texttt{yes} teče v ospredju, ne bi smeli dobiti nazaj
pozornika.

Zdaj, namesto da prekinete opravilo s \key{Ctrl-C}, \textbf{odložite}
opravilo.  Odložitev opravila ne pobije: le začasno ustavi opravilo,
dokler ga ponovno ne poženete.  Za to pritisnite tipko za odložitev,
ki je navadno \key{Ctrl-Z}.
\begin{tscreen}
/home/larry\$ \emph{yes $>$ /dev/null} \\
\key{Ctrl-Z} \\
\verb-[1]+  Stopped                 yes >/dev/null- \\
/home/larry\$
\end{tscreen}
Ko je opravilo odloženo, preprosto ne teče.  Za opravilo se ne
uporablja nič procesorskega časa.  Vendar lahko ponovno zaženete
opravilo, kar povzroči, da opravilo spet teče, kot da se ni nikoli nič
zgodilo.  Opravilo bo nadaljevalo s tekom tam, kjer je končalo.

\index{fg@\texttt{fg}}
\index{opravilo!ponovni zagon}
Za ponovni zagon opravila v ospredju, uporabite ukaz
\texttt{fg} (iz angl.\ >>foreground<<, ospredje). 
\begin{tscreen}
/home/larry\$ \emph{fg} \\
yes >/dev/null 
\end{tscreen}
\index{opravilo!ozadje}
\index{bg@\texttt{bg}}
Ukazna lupina spet izpiše ime ukaza, tako da se zavedate, katero
opravilo ste pravkar postavili v ospredje.  Spet ustavite opravilo s
\key{Ctrl-Z}.  Tokrat uporabite \texttt{bg} in postavite opravilo v
ozadje.  To povzroča, da ukaz teče, kot da bi ga zagnali z ukazom z
>>\texttt{\&}<<, kot smo videli v zadnjem razdelku.
\begin{tscreen}
/home/larry\$ \emph{bg} \\
\verb-[1]+- yes >/dev/null  \& \\
/home/larry\$ 
\end{tscreen}
In spet imate nazaj svoj pozornik.  Ukaz \texttt{jobs} naj bi poročal,
da \texttt{yes} zares teče, in opravilo lahko pobijete z ukazom
\texttt{kill}, kot smo že naredili.

Kako lahko ponovno ustavite to opravilo?  Uporaba \key{Ctrl-Z} ne bo
delovala, saj je opravilo v ozadju.  Odgovor je, da postavite opravilo
v ospredje s \texttt{fg} in ga potem ustavite.  Kot se izkaže, lahko
uporabljate \texttt{fg} na ustavljenih opravilih ali opravilih v
ozadju.

Obstaja velika razlika med opravilom v ozadju in opravilom, ki je
ustavljeno.  Ustavljeno opravilo ne teče -- ne uporablja procesorskega
časa in ne opravlja nobenega dela (opravilo še vedno zaseda sistemski
pomnilnik, čeprav je morda izmenjano na disk).  Opravilo v ozadju teče
in uporablja pomnilnik, kot tudi zaključuje neko nalogo, medtem ko vi
delate kaj drugega.

Včasih opravilo v ozadju poskuša na vašem terminalu prikazati tekst,
kar je lahko nadležno, če poskušate delati kaj drugega.  Na primer, če
ste uporabili ukaz
\begin{tscreen}
/home/larry\$ \emph{yes \&}
\end{tscreen}
brez preusmeritve \texttt{stdout} na \texttt{/dev/null}, bo na zaslonu
prikazovan tok črk \texttt{y}, ne da bi ga lahko prekinili.  (Za
prekinitev opravil v ozadju ne morete uporabiti \key{Ctrl-C}.)  Za
ustavitev neskončnih ipsilonov uporabite ukaz \texttt{fg}, da
prenesete opravilo v ospredje, potem uporabite \key{Ctrl-C}, da ga
pobijete.

Še eno sporočilo.  Ukaza \texttt{fg} in \texttt{bg} navadno
prizadeneta le opravilo, ki je bilo zadnje ustavljeno (prikazano z
znakom >>\texttt{+}<< poleg številke opravila, ko uporabite ukaz
\texttt{jobs}).  Če hkrati poganjate več opravil, lahko postavljate
opravila v ospredje ali ozadje tako, da podate številko opravila kot
argument ukazu \texttt{fg} ali \texttt{bg}, kot v primeru
\begin{tscreen}
/home/larry\$ \emph{fg \%2}
\end{tscreen}
(za postavitev opravila številka 2 v ospredje), ali
\begin{tscreen}
/home/larry\$ \emph{bg \%3}
\end{tscreen}
(za postavitev opravila številka 3 v ozadje).  Z ukazoma \texttt{fg}
in \texttt{bg} ne morete uporabljati številk ID procesov (PID).

Nadalje, uporaba same številke opravila, kot v
\begin{tscreen}
/home/larry\$ \emph{\%2}
\end{tscreen}
je ekvivalentna uporabi
\begin{tscreen}
/home/larry\$ \emph{fg \%2}
\end{tscreen}

Spomnite se le, da je uporaba nadzora opravil lastnost ukazne lupine.
Ukazi \texttt{fg}, \texttt{bg} in \texttt{jobs} so notranji ukazi
ukazne lupine.  Če iz nekega razloga uporabljate lupino, ki ne podpira
nadzora opravil, ne pričakujte, da bodo ti ukazi dostopni.

Poleg tega obstajajo nekateri vidiki nadzora opravil, ki se
razlikujejo med ukaznima lupinama \texttt{bash} in \texttt{tcsh}.
Nekatere ukazne lupine sploh ne ponujajo nadzora opravil -- večina
ukaznih lupin, dostopnih za Linux, pa ga ponuja.

\index{nadzor opravil|)}
