Job control refereert naar de mogelijkheid om processen (in wezen een ander woord voor programma's) in de achtergrond te plaatsen en ze weer naar de voorgrond te brengen. Je kunt er iets mee uitvoeren onderwijl je aan iets anders werkt, maar het ook weer terug kunt halen wanneer je het iets door wilt geven of wilt stoppen. Onder Unix is het belangrijkste hulpmiddel voor taakbeheer de shell. De shell houdt taken voor je bij, als je de taal ervan leert spreken.
De twee belangrijkste concepten in die taal zijn fg, voor foreground (voorgrond), en bg, voor background (achtergrond). Gebruik achter de prompt de opdracht yes om erachter te komen hoe ze werken.
/home/larry# yes |
Dit heeft de uitvoering van een lange kolom met y's die links van je scherm verschijnen als verrassend effect, sneller dan je kunt volgen. [1] Normaal gesproken stop je de uitvoering met de toetsencombinatie ctrl-c, maar in plaats daarvan typ je ditmaal ctrl-z. Het lijkt te zijn gestopt, maar voordat de prompt verschijnt, wordt nog een melding weergegeven, die er min of meer zo uitziet:
[1]+ Stopped yes |
Dit betekent dat het proces yes in de achtergrond is opgeschort. Je kunt het weer activeren met de opdracht fg, waarmee het weer in de voorgrond wordt geplaatst. Als je dat wenst, kun je tijdens deze opschorting iets anders doen. Probeer eens een paar keer de opdracht ls of iets dergelijks voordat je het terug in de voorgrond plaatst.
Zodra het is teruggekeerd in de voorgrond, stromen de y's weer over je scherm, net zo snel als voorheen. Je hoeft je er geen zorgen om te maken dat het tijdens de opschorting meer y's aan het opslaan was om naar het scherm te sturen: wanneer een programma wordt opgeschort, dan draait het programma pas weer op moment dat je het activeert. (Typ ctrl-c om het voorgoed te stoppen, zodra je er genoeg van hebt).
Laten we de melding van de shell eens apart bekijken:
[1]+ Stopped yes |
Het nummer tussen de blokhaken is het taaknummer van deze taak en het zal worden gebruikt wanneer we er specifiek naar moeten refereren. (Gezien taakbeheer geheel gaat over de uitvoering van meerdere processen, hebben we natuurlijk een manier nodig om onderscheid tussen de verschillende processen te kunnen maken). Het +-teken dat daarop volgt vertelt ons dat dit de "huidige taak" is; dat wil zeggen, de meest recent verplaatste taak van de voorgrond naar de achtergrond. Typ je fg dan zou je de taak met de + weer in de voorgrond plaatsen. (Daarover later meer, wanneer we de uitvoering van meerdere taken tegelijkertijd bespreken). Het woord Stopped betekent dat de taak is "beëindigd". De taak is niet dood, maar het is thans niet actief. Linux heeft het in een speciale opgeschorte toestand bewaard, klaar om in actie te komen mocht iemand daarom verzoeken. Tenslotte is yes de naam van het proces dat is beëindigd.
Laten we voordat we verdergaan deze taak stoppen en het weer op een andere manier opstarten. De opdracht daarvoor wordt kill genoemd en kan op de volgende wijze worden toegepast:
/home/larry# kill %1 [1]+ Stopped yes /home/larry# |
Wederom die melding "stopped" is misleidend. Typ jobs om erachter te komen of het nog steeds actief is:
/home/larry# jobs [1]+ Terminated yes /home/larry# |
Daar is het dan; de taak is beëindigd! (Het is mogelijk dat de opdracht jobs helemaal niets liet zien, wat gewoon betekent dat er geen taken meer in de achtergrond draaien. Paste je de opdracht kill op een taak toe, en toonde jobs niets, dan weet je dat de kill-opdracht succesvol was. Gewoonlijk wordt de melding "terminated"; weergegeven.)
Start nu als volgt yes weer op:
/home/larry# yes > /dev/null |
Als je de sectie over het omleiden van de invoer en uitvoer hebt gelezen, dan weet je dat hiermee de uitvoer van yes naar het speciale bestand /dev/null wordt gestuurd. /dev/null is een zwart gat dat alle uitvoer verslindt wat ernaar toe is gestuurd (als je hier gelukkig van wordt, kun je het je voorstellen als een stroom met y's die uit je achterkant van je computer komt en een gat in de muur doorboort).
Na het typen hiervan, krijg je geen prompt terug, en je ziet ook de rij met y's niet. Alhoewel de uitvoer naar /dev/null wordt gestuurd, is de taak nog steeds actief in de voorgrond. Zoals gewoonlijk kun je het opschorten met de toetsaanslag ctrl-z. Doe dat nu om de prompt terug te krijgen.
/home/larry# yes > /dev/null ["yes" is actief, we typten ctrl-z] [1]+ Stopped yes >/dev/null /home/larry# |
Hmm... is er een manier om het in de achtergrond te laten draaien terwijl het de prompt bij ons achterlaat voor wat interactief werk? De opdracht hiervoor is bg:
/home/larry# bg [1]+ yes >/dev/null & /home/larry# |
Hier zul je me op moeten vertrouwen: De opdracht yes > /dev/null werd weer actief, nadat je bg intikte. Ditmaal echter in de achtergrond. In feite kun je bemerken dat je machine iets is vertraagd (het eindeloos genereren en verwerpen van een constante stroom y's kost nu eenmaal wat werk!) als je opdrachten achter de prompt geeft, zoals bijvoorbeeld een ls enzo. Anders dan dat zijn er echter geen effecten. Je kunt achter de prompt doen wat je wilt en yes zal gewoon verdergaan met het doorsturen van zijn uitvoer naar het zwarte gat.
Er zijn nu twee verschillende manieren om het te stoppen: met de opdracht kill die je zojuist leerde, of door de taak weer in de voorgrond te plaatsen en de opdracht ctrl-c erop toe te passen. Laten we de tweede manier eens proberen, gewoon om de relatie tussen fg en bg wat beter te leren begrijpen:
/home/larry# fg yes >/dev/null [nu bevindt het zich weer in de voorgrond. Stel dat ik ctrl-c indruk om het te stoppen] /home/larry# |
Het is al weg. Start nu een paar taken op die dan gelijktijdig worden uitgevoerd, zoals:
/home/larry# yes > /dev/null & [1] 1024 /home/larry# yes | sort > /dev/null & [2] 1026 /home/larry# yes | uniq > /dev/null [en typ hier ctrl-z om het op te schorten] [3]+ Stopped yes | uniq >/dev/null /home/larry# |
Het eerste wat je wellicht opvalt bij deze opdrachten is de afsluitende & aan het eind van de eerste twee. Een & aan het einde van een opdracht plaatsen, vertelt de shell dat het direct vanaf het allereerste begin in de achtergrond moet draaien. (Het is gewoon een manier om te voorkomen het programma te starten, ctrl-z te typen, en vervolgens bg te typen.) Dus we startten deze twee opdrachten draaiend in de achtergrond. De derde is opgeschort en thans inactief. Wellicht dat je opvalt dat de machine nu langzamer is geworden, aangezien de twee actieve taken wat tijd van de CPU vereisen. Elke taak liet zijn taaknummer achter. De eerste twee toonden je ook hun process identification nummers, of PID's , onmiddellijk volgend op het taaknummer. De PID's hoef je normaal gesproken niet te weten, maar zo nu en dan komen ze van pas. Laten we de tweede beëindigen, aangezien het je machine vertraagt. Je zou gewoon kill %2 in kunnen tikken, maar dat zou iets te gemakkelijk zijn. Geef in plaats daarvan op:
/home/larry# fg %2 yes | sort >/dev/null [typ ctrl-c om het te stoppen] /home/larry# |
Hiermee wordt gedemonstreerd dat fg ook parameters accepteert die beginnen met een %. In feite zou je zelfs dit in hebben kunnen tikken:
/home/larry# %2 yes | sort >/dev/null [type ctrl-c om het te stoppen] /home/larry# |
Dit werkt omdat de shell een taaknummer automatisch interpreteert als een verzoek die taak in de voorgrond te plaatsen. Door de voorafgaande % kan het taaknummer worden herleid uit andere getallen. Typ nu jobs om te bekijken welke taken er nog actief zijn:
/home/larry# jobs [1]- Running yes >/dev/null & [3]+ Stopped yes | uniq >/dev/null /home/larry# |
De "-" betekent dat taaknummer 1 de tweede in lijn is om in de voorgrond te worden geplaatst, als je slechts fg zonder enige parameters opgeeft. De "+" betekent dat de aangegeven taak de eerste in lijn is; een fg zonder parameters zal taaknummer 3 in de voorgrond plaatsen. Je kunt het echter krijgen door het te benoemen als je dat wilt:
/home/larry# fg %1 yes >/dev/null [typ nu ctrl-z om het op te schorten] [1]+ Stopped yes >/dev/null /home/larry# |
Na taaknummer 1 te hebben gewijzigd en het vervolgens te hebben opgeschort heeft het ook de prioriteiten van alle taken gewijzigd. Je kunt dit zien met de opdracht jobs:
/home/larry# jobs [1]+ Stopped yes >/dev/null [3]- Stopped yes | uniq >/dev/null /home/larry# |
Nu zijn ze beiden gestopt (omdat beiden werden opgeschort met ctrl-z), en nummer 1 is de volgende in lijn om standaard in de voorgrond geplaatst te worden. Dit komt omdat je het handmatig in de voorgrond plaatste en het daarna opschortte. De "+" refereert altijd naar de meest recente taak die vanuit de voorgrond werd opgeschort. Je kunt het weer activeren:
/home/larry# bg [1]+ yes >/dev/null & /home/larry# jobs [1]- Running yes >/dev/null [3]+ Stopped yes | uniq >/dev/null /home/larry# |
Nu het weer actief is, is de andere taak weer in de lijn opgeschoven en staat hier de + voor. Laten we ze nu allen beëindigen zodat je systeem niet permanent wordt vertraagd door processen die niets doen.
/home/larry# kill %1 %3 [3] Terminated yes | uniq >/dev/null /home/larry# jobs [1]+ Terminated yes >/dev/null /home/larry# |
Als het goed is, krijg je diverse meldingen te zien over het beëindigen van de taken; niets lijkt in stilte te stoppen. Even verderop wordt een beknopte samenvatting getoond wat je behoort te weten over taakbeheer.
In taakbeheer gebruikte opdrachten en toetsaanslagen
[fg %taak Dit is een shellopdracht waarmee een taak naar de voorgrond wordt teruggebracht. Typ jobs en zoek naar de taak met het + teken om erachter te komen welke taak dit standaard is. Parameters: Optioneel taaknummer. De standaard is het proces geïdentificeerd met een +.
[&] Wanneer aan een opdracht het teken een ampersand (&) wordt toegevoegd, dan wordt hiermee aangegeven dat de opdracht automatisch in de achtergrond wordt uitgevoerd. Dit proces is dan onderworpen aan alle gebruikelijke methoden van taakbeheer die hier in detail zijn beschreven.
[bg taak] Dit is een shellopdracht die ervoor zorgt dat een opgeschorte taak in de achtergrond wordt uitgevoerd. Om erachter te komen welke dit standaard is, geef je de opdracht jobs en zoekt naar de taak met het teken +. Parameters: Optioneel taaknummer. De standaard is het proces geïdentificeerd met het teken +.
[kill %taakPID] Dit is een shellopdracht waarmee een achtergrondtaak, opgeschort of actief, wordt beëindigd. Geef altijd een taaknummer of PID op en denk er bij het gebruik van taaknummers aan ze te laten voorafgaan door een %. Parameters: Het taaknummer (voorafgegaan door %) of het PID (een % is hier niet nodig). Op één regel kunnen meer processen of taken worden opgegeven.
[jobs] Deze shellopdracht toont gewoon wat informatie over de taken die thans actief zijn of zijn opgeschort. Soms geeft het ook informatie over taken die net zijn afgesloten of beëindigd.
[ctrl-c] Dit is het algemene onderbrekingsteken. Gewoonlijk zal het 't programma stoppen als het programma in de voorgrond draait (soms zijn meer pogingen nodig). Echter niet alle programma's reageren op deze methode van beëindiging.
[ctrl-z] Deze toetscombinatie maakt gewoonlijk dat een programma wordt opgeschort, alhoewel een paar programma's het negeren. Eenmaal opgeschort kan de taak in de achtergrond worden uitgevoerd of worden beëindigd.
Het is van belang te begrijpen dat taakbeheer door de shell wordt uitgevoerd. Er bestaat geen programma op het systeem met de naam fg; fg, bg &, jobs, en kill zijn allen interne shellopdrachten (in werkelijkheid is kill soms wel een onafhankelijk programma, maar de bash shell die door Linux wordt gebruikt heeft hier een interne opdracht voor). Dit is logisch: gezien elke gebruiker zijn eigen ruimte voor taakbeheer wil, en elke gebruiker reeds een eigen shell heeft, is het 't makkelijkst gewoon de shell de taken van de gebruiker bij te laten houden. Daarom zijn de taaknummers van elke gebruiker alleen van betekenis voor die gebruiker: mijn taaknummer [1] en jouw taaknummer [1] zijn waarschijnlijk twee totaal verschillende processen. Het is zelfs zo dat als je meer dan eenmaal bent ingelogd, elk van je shells unieke taakbeheergegevens heeft. Dus jij als een gebruiker kan twee verschillende taken met hetzelfde nummer hebben draaien in twee verschillende shells.
De manier om hier zekerheid over te krijgen is door gebruik te maken van Process ID nummers (PID's). Deze zijn systeembreed; elk proces heeft een eigen uniek PID nummer. Twee verschillende gebruikers kunnen naar een proces refereren aan de hand van het PID en weten dat ze het hebben over hetzelfde proces (in de veronderstelling dat ze op dezelfde machine zijn ingelogd!).
Laten we nog eens een opdracht bekijken om te begrijpen wat PID's zijn. De opdracht ps toont een lijst met alle actieve processen, waaronder je shell. Probeer het uit. Deze opdracht accepteert tevens een paar opties, waarvan (voor veel mensen) de belangrijkste a, u en x zijn. De optie a toont de processen die toebehoren aan alle gebruikers, niet alleen die van jezelf. De x switch toont processen waarmee geen terminal is verbonden.[2] Tenslotte geeft de u switch aanvullende informatie over het proces.
Om werkelijk een indruk te krijgen wat je systeem aan het doen is, combineer je alle opties: ps -aux. Je kunt dan de processen zien die het meeste geheugen in beslag nemen door in de kolom %MEM te kijken, en het meeste CPU door te kijken in de kolom %CPU (In de kolom TIME wordt de totale hoeveelheid gebruikte CPU-tijd weergegeven.)
Nog even wat anders over PID's. In aanvulling op de acceptatie door kill in de vorm job#, accepteert het ook PID's als optie. Plaats dus een yes > /dev/null in de achtergrond, start ps, en zoek naar yes. Typ vervolgens kill PID [3]
Als je op je Linux-systeem begint te programmeren, dan zul je spoedig leren dat de taakbeheer van de shell gewoon een interactieve versie is van de aanroepen naar de functies fork en execl. Dit is te complex om hier verder op in te gaan, maar kan later van pas komen wanneer je gaat programmeren en meerdere processen wilt uitvoeren vanuit een enkel programma.
| [1] | Er zijn goede redenen voor het bestaan van deze vreemde opdracht. Zo nu en dan vragen opdrachten om bevestiging; een "yes" antwoord op een vraag. Met de opdracht yes kan een programmeur de reactie op deze vragen automatiseren. |
| [2] | Dit heeft alleen zin voor bepaalde systeemprogramma's die niet hoeven te communiceren met gebruikers via een toetsenbord. |
| [3] | Over het algemeen is het makkelijker om gebruik te maken van het taaknummer in plaats van het PID. |