Difference between revisions of "Esercizio 1 Prova Pratica 25-09-2014"

From Sistemi Operativi
Jump to navigation Jump to search
m (Migliorata formattazione e aggiunto esercizio 3 da altra pagina)
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
 +
==Esercizio 1==
 
<source lang ="text">
 
<source lang ="text">
'''Esercizio 1'''
 
 
Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri)
 
Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri)
 
  li attivi tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti gli altri.  
 
  li attivi tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti gli altri.  
Line 23: Line 23:
 
</source>
 
</source>
  
==Soluzione di Stefano Zaniboni==
+
===Soluzione di Stefano Zaniboni===
 
<source lang ="c">
 
<source lang ="c">
 
#include <stdio.h>
 
#include <stdio.h>
Line 94: Line 94:
 
</source>
 
</source>
  
 +
==Esercizio 2==
 
<source lang ="text">
 
<source lang ="text">
'''Esercizio 2'''
 
 
Completare wta in modo che l'output di ogni comando venga salvato separatemente e solo l'output del processo terminato per
 
Completare wta in modo che l'output di ogni comando venga salvato separatemente e solo l'output del processo terminato per
 
primo venga mostrato.  
 
primo venga mostrato.  
Line 104: Line 104:
 
</source>
 
</source>
  
==Soluzione di Maldus==
+
===Soluzione di Maldus===
 
<source lang="c">
 
<source lang="c">
 
#include <s2argv.h>
 
#include <s2argv.h>
Line 189: Line 189:
  
 
Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo...
 
Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo...
 +
==Esercizio 3==
 +
<source lang="text">
 +
Scrivere un programma python o uno scrip bash che faccia un backup storico di un file.
 +
backn file n
 +
deve mantenere n versioni del file specificato. n>2
 +
Esempio:
 +
backn miofile 10
 +
se esiste miofile.9 deve essere rinominato in miofile.10
 +
se esiste miofile 8 deve essere rinominato in miofile 9
 +
e cosi' via fino a miofile.2, rinominato miofile 3.
 +
ora se miofile.1 ha lo stesso contenuto di miofile.3, miofile diventa un link fisico a miofile.2
 +
miofile viene copiato in miofile.1
 +
</source>
 +
 +
== Soluzione di Blissett ==
 +
<source lang="bash">
 +
#! /bin/bash
 +
 +
if [[ $# != 2 || ! -f $1 ]]
 +
then
 +
echo "Usage: $0 file n_backup"
 +
exit -48
 +
fi
 +
 +
file=$1
 +
n_backup=$2
 +
cartella="cartellaBackup"
 +
true=0
 +
 +
if [[ ! -d $cartella ]]
 +
then
 +
mkdir $cartella
 +
fi
 +
cd ./$cartella
 +
 +
for i in `find ./ -name "$file*" | sort -n -r -t. -k3 | cut -d. -f3`
 +
do
 +
true=1
 +
tmp=`find ./ -name "$file.$i"`
 +
num=$(($i+1))
 +
mv $tmp "$file.$num"
 +
if [[ $num -gt n_backup ]]
 +
then
 +
rm "$file.$num"
 +
fi
 +
done
 +
 +
if [[ $true -eq 1 ]]
 +
then
 +
cmp -s "$file.2" "../$file"
 +
if [[ $? -eq 0 ]]
 +
then
 +
echo creo link fisico.
 +
ln "$file.2" "$file.1"
 +
else
 +
cp ../$file ./
 +
mv $file "$file.1"
 +
fi
 +
else
 +
cp ../$file ./
 +
mv $file "$file.1"
 +
fi
 +
</source>
 +
--[[User:Blissett|Blissett]] ([[User talk:Blissett|talk]]) 13:14, 11 May 2015 (CEST)
 +
 +
==Soluzione di Maldus==
 +
<source lang="python">
 +
import argparse
 +
import sys
 +
import os
 +
import shutil
 +
import filecmp
 +
 +
def olderVersion( new, old ):
 +
    new = new + '.'
 +
    l = len(new)
 +
    if new in old:
 +
        try:
 +
            num=int(old[l:])
 +
            if num < args.version and num!=1 : os.rename(old, old[:l]+str(num+1))
 +
        except ValueError:
 +
            return
 +
 +
 +
parser = argparse.ArgumentParser(description='backup storico')
 +
parser.add_argument('file', metavar='file', type=str, help='file di cui fare backup')
 +
parser.add_argument('version', metavar='versione', type=int, help='numero di versione')
 +
args = parser.parse_args()
 +
new = args.file
 +
 +
if args.version < 2:
 +
    print("la versione deve essere > 2")
 +
    sys.exit(1)
 +
 +
entries = [ x for x in os.listdir('.') if os.path.isfile(x)]
 +
if not new in entries:
 +
    print("Nessun file con quel nome")
 +
    sys.exit(1)
 +
 +
for file in entries: olderVersion( new, file )
 +
 +
if new+'.2' in entries:
 +
    if filecmp.cmp(new+'.3', new+'.1'): os.link(new, new+'.2')
 +
    else: os.rename(new+'.1', new+'.2')
 +
elif new+'.1' in entries: os.rename(new+'.1', new+'.2')
 +
 +
shutil.copyfile(new, new+'.1')
 +
</source>

Latest revision as of 16:22, 6 May 2017

Esercizio 1

Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri)
 li attivi tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti gli altri. 
(consiglio: puo' essere utile usare la mia libreria s2argv-execs)
esempio:
wta commands
il file commands contiene:
      ./ttest 40
      ./ttest 10
      ./ttest 20
lo script ./ttest contiene:
      #!/bin/bash
      echo waiting for $1 seconds
      sleep $1
      echo done $i
l'ouptut sara':
      waiting for 40 seconds
      waiting for 10 seconds
      waiting for 20 seconds
      done 10
e poi basta perche' gli altri processi verranno terminati.

Soluzione di Stefano Zaniboni

#include <stdio.h>
#include <s2argv.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <error.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <poll.h>

int main(int argc, char *argv[]){
   FILE *stream;
   char *line=NULL;
   size_t len=0;
   ssize_t read;
   int i=0;
   int status;
   pid_t fineFirst; /*memorizzo il pid del primo processo terminato*/
   pid_t all[i];
   int pipefd[2];
   struct pollfd pipe_read_poll;

   if(argc!=2){
      fprintf(stderr,"Argomento Mancante!\n");
      exit(1);
   }

   stream=fopen(argv[1], "r");
   if(stream == NULL)
      exit(EXIT_FAILURE);

   /*aprire una pipe, dentro al while dove ho la fork fare poll che aspetta un carattere dalla pipe. Lo mando finito il while*/
   pipe(pipefd);
   pipe_read_poll.fd = pipefd[0];
   pipe_read_poll.events = POLLIN;

   while((read = getline(&line, &len, stream)) != -1) {
      if(fork()==0){
         i++;
         char **lines=s2argv(line, NULL);
         poll(&pipe_read_poll,1,-1);
         execvp(lines[0], lines);
         all[i]=getpid(); /**/
         s2argv_free(lines);
         perror("execvp fail!");
         exit(1);
      }
      else
         exit(2);
   }

   /*inviare carattere alla pipe*/
   char buf='g';
   write(pipefd[1], &buf, 1);
   fineFirst=wait(&status);
   /*kill the rest of process*/
   while(i > 0){
      if(all[i] != fineFirst){
         kill(all[i], SIGTERM);
      }
      --i;
   }
   fclose(stream);
   exit(0);
}

Esercizio 2

Completare wta in modo che l'output di ogni comando venga salvato separatemente e solo l'output del processo terminato per
primo venga mostrato. 
Nell'esempio di prima l'output dovra' essere:
waiting for 10 seconds

done 10

Soluzione di Maldus

#include <s2argv.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>

int main(int argc, char* argv[]){
        int i=0, status, out;
        FILE *fd, *output;
        pid_t *idents, winner;
        char *line=NULL, *string;
        size_t n=1;
        int pipefd[2];
        pipe(pipefd);
        struct pollfd pipepoll;
        pipepoll.fd = pipefd[0];
        pipepoll.events = POLLIN;
        if( !(fd = fopen(argv[1], "r"))){
                perror("fopen:");
                exit(1);
        }
        while( getline(&line, &n, fd) > 0){
                i++;
                free(line);
                line=NULL;
        }
        idents = malloc(sizeof(pid_t)*i);
        rewind(fd);
        i = 0;
        while( getline(&line, &n, fd) >0 ){
                switch( idents[i]=fork()){
                        case 0:
                                asprintf( &string, "out%i" ,getpid());
                                if( (out=open(string, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) <0){
                                        perror("open");
                                        exit(1);
                                }
                                free(string);
                                dup2(out, 1);
                                close(out);
                                poll(&pipepoll, 1, -1);
                                execsp(line);
                                exit(0);
                        default:
                                free(line);
                                line=NULL;
                                i++;
                                break;
                }
        }
        write(pipefd[1], "g", 1);
        winner = wait(&status);
        i--;
        for( ; i >= 0 ; i--){
                if(idents[i]!=winner){
                        kill(idents[i], SIGTERM);
                        asprintf( &string, "out%i", idents[i]);
                        unlink(string);
                        free(string);
                }
        }
        asprintf( &string, "out%i" , winner);
        if( !(output = fopen(string, "r"))){
                perror("fopen");
                exit(1);
        }
        while( getline(&line, &n, output)>0){
                printf("%s", line);
                free(line);
                line=NULL;
        }
        unlink(string);
        fclose(fd);
        fclose(output);
        return 0 ;
}

Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo...

Esercizio 3

Scrivere un programma python o uno scrip bash che faccia un backup storico di un file.
backn file n
deve mantenere n versioni del file specificato. n>2
Esempio:
backn miofile 10
se esiste miofile.9 deve essere rinominato in miofile.10
se esiste miofile 8 deve essere rinominato in miofile 9
e cosi' via fino a miofile.2, rinominato miofile 3.
ora se miofile.1 ha lo stesso contenuto di miofile.3, miofile diventa un link fisico a miofile.2
miofile viene copiato in miofile.1

Soluzione di Blissett

#! /bin/bash

if [[ $# != 2 || ! -f $1 ]]
then 
		echo "Usage: $0 file n_backup"
		exit -48
fi

file=$1
n_backup=$2
cartella="cartellaBackup"
true=0 

if [[ ! -d $cartella ]]
then
	mkdir $cartella
fi
cd ./$cartella

for i in `find ./ -name "$file*" | sort -n -r -t. -k3 | cut -d. -f3` 
do
	true=1
	tmp=`find ./ -name "$file.$i"`
	num=$(($i+1))
	mv $tmp "$file.$num"
	if [[ $num -gt n_backup ]]
	then
		rm "$file.$num"
	fi
done

if [[ $true -eq 1 ]]
then
	cmp -s "$file.2" "../$file"
	if [[ $? -eq 0 ]]
	then	
	echo creo link fisico.
		ln "$file.2" "$file.1"
	else
		cp ../$file ./
		mv $file "$file.1"
	fi
else
		cp ../$file ./
		mv $file "$file.1"
fi

--Blissett (talk) 13:14, 11 May 2015 (CEST)

Soluzione di Maldus

import argparse
import sys
import os
import shutil
import filecmp

def olderVersion( new, old ):
    new = new + '.'
    l = len(new)
    if new in old:
        try:
            num=int(old[l:])
            if num < args.version and num!=1 : os.rename(old, old[:l]+str(num+1))
        except ValueError:
            return 


parser = argparse.ArgumentParser(description='backup storico')
parser.add_argument('file', metavar='file', type=str, help='file di cui fare backup')
parser.add_argument('version', metavar='versione', type=int, help='numero di versione')
args = parser.parse_args()
new = args.file 

if args.version < 2:
    print("la versione deve essere > 2")
    sys.exit(1)

entries = [ x for x in os.listdir('.') if os.path.isfile(x)]
if not new in entries:
    print("Nessun file con quel nome")
    sys.exit(1)

for file in entries: olderVersion( new, file )

if new+'.2' in entries:
    if filecmp.cmp(new+'.3', new+'.1'): os.link(new, new+'.2')
    else: os.rename(new+'.1', new+'.2')
elif new+'.1' in entries: os.rename(new+'.1', new+'.2')

shutil.copyfile(new, new+'.1')