Eksamen våren 2008 Unix og Operativsystemer
Les nøye gjennom oppgavene før du begynner og pass på å besvare alle spørsmålene. Alle trykte og skrevne hjelpemidler er tillatt. Sett gjerne egne forutsetninger dersom du synes oppgaveteksten er uklar. Beskriv forutsetningene og løs oppgaven utifra dem.

Oppgave 1 - Bash (10%)

a) Skriv en kommando som setter rettighetene til eieren av filen fil.txt til lese + skrive, mens gruppen kun kan lese og øvrige har ingen rettigheter.

b) Hva gjør følgende kommando:

ls -l | wc -l

c) Skriv en kommando som teller antall vanlige brukere på systemet. Anta at en vanlig bruker er definert som en bruker som har hjemmekatalog i /home.

d) Hva gjør følgende kommando:

ps aux --no-headers | grep -v "^root" | wc -l

e) Hva gjør følgende kommando når min_musikk er en mappe:

for f in *.mp3; do mv $f min_musikk; done

f) Hva ville skjedd ved kommandoen over, dersom mappen min_musikk ikke hadde eksistert på forhånd?

g) Skriv en enlinjers kombinasjon av kommandoer som leser filen code.txt, fjerner alle linjene som inneholder tegnet # og som skriver resten til en fil code_no_comments.txt.

Oppgave 2 - Prosesser (30%)

Denne oppgaven handler om prosesser i et Linux/UNIX miljø.

a) Forklar en måte man kan liste opp alle prosessene på et Linux system.

b) Forklar (uten å gå i detalj) følgende begreper som er med på å beskrive en prosess:

c) Fortell hvorfor det kan være interessant å overvåke root-prosesser og ikke-root prosesser separat.

d) Forklar kort begrepet CPU-scheduling.

e) I utgangspunktet er det rettferdig fordeling av tid mellom alle prosesser på systemet. Gi eksempel på en kommando som kan forandre prioriteten til en prosess som kjører. Forklar hva som da skjer og på hvilken måte prioriteten endres.

f) To prosesser prøver å få tilgang til samme området i internminnet på likt. Da kan det fort oppstå en situasjon at de overskriver ting samtidig og lager rot for hverandre. Beskriv metoder som finnes for at prosessene kan holde orden på hvem som har tilgang akkurat nå og når området i minnet er ledig for noen andre til å ta over.

g) I et Perl-program ønsker du å starte opp to uavhengige instanser av en subrutine du har kalt prosess() slik at disse to instansene kjøres samtidig som uavhengige prosesser. Du tester ut følgende script:

#! /usr/bin/perl
for($i = 1;$i <= 2;$i++)
{
    fork();
    print "Starter p$i\n";
    prosess($i);
}

sub prosess()
{
    sleep 5;
    print "P$_[0] ferdig\n";
}
Når du kjører programmet får du følgende output:
Starter P1
Starter P1
P1 ferdig
P1 ferdig
Starter P2
Starter P2
Starter P2
Starter P2
P2 ferdig
P2 ferdig
P2 ferdig
P2 ferdig
Dette var ikke helt som planlagt, forklar hvorfor output ble slik og du ikke fikk bare de to kjøringene av prosess() som du ønsket.

h) Du innser at forsøket i forrige delspørsmål ikke var vellykket. Endre koden slik at du oppnår det du ønsket. Utskriften fra programmet skal da bli

Starter P1
Starter P2
P1 ferdig
P2 ferdig
der de to instansene av prosess() kjører som to uavhengige prosesser.

Oppgave 3 - Munin (30%)

Vi tenker oss at det finnes en kommando "getmem", som viser hvor mye minne som er brukt av prosessene på et Linux system tilsammen. Når man kjører kommandoen får man følgende resultat:

$ getmem
Memory used: 248

Oppgaven går ut på å lage et munin script som skal vise dette tallet.

a) Forklar kort hva munin er. Ikke gå i detalj.

b) Forklar hva vi mener med et "munin script" (Munin plugin).

c) Følgende halv-ferdig utkast blir laget av munin-scriptet:

#!/bin/bash
# munin script used to show the results of getmem

if [ "$1" = "config" ]; then
    echo "graph_title Results of getmem";
    echo "graph_vlabel getmem";
    echo "graph_info Sum of memory used by applications";
    echo "getmem.label Mem";
    exit 0;
fi

exit 0;
Forklar hvordan dette scriptet fungerer og hva som mangler.

d) Fullfør scriptet. Du trenger ikke gjenta hele koden, men gjør det klart hvor du ville lagt til din kode.

e) La oss anta, at getmem sin utskrift istedet ville vært følgende:

$ getmem
Memory used: 248MB
Vi er fortsatt kun interessert i tallet 248, og ikke "248MB". Vis hvordan du kunne brukt Perl til å hente ut kun tallet og deretter skrive det ut. Du trenger ikke lage et munin-script i Perl, vis kun koden som kjører kommandoen, henter ut resultatet og skriver ut tallet.

f) Etter en lengre periode innser vi, at minnebruken i sum slik som "getmem" gir oss, ikke er tilstrekkelig for å få god nok oversikt over systemet. Vi vil heller skille mellom

  1. Minnebruk av prosesser som blir eid av "root" og
  2. Minnebruk av prosesser som ikke blir eid av "root"

Getmem kommandoen blir da modifisert til å vise følgende:

$ getmem
Memory owned by root: 60
Memory not owned by root: 188
Foreslå hvordan du kunne modifisert config-delen av munin-scriptet til å vise begge variablene.

g) Vis hvordan du kunne hentet ut hver av disse verdiene for seg selv og endre resten av scriptet slik at begge variablene vises i den samme munin-grafen.

h) Forklar hva slags trend/oppførsel du ville forventet å se på disse to verdiene over tid på et Linux system som brukes av en student-gruppe regelmessig til å gjøre ukeoppgaver tilsvarende som i deres kurs.

Oppgave 4 - Perl sockets (30%)

En munin-node er den delen av Munin-systemet som ved hjelp av munin-plugins samler data fra systemet. Munin-master samler sammen data med fem minutters mellomrom ved å be om dem fra munin-node. Egentlig er munin-node en nettverkstjeneste som kan sende sine data over nettet. Dermed kan en sentral Munin-master samle inn data fra munin-noder på flere maskiner. I denne oppgaven skal du ved hjelp av Perl socket-programmering skrive en munin-node som gir svar til Munin-master når den spør.

Følgende eksempel viser hvordan det kan se ut når man spør en aktiv munin-node som svarer på default munin-port 4949:

  [commandchars=\\\{\}]
$ {\bf telnet os76 4949}
Trying 128.39.73.158...
Connected to os76.vlab.iu.hio.no.
Escape character is '^]'.
# munin node at ubuntu
{\bf list}
open_inodes if_err_eth0 userCpu irqstats entropy if_eth0 processes hdpar au pingRTT df 
netstat interrupts swap usr load cpu df_inode if_err_eth1 if_eth1 vnc open_files forks iostat 
authDe memory psnotroot vmstat ps
{\bf fetch ps}
ps.value  95
.
{\bf fetch noSuchPlugin}
# Unknown service
.
{\bf config ps}
graph_title Processes
graph_category OS
ps.info Number of current processes
ps.label processes
graph_args --base 1000 -l 0
.
{\bf ls}
# Unknown command. Try list, config, fetch or quit 
{\bf quit}
Connection closed by foreign host.
Kommandoene som den som kobler seg til munin-node på os76.vlab.iu.hio.no skriver inn er uthevet.

Skriv et Perl-program som ved hjelp av Sockets lager en munin-node som svarer på tilkoblinger på TCP port 4949 på samme måten som munin-noden på os76.vlab.iu.hio.no gjør i eksempelet over. Perl serveren skal slik eksempelet viser svare på følgende kommandoer når en klient kobler set til og sender dem over socketen:

Hvis argumentet til fetch eller config ikke finnes i plugin-mappen skal serveren som vist svare # Unknown service. Serveren skal som i eksempelet svare på en henvendelse ved å sende
# munin node at HOSTNAME
hvor HOSTNAME er navnet på maskinen serveren kjører på. Hvis serveren mottar en ukjent kommando skal den som i eksempelet svare med
# Unknown command. Try list, config, fetch or quit

-SLUTT-



haugerud 2008-07-01