1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
|
\chapter{Procesbeheer}
\label{process}
In dit hoofdstuk zullen we leren hoe processen zowel interactief als
niet interactief te besturen. Het is zeer belangrijk de besturing over
je systeem te onderhouden en lastige processen te beheren.
\section{Voorgrond- en achtergrondprocessen aanmaken}
\term{Procesbeheer} refereert naar de mogelijkheid processen zowel
in de \term{voorgrond} als \term{achtergrond} van de shell te besturen.
Een \term{voorgrond} proces is een proces dat interactief in je shell
draait, en dit zijn de meeste processen die we tot dusverre hebben
besproken. Je kunt een \term{voorgrond} proces onderbreken met behulp
van de toetsencombinatie \program{Ctrl-Z}
(uitgesproken als ``control z'', druk de \lt{}Ctrl\gt\ en \term{z} toets
tegelijkertijd in). Om dat proces nu weer terug in de \term{voorgrond}
te plaatsen, gebruik je de (bash) opdracht \program{fg}.
Als contrast is een \term{achtergrond} proces een proces waarbij geen
directe interactie met je shell is. Het blijft op zichzelf en draait in stilte.
Om in plaats daarvan een proces in de achtergrond te plaatsen gebruik je
de interne opdracht \program{bg}.
Vanuit de shell gezien, hebben alle processen een
\term{job} nummer. Vanuit het systeem gezien, hebben alle
processen een \term{proces ID}, vaak een \term{PID} genoemd (zie de
opdracht \program{ps}).
Om echt een van deze processen af te vangen, moeten we naar een opdracht
op zoek gaan welke langer duurt dan even (zoals \program{date}).
Laten we met de opdracht \program{xterm} werken waarmee een X-terminal
venster wordt gecreeerd:
\begin{alltt}
\bash{xterm} # Start een nieuwe \program{xterm}
\unshell{Ctrl-Z} # Je drukte \term{Ctrl-Z} in en stelde het uit!
\unshell{[1]+ Stopped xterm}
\bash{fg} # Herstartte het met \program{fg}
\unshell{xterm}
\unshell{Ctrl-Z} # Je stelde het weer uit.. goed..
\unshell{[1]+ Stopped xterm}
\bash{jobs} # Zoek naar het nummer van de job.
\unshell{[3]+ Stopped xterm}
\bash{}
\bash{bg \%3} # Plaats xterm in de achtergrond.
\unshell{[3] xterm &}
\bash{}
\end{alltt}
Als het goed is heb je nu een \program{xterm} die normaal functioneert.
De laatst getoonde [3] geeft aan dat dit \term{Job Number} 3 is.
Je kunt dat nummer gebruiken om ernaar te refereren met behulp van
\program{fg} als in
\begin{alltt}
\bash{fg \%3} # plaats het op de voorgrond met \\program{fg}
\unshell{Ctrl-Z} # Stel de uitvoering ervan weer uit.
\unshell{[3]+ Stopped xterm}
\bash{bg \%3} # Plaats het met \\program{bg} in de achtergrond
[3] xterm &
\bash{jobs}
[1] Running xterm -cr red -ms >&
[2] Running xclock
[3] Running xterm
\bash{kill -9 %3}
\bash{jobs}
[1] Running xterm -cr red -ms >&
[2] Running xclock
[3]- Terminated xterm
\end{alltt}
Het programma \program{jobs} toont alle jobs en het bijbehorende nummer
en de status. De opdracht \program{kill -9 \%N} verwijdert jobnummer $N$.
De vlag (-9) is nodig om een ``echte kill'' te forceren, wat soms nodig is.
Het ampersand symbool (\&) is wat je zou gebruiken om een opdracht direct
in de achtergrond te plaatsen, zoals in \program{xterm \&}.
Wees voorzichtig, want een aantal opdrachten willen fouten wegschrijven naar
standaarduitvoer \term{stdout} en dat zou vreemde resultaten op je scherm
op kunnen leveren. Om dit te voorkomen, kun je \term{stdout} omleiden naar
\file{/dev/null} (of een logbestand) EN het in een keer in de achtergrond
kunnen plaatsen:
\begin{alltt}
\bash{xterm \gt\& /dev/null \&}
of
\bash{xterm \gt\& /tmp/xterm-log \&}
\end{alltt}
Dit is aan te raden als je van plan bent de opdrachten in een script te
plaatsen, omdat de \term{stdout} die nergens heen kan, je script kan stoppen.
Ervaring heeft aangetoond van te voren altijd gebruik te maken van
/dev/null.
\section{Processen met \program{\Large kill} verwijderen}
Nu zullen we procesnummers met de opdracht \program{ps} laten zien.
\normalsize
\begin{Verbatim}[fontfamily=tt,frame=single,commandchars=\\\{\}]
\bash{ps}
PID TTY TIME CMD
683 ttyp1 00:00:00 bash
31666 ttyp1 00:00:00 xterm
32716 ttyp1 00:00:00 xclock
698 ttyp1 00:00:00 ps
\bash{ps -agl} # Haal een uitgebreide lijst op met \program{ps}
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
000 501 683 672 13 0 2220 804 rt_sig S ttyp1 0:01 [bash]
000 501 31666 683 0 0 3012 1900 wait4 S ttyp1 0:00 xterm -cr r
000 501 32716 683 0 0 2572 1304 do_sel S ttyp1 0:00 xclock
000 501 464 683 0 0 8540 5936 do_sel S ttyp1 0:03 /home/carin
\bash{top}
42 processes: 40 sleeping, 2 running, 0 zombie, 0 stopped
CPU states: 2.3% user, 0.7% system, 0.0% nice, 96.8% idle
Mem: 63484K av, 52328K used, 11156K free, 18020K shrd, 2896K buff
Swap: 220316K av, 4964K used, 215352K free 28804K cached
PID USER PRI NI SIZE RSS SHARE STAT LIB %CPU %MEM TIME COMMAND
664 root 18 0 14824 14M 1540 R 0 1.1 22.7 18:21 X
31797 carinhas 9 0 7060 7060 3276 S 0 0.0 11.1 0:16 xemacs
464 carinhas 0 0 6020 6020 3596 S 0 0.0 9.4 0:03 netscapex
31666 carinhas 0 0 1900 1900 1440 S 0 0.0 2.9 0:00 xterm
32716 carinhas 0 0 1304 1304 1096 S 0 0.0 2.0 0:00 xclock
587 carinhas 0 0 1104 1104 728 S 0 0.0 1.7 0:00 bash
... <Shift-M> Sorted by memory usage....
Ctrl-C <quit>
\end{Verbatim}
\large
Ik heb nu een afvallig proces met de naam \program{xclock} opgezocht wat volgens
het \program{top} utility veel te veel geheugen verbruikt. Je wilt dit
proces verwijderen door het uitvoeren van
\begin{alltt}
\bash{kill -9 32716}
\bash{}
[3] Terminated xclock
\end{alltt}
Bestudeer voor de LPI-examens ook de man pages van \program{pstree} en
\term{proc}.
Hierna komt een verkorte manual page van \program{kill}, maar denk erom dat
de meeste shells een eigen ingebouwde versie hebben van \program{kill}.
\newpage
\normalsize
\begin{alltt}
\hrulefill
KILL(1) Linux Programmer's Manual KILL(1)
NAME
kill - terminate a process
SYNOPSIS
\command{kill}\option{ [ -s signal ] \%job \pipe{} pid ...}
\command{kill} \option{ -l [ signal ]}
OPTIONS
pid .. Specify the list of processes.
-s Specify the signal name or number to send.
-l Print a list of signal names. See \term{signal(7)}
\hrulefill
\end{alltt}
\vspace{-10truept}
\large
Hier is de relevante en verkorte man sectie van signal(7):
\normalsize
\vspace{-19truept}
\begin{alltt}
\hrulefill
SIGNAL(7) Linux Programmer's Manual SIGNAL(7)
NAME signal - list of available signals
Signal Value Action Comment
----------------------------------------------------------
SIGHUP 1 A Hangup detected on controlling terminal
SIGINT 2 A Interrupt from keyboard
SIGQUIT 3 A Quit from keyboard
SIGILL 4 A Illegal Instruction
SIGABRT 6 C Abort signal from abort(3)
SIGFPE 8 C Floating point exception
SIGKILL 9 AEF Kill signal
SIGSEGV 11 C Invalid memory reference
SIGPIPE 13 A Broken pipe: write to pipe with no readers
SIGALRM 14 A Timer signal from alarm(2)
SIGTERM 15 A Termination signal
SIGUSR1 30,10,16 A User-defined signal 1
SIGUSR2 31,12,17 A User-defined signal 2
SIGCHLD 20,17,18 B Child stopped or terminated
SIGCONT 19,18,25 Continue if stopped
SIGSTOP 17,19,23 DEF Stop process
SIGTSTP 18,20,24 D Stop typed at tty
SIGTTIN 21,21,26 D tty input for background process
SIGTTOU 22,22,27 D tty output for background process
The letters in the "Action" column have the following meanings:
A Default action is to terminate the process.
B Default action is to ignore the signal.
C Default action is to dump core.
D Default action is to stop the process.
E Signal cannot be caught.
F Signal cannot be ignored.
G Not a POSIX.1 conformant signal.
\hrulefill
\end{alltt}
\large
\newpage
\section{Beheren van procesprioriteiten}
Onder Linux en Unix hebben alle processen een belangrijke factor genaamd
de \term{prioriteit}. De \term{prioriteit} vertelt de systeem \term{kernel}
hoe vaak service te verlenen aan dat proces. Uiteraard zijn een aantal
processen veel kritischer voor het systeem dan anderen.
Toegang tot de hardware is veel belangrijker dan email. Hoe kleiner de waarde
van de prioriteit hoe meer belang aan het proces is gegeven.
Prioriteitswaarden vari\"eren van -20 tot 20, waar -20
de hoogste prioriteit is en 20 de laagste.
Je kunt de prioriteit van je processen zien door het lezen van de kolom
\term{PRI} in de opdracht \program{ps -xl}:
{\normalsize
\begin{alltt}
\bash{ps -xl}
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
000 501 617 612 0 0 2032 504 do_sel S ? 0:03 fvwm
000 501 622 617 0 0 3144 872 do_sel S ? 0:01 xterm -cr r
....etc....
\end{alltt}
}
Er zijn twee belangrijke tools voor het manipuleren van procesprioriteiten,
\program{nice} en \program{renice}. \program{nice} laat je de prioriteit
voor een opdracht aanvankelijk opgeven, en \program{renice} geeft je de
mogelijkheid de prioriteit te wijzigen nadat het proces is gestart.
Hier is een oefening voor je:
{\normalsize
\begin{alltt}
\bash{man nice}
----------------------------------------------------------------
NICE(1) NICE(1)
nice - run a program with modified scheduling priority
SYNOPSIS
\command{nice} \option{ -n priority command [arguments]}
----------------------------------------------------------------
\end{alltt}
}
\subsection{Oefeningen}
{\normalsize
\begin{alltt}
\bash{xclock -rv}
\bash{nice -10 xclock -rv}
\bash{/bin/nice -n 10 xclock -rv} # Hetzelfde als boven
\bash{ps -xl}
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
000 501 617 612 0 0 2032 504 do_sel S ? 0:03 fvwm
000 501 622 617 0 0 3144 872 do_sel S ? 0:01 xterm -cr r
000 501 2855 1321 8 4 2568 1300 do_sel SN ttyp2 0:00 xclock
\bash{renice 20 2855} # Renice de xclock job, ok?
\unshell{2855: old priority 4, new priority 20}# Don't worry if numbers don't jive.
\bash{renice 5 2855} # renice naar LOWER # ?
{\bf renice: 2855: setpriority: Permission denied} # Kan niet, alleen HOGER # is
toegestaan.
\bash{ps -xl}
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
000 501 617 612 0 0 2032 504 do_sel S ? 0:03 fvwm
000 501 622 617 0 0 3144 872 do_sel S ? 0:01 xterm -cr r
000 501 2937 1321 19 19 2568 1300 do_sel SN ttyp2 0:00 xclock
\end{alltt}
}
Je kunt renice alleen met een hoger nummer gebruiken (dus lagere prioriteit)
daarom geeft het systeem een foutmelding.
Ook duurt het even eer de weergegeven \term{PRI} zich heeft aangepast tot
de \term{NI} (\program{nice}) waarde.
\vspace{10pt}
{\normalsize
\begin{alltt}
{\large LINUX WAARSCHUWING!
\program{tcsh} definieert een EIGEN ingebouwde versie van nice:}
\hrulefill
TCSH(1) TCSH(1)
Builtin commands
\command{nice} \option{ [+priority] [command]}
\hrulefill
\end{alltt}
}
\newpage
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Cron}
\label{crontab}
\term{Cron} is een \term{daemon} waarmee taken
kunnen worden geautomatiseerd door ze op basis van een tijdschema
periodiek uit te voeren. Het is erg handig voor beheertaken.
\term{Cron} neemt een bestandsnaam als een script voor de invoer
die het intern indeelt en periodiek controleert.
Het bestand wordt een \term{crontab} bestand genoemd.
\subsection{Een Crontab bestand aanmaken}
Het \term{crontab} bestand is standaard een \term{bash} script. Het heeft
extra parameters die \term{cron} vertellen wanneer de uitvoering moet
beginnen. Hier is het formaat:
\begin{figure}[h]
\begin{alltt}
\Large
\begin{center}
mm hh dd MM D COMMAND
\end{center}
\end{alltt}
\begin{center}
\vskip-40truept
{
\normalsize
\hspace{-20pt}
\rotate{320}{\large--minute}\endrotate
\hspace{28truept}
\rotate{320}{\large--hour}\endrotate
\hspace{28truept}
\rotate{320}{\large--day}\endrotate
\hspace{25truept}
\rotate{320}{\large--Month}\endrotate
\hspace{23truept}
\rotate{320}{\large--Weekday}\endrotate
\hspace{40truept}
\rotate{320}{\large--Executable}\endrotate
\vspace{30truept}
}
\end{center}
\caption{\large Crontab File Specification Format}
\end{figure}
Sterretjes (*) zijn jokertekens die met alles overeenkomen, en
op de andere parameters afgaan om \term{cron} timing queues te geven.
Als je de taak elke dag uit wilt laten voeren, plaats je gewoon
een * in de kolom `day'.
Een simpel voorbeeld hiervan zou zijn ons bovenstaande script elke
nacht om 12 uur middernacht uit te laten voeren:
\begin{alltt}
# File: crontab-file. Start me ELKE DAG om 00.00 uur op!
0 0 * * * /home/\user/bin/backup >& /home/\user/backup-log &
\end{alltt}
Merk op dat we \stdout zorgvuldig om hebben geleid naar een logbestand,
anders zou \term{cron} de taak kunnen laten hangen, of ons alle foutmeldingen
per mail toe kunnen zenden.
Een ander interessante eigenschap van de \term{cron} time spec is de
mogelijkheid een nummer op te geven op een \term{modulus} manier.
Deel een * door een nummer om cron periodiek een opdracht uit te laten
voeren:
\begin{alltt}
# File: crontab-file. Voer elke vier uur een backup uit.
* */4 * * * /home/\user/bin/backup >> /home/\user/backup-log 2>&1
\end{alltt}
\subsection{Aanleveren van Cron Jobs}
Zodra we een \term{crontab} bestand hebben geschreven, kunnen we het
aanleveren met de opdracht \program{crontab \file{crontab-bestand}}.
\program{crontab -l} geeft een opsomming van de huidige crontab records.
\begin{alltt}
\bash{crontab crontab-file}
\bash{crontab -l}
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (crontabs installed on Mon Feb 7 00:13:36 2000)
# (Cron version -- $Id: process.tex,v 1.1.1.1 2004/03/21 21:02:25 cor Exp $)
# Execute the job every four hours.
# /home/\user/crontab-file
* * * * * /home/\user/bin/backup >> /home/\user/backup-log 2>&1
\end{alltt}
\subsection{Cron taken verwijderen}
Met behulp van de (-r) vlaggen kun je de \program{cron} taken verwijderen:
\begin{alltt}
\bash{crontab -r}
\bash{crontab -l}
\end{alltt}
\subsection{Oefeningen}
\subsubsection{Oefening 1:}
Maak een simpel script met de naam \file{hello} dat ``hallo \user'' afdrukt''.
Er hoeven slechts twee regels in te staan:
\begin{alltt}
#!/bin/bash
echo Hallo \user jij slacker...
\end{alltt}
Dit bestand zou worden geplaatst in je persoonlijke \file{\tilde/bin} directory,
en hiervoor zouden de juiste bestandsmodi voor uitvoering moeten zijn
ingesteld (hint: chmod). Zorg dat je dit script met de hand test voordat
je verdergaat.
\subsubsection{Oefening 2:}
Maak nu een crontab bestand aan met de naam \file{crontab-file} dat elke
2 minuten \file{hallo} uit zal voeren. Lever dit crontab bestand zoals
hierboven besproken aan en controleer elke even minuut om te zien of de
scripts werken.
Noot: Cron's standaardfunctioneren is alle onbehandelde uitvoer via mail
naar je toe te sturen. Als mail om wat voor reden dan ook niet werkt, kun
je de uitvoer naar een bestand of naar het scherm laten sturen.
|