This shows you the differences between two versions of the page.
sde:teme:tema_fr_3 [2020/03/16 19:33] ioana_maria.culic |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Devoir 3 - Mini-shell ====== | ||
- | |||
- | Le but de ce thème est de créer un shell simple, compatible avec '' sh ''; | ||
- | |||
- | ===== Informations générales ===== | ||
- | |||
- | <note important> | ||
- | Date limite: ** Le 5 avril, 23h55 ** \\ | ||
- | Note: ** 2 points ** de la note \\ | ||
- | Téléchargement du devoir: [[https://vmchecker.cs.pub.ro|vmchecker.cs.pub.ro]] \\ | ||
- | Charge différée: ** 0.1 point / jour ** (max 4 jours) \\ | ||
- | </note> | ||
- | |||
- | ===== Connaissances précieuses ===== | ||
- | |||
- | * Utiliser les fonctions POSIX pour travailler avec des fichiers ('' os.open '', '' os.read '', '' os.write '', ...) | ||
- | * Utiliser les fonctions pour travailler avec des processus ('' os.fork '', '' os.exec '' et 'os.waitpid' ', ...) | ||
- | * Comprendre les principes de travail avec les fichiers et les processus | ||
- | |||
- | ===== Règles ===== | ||
- | |||
- | - Le devoir doit contenir un fichier Readme expliquant comment vous avez créé le devoir (-0.1p) | ||
- | - Vous pouvez utiliser seulement les fonctions POSIX (bibliothèque [[https://docs.python.org/3/library/os.html|os]] ). | ||
- | - Vous pouvez utiliser uniquement le langage Python ( Python 3) | ||
- | - Un devoir qui passe tous les tests automatisés obtiendra 10 sur 10 (si vouz ne trichez pas en utilisant un API interdit, tel que la fonction '' f.write() '', situation pour laquelle de devoir ne sera pas noté). | ||
- | |||
- | |||
- | ===== Copier ===== | ||
- | |||
- | Le devoir doit etre résolu individuellement. Toute tentative de tricher entraînera ** 0p ** pour ce devoir. Nous utiliserons également des systèmes de détection de trichage automatique. Si nous avons des doutes, nous vous poserons des questions supplémentaires concernant le devoir. | ||
- | |||
- | ===== Questions ===== | ||
- | |||
- | Si vous avez des questions sur le sujet, écrivez un problème sur le référentiel github [[https://github.com/upb-fils/sde.git|repository]] avec le titre [mini-shell ] <le titre de votre question>. Vous avez besoin d'un compte github pour écrire des questions. | ||
- | |||
- | <note warning> | ||
- | ** NE PAS PUBLIER LE CODE SOURCE **. Cela sera considéré comme une tentative de tricher et sera pénalisé avec 0p pour vous sur ce devoir. | ||
- | </note> | ||
- | |||
- | Si vous souhaitez recevoir un courrier électronique lorsque de nouvelles questions sont posées ou lorsque des réponses sont fournies, accédez à github [[https://github.com/upb-fils/sde|repository]] et cliquez sur // Regarder //. | ||
- | |||
- | ===== Mini Shell ===== | ||
- | |||
- | Implémentez un shell simple qui prend en charge l'exécution de commandes externes avec plusieurs arguments, commandes internes, redirections, canaux. Le shell doit gérer l'exécution de commandes composées avec plusieurs opérateurs. | ||
- | |||
- | <note> | ||
- | Commandes internes: commandes que le shell exécute: '' cd '', '' pwd '', '' exit '' ... | ||
- | |||
- | Commandes externes: Les commandes qui sont en fait des exécutables séparés: '' ls '', '' vim '', '' arbre '', '' nano '', ... | ||
- | |||
- | La règle est la suivante: vérifiez si la commande interne est, sinon, on suppose qu'elle est une commande externe. | ||
- | </note> | ||
- | |||
- | Le shell doit prendre en charge les opérateurs d'exécution suivants: | ||
- | |||
- | * Opérateur de séquençage ''; '' | ||
- | * sera utilisé pour exécuter des commandes séquentiellement; | ||
- | * par exemple, '' expr1; expr2 '' commencera par exécuter les commandes '' expr1 '' et les commandes '' expr2 '' seulement après l'exécution de //expr1//; | ||
- | * Opérateur de parallélisme '' & '' | ||
- | * sera utilisé pour exécuter les commandes en parallèle; | ||
- | * par exemple, '' expr1 & expr2 '' entraînera l'exécution de '' expr1 '' et des commandes '' expr2 '' en parallèle; | ||
- | * dans l'implémentation de votre programme, il est ** INTERDIT** de rappeler le propre exécutable. <code> execv ("./ my_homework", "command"); </code> | ||
- | * opérateurs d'exécution conditionnelle '' && '' et '' || '' | ||
- | * seront utilisés pour exécuter des commandes en fonction du code d'erreur; | ||
- | * '' expr1 && expr2 '' n'exécutera les commandes '' expr2 '' que si la commande '' expr1 '' génère un code d'erreur '0' '; | ||
- | * '' expr1 || expr2 '' n'exécutera les commandes '' expr2 '' que si les commandes '' expr1 '' génèrent un code d'erreur différent de zéro. | ||
- | * l'opérateur de pipe '' | '' est interpolé entre deux commandes. L'effet est la redirection de ce que le premier processus écrit sur l'écran vers ce que le deuxieme processus lit du clavier . Par exemple, '' expr1 | expr2 '' entraînera l'exécution des commandes '' expr1 '' avec la sortie standard redirigée vers le stdin des commandes '' expr2 ''; | ||
- | |||
- | La priorité des opérateurs d'exécution est, de la priorité la plus grande à la plus petite: | ||
- | |||
- | - opérateur pipe | ||
- | - opérateurs d'exécution conditionnelle | ||
- | - opérateur de parallélisme | ||
- | - opérateur de séquençage | ||
- | |||
- | Le shell doit également prendre en charge les redirecteurs suivants: | ||
- | |||
- | * '' < nom_fichier '' pour rediriger l'entrée standard à partir du fichier ''nom_fichier''; | ||
- | * '' > nom_fichier '' pour rediriger la sortie standard vers le fichier '' nom_fichier ''; | ||
- | * '' 2> nom_fichier '' pour rediriger la sortie d'erreur standard vers le fichier '' nom_fichier ''; | ||
- | * '' &> nom_ficher'' pour rediriger la sortie standard et la sortie d'erreur standard vers le fichier ''nom_fichier''; | ||
- | * '' %% >> %% nom_fichier '' pour rediriger la sortie standard vers le fichier '' nom_fichier '' en mode // append //; | ||
- | * '' 2 %% >> %% nom_fichier '' pour rediriger la sortie d'erreur standard vers le fichier '' nom_fichier '' en mode // append //. | ||
- | |||
- | Finalement, le shell doit accepter les commandes internes suivantes: | ||
- | |||
- | * '' exit '' et '' quit '' pour terminet le shell | ||
- | * '' cd directory '' pour changer le répertoire actuel | ||
- | * ** ATTENTION **: Le mini-shell doit toujours fonctionner a l'utilisation de la commande '' cd '' sans paramètre. Il n'est pas nécessaire d'implémenter le comportement de 'bash' '(remplacer le répertoire en cours par le répertoire //home// de l'utilisateur courant) ni l'implémentation d'une valeur de sortie pour ce scénario (plus précisément,' 'cd' 'sans paramètre peut ne rien faire , mais il ne doit pas rester avec un comportement indéfini qui va conduire à des erreurs). | ||
- | |||
- | Le shell doit aussi supporter les sous-commandes: | ||
- | * Le format d'utilisation est '' commande $(commande ou liste commandes) '' | ||
- | * pour celles-ci, on va exécuter tout ce qu'on trouve entre les paranthese et le résultat sera remplacé dans la liste de commandes | ||
- | |||
- | ==== Remarques générales ==== | ||
- | |||
- | * Pour simplifier la mise en oeuvre du devoir, vous pouvez utiliser l' [[https://ocw.cs.pub.ro/courses/sde/teme/tema_ro_3_python#parcurgearea_linii_de_comanda | analyseur]] mis en œuvre par nous. Pour plus de détails sur l’analyseur, lisez le fichier README dans l’archive. Des exemples d'utilisation de l'analyseur peuvent être trouvés dans la source '' cmd.py '', qui peut etre utilisée comme un support pour le devoir. | ||
- | * Le prompt affiché par le shell est requis pour faciliter les tests automatiques et est %%$%% (c'est-à-dire qu'il affichera le caractère %%$%% suivi d'un espace blanc). | ||
- | * Le nom de l'exécutable du devoir doit être '' cmd.py ''. | ||
- | |||
- | ==== Suggestions ==== | ||
- | Le devoir est relativement complexe par rapport au précédent. Un modèle pour le commencement du devoir est disponible sur le [[https://github.com/upb-fils/sde|repository]] dans le répertoire // tema3 //. | ||
- | Nous vous recommandons de résoudre et de tester toujours le devoir, étape par étape: | ||
- | |||
- | - Lancer des commandes simples ('' ls '', '' ls -l '') | ||
- | - Exécuter des commandes internes ('' cd '', '' exit '', 'quit' ') | ||
- | - mise en place de redirections (opérateurs '' < '', '' > '', '' 2> '', '' &> '', '' >> '', '' 2>> '') | ||
- | - séquencement des commandes (opérateurs ''&&'', ''||'', '';'') | ||
- | - implémentation des opérateurs '' & '' (parallèle) | ||
- | - '' | '' | ||
- | |||
- | * Voici quelques exemples de commandes et le résultat généré par celles-ci: | ||
- | <code bash> | ||
- | $ ls | ||
- | Makefile README.checker mini-shell mini-shell.o parser | ||
- | Makefile.checker inputs mini-shell.c outputs tags | ||
- | |||
- | $ cat /etc/services | grep telnet | ||
- | telnet 23/tcp | ||
- | rtelnet 107/tcp # Remote Telnet | ||
- | rtelnet 107/udp | ||
- | telnets 992/tcp # Telnet over SSL | ||
- | telnets 992/udp | ||
- | tfido 60177/tcp # fidonet EMSI over telnet | ||
- | |||
- | $ uname -a ; ps | ||
- | Linux bogdan-desktop 2.6.31-19-generic #56-Ubuntu SMP Thu Jan 28 02:39:34 UTC 2010 x86_64 GNU/Linux | ||
- | PID TTY TIME CMD | ||
- | 6078 pts/0 00:00:00 bash | ||
- | 6190 pts/0 00:00:00 mini-shell | ||
- | 6200 pts/0 00:00:00 ps | ||
- | |||
- | $ date && sleep 1 ; echo date | ||
- | Mon Feb 8 13:40:25 EET 2010 | ||
- | date | ||
- | |||
- | $ date && sleep 1; date | ||
- | Mon Feb 8 13:40:49 EET 2010 | ||
- | Mon Feb 8 13:40:50 EET 2010 | ||
- | |||
- | $ true && date | ||
- | Mon Feb 8 13:41:16 EET 2010 | ||
- | |||
- | $ false && cat mini-shell.c | ||
- | |||
- | $ false || date | ||
- | Mon Feb 8 13:42:36 EET 2010 | ||
- | |||
- | $ cat /et/services | ||
- | cat: /et/services: No such file or directory | ||
- | |||
- | $ gcc > tmp; echo sep; cat tmp | ||
- | gcc: no input files | ||
- | sep | ||
- | |||
- | $ strace -e trace=read ls 2> strace.out | ||
- | Makefile README.checker mini-shell mini-shell.o parser tags | ||
- | Makefile.checker inputs mini-shell.c outputs strace.out tmp | ||
- | |||
- | $ head -1 strace.out | ||
- | read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@#\0\0\0\0\0\0@"..., 832) = 832 | ||
- | |||
- | $ pwd; cd Teme; pwd | ||
- | /home/bogdan/Documents/SO/Solutii | ||
- | /home/bogdan/Documents/SO/Solutii/Teme | ||
- | |||
- | $ LETTER=alfa && echo $LETTER | ||
- | alfa | ||
- | |||
- | > echo a > test ; echo b >> test && cat test | ||
- | a | ||
- | b | ||
- | |||
- | > exit</code> | ||
- | ===== Documents d'aide ===== | ||
- | Cours utiles: | ||
- | |||
- | *[[sde:cursuri:01]] | ||
- | *[[sde:cursuri:02]] | ||
- | *[[sde:cursuri:03]] | ||
- | *[[sde:cursuri:04]] | ||
- | *[[sde:cursuri:05]] | ||
- | Laboratoires utiles: | ||
- | |||
- | *[[sde:laboratoare:01]] | ||
- | *[[sde:laboratoare:02]] | ||
- | *[[sde:laboratoare:03]] | ||
- | *[[sde:laboratoare:04]] | ||
- | *[[sde:laboratoare:05]] | ||
- | Ressources: | ||
- | * L'analyseur de commandes, le modèle de code et les tests sont disponibles dans [[https://github.com/upb-fils/sde/tree/master/tema3 | tema3]] sur le [[https://github.com/upb-fils/sde|repository de Github]]. | ||
- | |||
- | |||
- | ===== Traitement de la ligne de commande ===== | ||
- | Pour traiter la ligne de commande, nous avons déjà écrit un analyseur que vous pouvez utiliser. | ||
- | Lancez le devoir dans le fichier 'cmd.py' du modèle. | ||
- | |||
- | Pour voir à quoi ressemble la structure de données à partir de l'analyseur, exécutez le script cmd.py et apres introduisez une commande du clavier. | ||
- | |||
- | <note warning> | ||
- | Pour pouvoir exécuter le fichier cmd.py, il faut intaller la bibliotheque bashlex (pip3 install -target=. bashlex). | ||
- | </note> | ||
- | <code bash> | ||
- | $ pip3 install --target=. bashlex | ||
- | $ python3 cmd.py | ||
- | |||
- | $ ls | ||
- | ls | ||
- | {'op': 4, 'com1': None, 'com2': None, 'commands': [<parse.SimpleCommand object at 0x100b4bfd0>], 'input': None, 'output': None, 'err': None, 'append_err': False, 'append_out': False} | ||
- | commands | ||
- | ls | ||
- | |||
- | </code> | ||
- | |||
- | ===== La structure retournée en cmd.py ===== | ||
- | |||
- | En appelant parse.parse(line), on va renvoyer un objet de type **Command**. | ||
- | |||
- | ==== Classe Command ==== | ||
- | |||
- | Propriétés: | ||
- | |||
- | * op - le type d'opération de la commande (les types sont définis en bas) | ||
- | * com1 - contient un objet de type Command, la premiere commande de la liste, si op est OP_NONE, com1 sera égal a None | ||
- | * com2 - contient un objet de type Command, la deuxieme commande de la liste, si op est OP_NONE, com2 sera égal a None | ||
- | * commands - contient la liste des commandes et argumens ( seulement si op est OP_NONE), si l'un des arguments est de la forme '' $(cmd_list) '', l'contient un objet de type Command, la premiere commande de la liste, si l'élément sera du type Command; sinon, l'élément sera du type SimpleCommand | ||
- | |||
- | <note> | ||
- | Pour vérifier le type d'on objet, utilisez la structure **isinstance (obj, class)**. | ||
- | </note> | ||
- | * input - comprend le fichier d'input, si l'entrée est redirigée ('' < '') | ||
- | * output - contient le fichier d'output, si la sortie est redirigée ('' > '', ''>>'') | ||
- | * err - contient le fichier d'error_output, si la sortie d'erreur standars est redirigée (''2>'', ''2>>'', ''&>'', ''&>>'') | ||
- | * append_err - a la valeur True si la sortie d'erreur fait un appned (''2>>'', ''&>>'') | ||
- | * append_out - a la valeur true si la sortie fait un append (''>>'', ''&>>'') | ||
- | |||
- | ==== Classe SimpleCommand ==== | ||
- | L'objet de type SimpleCommand est utilisé dans les commandes ayant op égal a OP_NONE (commande simple). Celles-ci se trouvent dans la liste **commands** est sont soit des commandes, soit des parametres pour des commandes. | ||
- | |||
- | Propriétés: | ||
- | * word - le texte de la commande ou du parametre | ||
- | |||
- | ==== Types d'opérations ==== | ||
- | |||
- | Le module **parse** expose les suivantes types d'opérations (la valeur de command.op): | ||
- | |||
- | * OP_CONDITIONAL_NZERO - l'opération des de type ( '' cmd1 && cmd2 '' ) | ||
- | * OP_CONDITIONAL_ZERO - l'opération des de type ( '' cmd1 || cmd2 11 '') | ||
- | * OP_SEQUENTIAL - l'opération est de type ( ''cmd1 ; cmd2 '' ) | ||
- | * OP_PARALLEL - l'opération est de type ( '' cmd1 & cmd2 '' ) | ||
- | * OP_NONE - l'opération est de type ( '' commande params '' ) | ||
- | * OP_PIPE - l'opération est de type ( '' cmd1 | cmd2 '' ) | ||
- | ===== FAQ ===== | ||
- | |||
- | *** Q: ** Le devoir 3 peut être réalisé en Python 2? | ||
- | *** A: ** Non. | ||
- | |||
- | *** Q: ** Le nombre de fors doit-il être optimisé? Par exemple, pour la commande '' a | b | c '', j'ai 3 fourchettes ou puis-je en avoir 4 ou 5? | ||
- | *** A: ** Il n'est pas nécessaire d'optimiser le nombre de fourches. Cependant, il est généralement conseillé de considérer l'efficacité des ressources plus efficacement. | ||
- | |||
- | *** Q: ** Le Shell doit se comporter comme un vrai shell (sh, bash) dans la situation ...? | ||
- | *** A: ** La fonctionnalité minimale requise est celle indiquée dans la déclaration. Si vous implémentez quelque chose de plus, veuillez spécifier dans le fichier README Exemples de fonctionnalités non requises: mise à jour des variables d’environnement (comme '' $ OLDPWD '' et '' $ PWD ''), historique, etc. - (voir [[http://linux.die.net / man / 1 / bash | man bash]] pour une idée de la fonctionnalité d'un shell complet :-)) | ||
- | |||
- | *** Q: ** Puis-je utiliser l'analyseur si je veux écrire un autre équivalent? | ||
- | *** A: ** Oui. | ||
- | |||
- | *** Q: ** Nous sommes autorisés à utiliser: | ||
- | <code> | ||
- | args = ["/bin/bash", "-c", command]; | ||
- | os.execv(args[0], args); | ||
- | </code> | ||
- | *** A: ** Non. | ||
- | |||
- | *** Q: ** Puis-je faire '' os.execv '' sur mon devoir pour exécuter une partie de l'arbre indépendamment? | ||
- | *** A: ** Non. | ||
- | |||
- | |||
- | ===== Télécharger les devoirs ===== | ||
- | Le devoir sera téléchargé sur [[https://vmchecker.cs.pub.ro | vmchecker]]. Connectez-vous au site à l'aide de l'utilisateur moodle, sélectionnez // Systemes d'Explotation (FILS) // et chargez [[#archive-devoir | archive de devoir]]. | ||
- | |||
- | ====Readme ==== | ||
- | Le fichier readme a le format suivant: | ||
- | |||
- | <code> | ||
- | Votre nom entier | ||
- | La groupe | ||
- | |||
- | Description de la résolution du devoir, pourquoi vous avez choisi des solutions, etc. | ||
- | </code> | ||
- | |||
- | |||
- | ==== Archivage de devoir ==== | ||
- | Pour télécharger le devoir, suivez les étapes suivantes: | ||
- | |||
- | - Créez une archive zip (pas rar, ace, 7zip ou autre format) contenant: | ||
- | * tous Python (*.py) | ||
- | * le fichier principal ayant le nom cmd.py | ||
- | * Fichier Readme - connectez-vous sur [[https://vmchecker.cs.pub.ro | vmchecker]] | ||
- | - sélectionnez le cours // Systemes d'Explotation (FILS) // | ||
- | - sélectionnez // 3. Mini-Shell // | ||
- | - téléchargez l'archive | ||
- | |||
- | |||
- | <note> | ||
- | L'archive doit contenir tous les fichiers (principaux) à la racine, pas dans les sous-répertoires. NE PAS archiver le répertoire du devoir, archiver les fichiers DIRECT. | ||
- | |||
- | N'incluez PAS les directoires spécifiques a la bibliotheque bashlex (pycache, bashlex, bashlex-0.14.dist-info). | ||
- | </note> | ||
- | |||
- | Après avoir chargé l'archive, vmchecker s'exécutera: | ||
- | <code bash> | ||
- | unzip archive.zip homework | ||
- | cd homework | ||
- | python3 cmd.py | ||
- | </code> | ||