Uke 9 - Multitasking og Linux-VMer

Oppgaver til mandag 24. - fredag 28. feb

Mot slutten av denne uken skal dere studere hvordan multitasking av CPU-intensive prosesser fungerer i praksis. Til ukens oppgaver må du ha tilgang til en Linux-VM (som egentlig er en Docker container, mer om det senere) som blir tildelt hver gruppe. Disse skal vi bruke i mange av de kommende ukene. Passord til de virtuelle Linux-maskinene, er lagt ut som en kunngjøring i os-gruppene(som obligene blir levert i) og man må derfor bli medlem av en os-gruppe for å få dette passordet. Dette gjelder også om du har fått godkjent alle obliger fra ifjor og ikke leverer inn obliger i år. Meld deg inn i en os-gruppe på Canvas for å få tilgang til VMer. Hvis du ønsker å teste ut noe på egenhånd, er det også mulig å bruke s-serveren intel3 til mange av oppgavene. Husk at det ikke tas backup av noen av disse VM-ene, så sørg for selv å ta backup av alt du lager av script og lignende du ønsker å ta vare på og trenger til oblig-rapportene. Passordet i os-gruppene på Canvas er alt du trenger for å få full tilgang til en Linux-VM med offentlig IP (men de er bak VPN på OsloMet så de kan ikke nås fra hvorsomhelst). Brukernavnet på VMen er group? hvor ? er nummeret på gruppen. Du kan koble deg til med putty eller wsl fra Windows eller ssh fra Mac/Linux på samme måte som til data2500:

ssh group13@os13.vlab.cs.oslomet.no
hvis du er med i gruppen os13. Husk at en slik VM har en offentlig IP og kan bli utsatt for innloggingsforsøk fra andre (men begrenset til alle med tilgang til OsloMet-nettverket). Vær derfor veldig nøye med å lage gode passord når dere senere skal lage egne brukere; lange nok og ikke bare med små bokstaver. Fordelen med en offentlig IP er at du nå kan sette opp tjenester, som for eksempel en web-server, som kan nås fra alle som er innenfor OsloMet-nettverket og det skal du gjøre denne uken.

  1. (Oblig) Studer følgende C++ program, lag en kopi og kall det b.cpp og kompiler det med $ g++ b.cpp Kjør deretter programmet på data2500 eller på en annen server og mål hvor lang tid det bruker med kommandoen $ time ./a.out.

     
    #include <algorithm>
    #include <iostream>

    using namespace std;

    int main()
    {
       // Lager et data-array
       int i,c;
       int arraySize = 32768;
       int data[arraySize];
       
       for (c = 0; c < arraySize; ++c)
         {
        data[c] = rand() % 256;
         }
       
       // Gir tilfeldig tall mellom 0 og 255
       // Gir samme array med tall for hver kjøring
        
       // sort(data, data + arraySize);
       // sorterter data-arrayet
       
       // Skriver ut de 10 første verdiene
       for (c = 0; c < 10; c++)
         cout << data[c] << "\n";
       
       // Legger sammen alle tall større enn 127
       long sum = 0;
       
       // Ytre løkke for at det skal ta litt tid...
       for (i = 0; i < 50000; ++i)
         {
            // Indre løkke
            for (c = 0; c < arraySize; ++c)
          {
             if (data[c] > 127)
               sum += data[c];
          }
         }
       
       cout << "sum = " << sum << "\n";
    }

    Fjern så kommentartegnene foran linjen som sorterer arrayet, kompiler på nytt og ta tiden på nytt med time. Hvorfor går programmet nå fortere? Hva i ukens forelesninger kan dette relateres til?
  2. (Oblig) Gjør den forrige oppgaven med ChatGPT (https://ki-chat.sikt.no/) og fortell den hva som skjer (at programmet går fortere når sorteringen kommenteres bort) og paste ut all cpp-koden i chaten. Og spør hvorfor dette skjer. Ikke vær sikker på at svaret er riktig i første omgang; ved en test var første svar helt galt. Prøv i såfall å diskutere med ChatGPT og prøv å vurdere om neste svar er riktigere.
  3. (Oblig) Logg inn på data2500 og last ned programmet regn med wget https://os.cs.oslomet.no/os/regn til din egen hjemmekatalog. Programmet gir en feilmelding om ehco og det er meningen at det skal gjøre det, slik at error kan omdirigeres. Programmet regner på et problem i noen minutter (ca. et halvt på data2500 og Linux VM, ett minutt på s-server) og skriver tilslutt resultatet til skjermen. Start programmet slik at det blir en bakgrunnsprosess som skriver resultatet til filen res.txt når den er ferdig og som skriver feilmeldinger til err.txt. Hva skjer om du logger ut før regn er ferdig?
  4. Finn ut hvor mye CPU-tid regn-programmet bruker og hvor stor andel av den totale CPU-tiden det bruker ved å bruke kommandoen time foran selve kommandoen du kjører med $ time ./regn. For å få med prosentandel CPU, må man formatere output fra time, f. eks slik:
    $ TIMEFORMAT="Real:%R User:%U System:%S %P%%"
    
    der Real viser reell tid, User viser CPU-tid brukt i user-mode (prosessen selv som regner), System viser CPU-tid brukt i kernel-mode (av OS-kjernene) og %P gir prosentandel CPU denne prosessen har brukt. Hvis man legger denne kommandoen inn i ~/.bashrc vil dette formatet alltid brukes. Prøv å kjøre programmet slik at også tidsbruken lagres i err.txt. Det siste er det ikke så enkelt å få til......
  5. Det er veldig viktig at du stopper alle regnejobber etter at du er ferdig med denne oppgaven!

    Logg inn på data2500 og last ned programmet regn med wget https://os.cs.oslomet.no/os/regn til din egen hjemmekatalog. Programmet vil stå og regne og bruke så mye CPU det klarer. Start programmet med
    $ ./regn&
    
    og det vil starte å regne. Se at programmet kjører med
    top
    
    Hvor mange prosent CPU får prosessen? (husk at også andre kan teste ut det samme samtidig).

    Start så en ny prosess mens den forrige kjører med

    $ ./regn&
    
    Se igjen på top. Hvor mange prosent CPU får hver prosess? Tast 1 mens top kjører. Hvor mange CPU'er har data2500?

  6. Det er viktig at du stopper alle regnejobber etter at du er ferdig med denne oppgaven!

    Logg inn på data2500 og last ned programmet run.c med
    wget https://os.cs.oslomet.no/os/run.c
    
    til din hjemme-mappe. Programmet vil stå og regne og bruke så mye CPU det klarer. Kompiler og kjør programmet med
    $ gcc -O run.c
    $ ./a.out&
    
    og det vil starte å regne. Se at programmet kjører med
    top
    
    Hvor mange prosent CPU får prosessen? (husk at også andre kan teste ut det samme samtidig på data2500)

    Start så en ny prosess mens den forrige kjører med

    $ ./a.out&
    
    Se igjen på top. Tast 1 mens top kjører. Hvor mange CPU'er har data2500? Hvor mange prosent CPU får hver prosess? Hvordan fordeles de to regne-jobbene på CPUer?

    Start så fem prosesser i en for-løkke slik at de alle samtidig kjører ./a.out &. Hvordan fordeles CPUene mellom de 5 regne-jobbene? Tast f som gir mulighet til å se flere kolonner, flytt så pekeren ned til kolonnen "Last used CPU" med piltatsten og tast space og deretter q for å komme tilbake til top. Prøv å se hvilke CPUer dine 5 prosesser jobber på og prøv å forklare hvordan OS fordeler jobbene på CPU'ene.

    Stopp til slutt alle a.out-prosessene du har startet med
    $ killall a.out
    

    Editer run.c og fjern en null fra den indre i-løkken slik at programmet etter å ha blitt kompilert med gcc -O bruker ca 10 sekunder. Klarer du å beregne hvor lang tid hver prosess bruker når du kjører 5 a.out-prosesser samtidig ut ifra hvor lang tid en enkelt prosess bruker når den kjører alene?

  7. (Oblig)

    Det er viktig at du stopper alle regnejobber etter at du er ferdig med denne oppgaven!

    Logg inn på Linux-VM (ssh group13@os13.vlab.cs.oslomet.no eller lignende)og last ned programmet run.c med
    wget https://os.cs.oslomet.no/os/run.c
    
    til din hjemme-mappe. Før du kan kompilere det må du laste ned gcc med
    group100@os100:~$ sudo apt install gcc
    
    Kompiler og kjør programmet med
    $ gcc -O run.c
    $ ./a.out&
    
    og det vil starte å regne. Se at programmet kjører med
    top
    
    Hvor mange prosent CPU får prosessen? (husk at også andre kan teste ut det samme samtidig, de virtuelle VM-ene deler samme fysiske server). Stopp prosessen med
    $ killall a.out
    
    hvis den ikke har stoppet av seg selv. Hvis du ikke har killall installert, kan den installeres med
    group100@os100:~$ sudo apt-get install psmisc
    

    Start så tre nye prosesser samtidig med

    $ ./a.out&
    $ ./a.out&
    $ ./a.out&
    
    eller med en for-løkke. Se igjen på top. Hvor mange CPU'er ser det ut til at din VM/docker container har? Hvor mange prosent CPU får hver prosess? Hvordan fordeles de tre regne-jobbene på CPUer?

    Drep eventuelle kjørende a.out-prosesser og start igjen tre prosesser i en for-løkke slik at de alle samtidig kjører ./a.out &. Start top og tast 1 for å se alle CPUene. Ser det ut til at din VM/container har så mange CPUer? Hvordan fordeles CPUene mellom de 3 regne-jobbene? Tast f som gir mulighet til å se flere kolonner, flytt så pekeren ned til kolonnen "Last used CPU" med piltatsten og tast space og deretter q for å komme tilbake til top. Prøv å se hvilke CPUer dine 3 prosesser jobber på og prøv å forklare hvordan jobbene blir fordelt på CPU'er. Hvordan er dette anderledes enn på data2500? Data2500 er en ekte virtuell maskin, mens din os-host er egentlig en docker container.

    Stopp til slutt alle a.out-prosessene du har startet med
    $ killall a.out
    

    Klarer du å beregne hvor lang tid hver prosess bruker når du kjører tre slike prosesser samtidig, ut ifra hvor lang tid en enkelt prosess bruker når den kjører alene?

  8. Ukens nøtt nr. 1: Studer følgende svar fra ChatGPT 4.0. Fire av svarene er riktige og ett er galt. Hvilket av svarene er galt og hvorfor? Klarer du å lage en litt mer systematisk metode for å beregne tiden som alltid gir rett svar?
  9. Ukens nøtt nr. 2: Endre den ytre j-løkken i run.c som du tidligere har lastet ned
    wget https://os.cs.oslomet.no/os/run.c
      
    slik at den bare går en gang. Da vil programmet bruke litt mindre enn 10 sekunder på Linux-VM. Bruk dette til å teste om beregningene dine i forrige oppgave for 2 CPUer og 6 prosesser stemmer (men gitt i sekunder og ikke i minutter).
  10. (Oblig) På gruppens Linux-VM: lag en bruker for hvert medlem av gruppen, bruk samme brukernavn som dere har på data2500(s123456 eller lignende). Pass NØYE på å ha et ordentlig passord, minst 8 tegn og gjerne tall og spesialtegn, ellers vil dere kunne bli hacket. Prøv å logge deg på som en av brukerene du laget.

    Hvilken kommando kan man bruke for å se hvilke grupper man tilhører?

    Prøv om din nye bruker kan bli root ved å kjøre kommandoen "sudo su". Forklar hvorfor det ikke går (HINT: se hvilke grupper din nye bruker er medlem av i forhold til den brukeren du fikk tildelt.)

    Se om du kan legge den nye brukeren din til riktig gruppe slik at den også kan bli root. Hva er det som gjør at medlemmene i denne gruppen får sudo-rettigheter?
  11. Lag som brukeren groupXX (på Linux-VM der XX er ditt gruppenummer) en katalog ~/felles og lag en fil info.txt i denne katalogen. Lag så en ny gruppe med navn os med kommandoen
    sudo addgroup os
    
    Sørg så for at groupXX blir medlem av denne gruppen. og deretter for at de andre brukerne dere tidligere lagde på Linux-VM (s123456 eller lignende) også blir medlemmer av denne gruppen. Bruk så kommandoene chgrp og chmod til å sørge for at alle medlemmer av gruppen os for lov til å editere og lagre filen ~/felles/info.txt. Logg inn som en av de andre brukerne og sjekk at de virkelig får editere filen. Endres hvem som eier filen når du editerer og lagrer den? (hvis du bruker chgrp som brukeren groupXX, må du logge ut og inn igjen først. Som du ser med groups blir brukeren først da oppfattet som medlem av os)
  12. Ukens utfordring Som brukeren groupXX på Linux-VM: Sett filrettighetene til filen ~/felles/info.txt slik at brukeren selv og alle i gruppen ikke har noen rettigheter, mens alle andre har alle rettigheter (såkalte James Bond rettigheter). Prøv å se på innholdet med
    $ cat ~/fil.txt
    Logg inn som en annen bruker (s123456) og se på innholdet med
    $ cat ~groupXX/fil.txt
    Forklar.
  13. (Oblig) Installer en Apache webserver på gruppens Linux-VM med kommandoene
      sudo apt update -y
      sudo apt install -y apache2
      
    Deretter må du starte webserveren med
    sudo service apache2 start
    
    Test at Web-serveren virker ved å skrive inn http://os??.vlab.cs.oslomet.no men der du bytter ut ?? med ditt gruppenummer. Alt du legger inn i katalogen /var/www/html kommer opp her. Altså har du nå din egen private webserver som kan nås fra OsloMet-nettverket. Endre /var/www/html/index.html slik at man kan se hvilken gruppe som styrer denne webserveren.
  14. (Oblig) Installer først screen på Linux-VM om det ikke er installert:
      sudo apt update -y
      sudo apt install -y screen
    
    Anta at du er på os-gruppe osXX hvor XX er ditt gruppenummer. Følg forelesningsnotatene, logg inn som brukeren groupXX og lag en screen session som kan deles av andre. Få så alle de andre på gruppen til å logge seg på med samme bruker, groupXX, og få deretter alle på gruppen til å koble seg til samme screen. Om du er alene på en gruppe, test med to forskjellige innloggingsvinduer. Dette kan være veldig praktisk om dere sitter rundt et bord og samarbeider om Linux-oppgaver og for eksempel skriver et script. Et av medlemmene kan da vise hvordan et problem løses, eventuelt kan alle prøve forskjellige kommandoer. Det gjelder bare å sørge for å være en av gangen, for alle kan taste samtidig.

    Det er også mulig å få til en delt screen mellom forskjellige brukere om man nøye følger punkt 4 på siden https://www.pc-freak.net/blog/share-screen-terminal-session-in-linux-screen-share-between-two-or-more-users-howto/.

  15. (Oblig) Start fra data2500 og bruk ssh-copy-id til å sørge for at du kan logge inn til group-brukeren din på Linux-VM uten å taste passord (start fra s-server om du ikke kommer inn med ssh fra data2500 til Linux-VM). Se forelesningsnotater. Lag deretter et script som skal kjøres fra data2500. Scriptet skal først pakke ned mappen /tmp/dir på data2500 med tar cfz og lage en tgz-fil(pakket med tar og zippet med gzip, se notater). Deretter skal det flytte pakken til din bruker på Linux-VM med scp og pakke ut pakken i ~/tmp på Linux VM. Om denne mappen ikke finnes på Linux-VM, skal den lages først. Alle mellomlagrede filer (.tgz) på både data2500 og Linux VM skal slettes etterpå av scriptet. Når scriptet kjøres på data2500
    s123456@data2500:~$ ./s.sh
    dir.tgz
    100%   43KB  12.0MB/s   00:00    
      
    skal det se omtrent slik ut på Linux-VM:
    group100@os100:~$ ls -l tmp/dir/
    total 684
    -rw-r--r-- 1 group100 group100 694186 Feb 16 18:08 auth.log
    -rw-r--r-- 1 group100 group100      4 Feb 16 18:08 enFil.txt
      
  16. Installer først rsync på Linux-VM om den ikke er installert:
      sudo apt update -y
      sudo apt install -y rsync
      
    Lag et script som bruker rsync til å ta backup av av mappen /home/group?? med undermapper og filer på os??, hvor ?? er ditt gruppe-nummer og group?? er gruppens bruker på Linux-VM. La scriptet ta backup til en mappe ~/home for din bruker på data2500. Scriptet skal kjøres fra data2500, slik at du ikke gir andre med tilgang til Linux-VM tilgang til ditt område på data2500. NB! rsync må være installert på begge sider, så du må først installere rsync på Linux-VM. Hva skjer om du sletter en fil på Linux-VM og du etterpå gjør rsync? Bruk en rsync-kommandoen som gjør slik at filen da slettes der du lagrer backup(på data2500 i dette tilfellet). Bruk cron til å sørge for at det tas backup hver natt (kjør crontab -e på data2500) og få scriptet til å skrive en linje med dato og klokkeslett for når backup ble tatt til en loggfil i din hjemme-mappe. Test ut med en hurtigere backup-frekvens (f.eks. ett minutt) for å sjekke at alt virker og sett så til nattlig backup. Pass på å bruke full path i crontab! Sørg for at all output fra cron-kommandoen sendes til en fil eller til /dev/null, både stderr og stdout. Ellers kan det bli generert en rekke eposter til din epost-konto. Legg merke til at crontab-kommandoen kjøres i /bin/sh, så bruk for eksempel > /dev/null 2&>1, for >& /dev/null virker ikke. Sett også MAILTO="" i crontab for å unngå mange epost når du har fått det til å virke.
  17. Utvid backupscriptet fra forrige oppgave slik at det det også tar backup av hele mappen /etc med filer og undermapper til ~/home. Da må du sørge for å ha ssh-key innlogging som root til os-VM. Følg instruksjonene i forelesningsnotatene.
  18. Ukens utfordring nr 2! Sørg for at du har ssh-key innlogging uten passord fra din bruker s123456 på Linux-VM til brukeren din på data2500 (fjern dette etterpå slik at du unngår at andre på gruppen får denne tilgangen). Er det mulig ved å 'stjele' den private (id_rsa) nøkkelen fra s123456, og sette opp en ssh-key slik at group-brukeren får tilgang til s123456 på data2500 (men uten at du bruker ditt passord der). Fjern denne tilgangen etterpå hvis du klarer å sette det opp.
  19. (Oblig) Ukens konkurranse-oppgave går ut å finne en fil som sist ble endret 2 juni 1998. På s-serveren er det lagt inn en ny mappe som heter newdir og som inneholder 1000 mapper hvor det lagt inn en fil med navn dfil.txt i hver eneste av de 1000 mappene. Alle er like store og alle inneholder en tekstreng av typen "x3i1YTfHsG". Filen du skal lete deg frem til skiller seg ut fra de andre ved at den sist ble endret 2. juni 1998 klokken 08:12 (1998-06-02 08:12:41). Å kunne finne en fil som ble endret på et gitt tidspunkt på en Linux-server kan i mange tilfeller være veldig nyttig og her må du prøve å få til det. Les forelesningsnotater om å finne filer med find hvis du står fast. Innholdet i denne filen er som vanlig en 10-tegns kode som viser at du har løst oppgaven.

    Logg inn som tidligere med noe tilsvarende som følgende:

    $ ssh -p 5135 s135@intel3.vlab.cs.oslomet.no
    
    s135@intel3.vlab.cs.oslomet.no's password: 
    
    s135@os5135:~$ 
    

    For å sjekke at du har funnet det rette ordet, skriv strengen med 10 tegn inn på siden os.php uke 9 og du får beskjed om du har skrevet riktig. I tilegg blir du da med på konkurransen om å finne denne koden fortest mulig!