This is an old revision of the document!
Le but de ce thème est de créer un shell simple, compatible avec sh
;
os.open
, os.read
, os.write
, …) os.fork
, os.exec
et 'os.waitpid' ', …) f.write()
, situation pour laquelle de devoir ne sera pas noté).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.
Si vous avez des questions sur le sujet, écrivez un problème sur le référentiel github repository avec le titre [mini-shell ] <le titre de votre question>. Vous avez besoin d'un compte github pour écrire des questions.
Si vous souhaitez recevoir un courrier électronique lorsque de nouvelles questions sont posées ou lorsque des réponses sont fournies, accédez à github repository et cliquez sur Regarder .
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.
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.
Le shell doit prendre en charge les opérateurs d'exécution suivants:
;
expr1; expr2
commencera par exécuter les commandes expr1
et les commandes expr2
seulement après l'exécution de expr1; &
expr1 & expr2
entraînera l'exécution de expr1
et des commandes expr2
en parallèle;execv ("./ my_homework", "command");
&&
et ||
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. |
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:
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 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:
commande $(commande ou liste commandes)
cmd.py
, qui peut etre utilisée comme un support pour le devoir. cmd.py
.Le devoirest relativement complexe par rapport au précédent. Un modèle pour le commencement du devoir est disponible sur le repository dans le répertoire tema3 . Nous vous recommandons de résoudre et de tester toujours le devoir, étape par étape:
ls
, ls -l
) cd
, exit
, 'quit' ') <',' ',' ',' ',' ','
,
>> , %
)&&
, ||
, ;
) &
(parallèle) |
$ 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
Cours utiles:
Laboratoires utiles:
Ressources:
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.
$ 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
En appelant parse.parse(line), on va renvoyer un objet de type Command.
Propriétés:
$(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
<
) >
, »
)2>
, 2»
, &>
, &»
)2»
, &»
)»
, &»
)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:
Le module parse expose les suivantes types d'opérations (la valeur de command.op):
cmd1 && cmd2
) cmd1 || cmd2 11
)cmd1 ; cmd2
) cmd1 & cmd2
) commande params
) cmd1 | cmd2
) a | b | c
, j'ai 3 fourchettes ou puis-je en avoir 4 ou 5? $ OLDPWD
et $ PWD
), historique, etc. - (voir man bash pour une idée de la fonctionnalité d'un shell complet )args = ["/bin/bash", "-c", command]; os.execv(args[0], args);
* A: Non.
os.execv
sur mon devoir pour exécuter une partie de l'arbre indépendamment?Le devoir sera téléchargé sur vmchecker. Connectez-vous au site à l'aide de l'utilisateur moodle, sélectionnez Systemes d'Explotation (FILS) et chargez archive de devoir.
Le fichier readme a le format suivant:
Votre nom entier La groupe Description de la résolution du devoir, pourquoi vous avez choisi des solutions, etc.
Pour télécharger le devoir, suivez les étapes suivantes:
N'incluez PAS les directoires spécifiques a la bibliotheque bashlex (pycache, bashlex, bashlex-0.14.dist-info).
Après avoir chargé l'archive, vmchecker s'exécutera:
unzip archive.zip homework cd homework python3 cmd.py