La ligne de commande
État :
Sommaire
Pré-requis
- Aucun
Objectifs
- Introduction au shell bash et aux concepts de base comme l'exécution interactive de programmes
- Distinguer les variables locales et globales (exportées)
- Manipuler les données à partir des tubes et des autres opérateurs de redirection
- Comprendre les caractères de substitution et les expansions de nom de fichiers (file globbing)
Présentation
La ligne de commande est un moyen simple d'interagir avec un ordinateur. Le shell interprète les commandes tapées au clavier. Le prompt, ou l'invite de commande, qui se termine par un $ ou un # pour l'administrateur, indique que le shell attend les commandes de l'utilisateur.
Le shell est également un langage de programmation qu'on peut utiliser pour lancer des tâches automatiquement. Les programmes shell sont appelés des scripts.
Shells les plus courants |
|
Le Bourne shell |
/bin/sh |
Le "Bourne again" shell |
/bin/bash |
Le Korn shell |
/bin/ksh |
Le C shell |
/bin/csh |
Tom's C shell |
/bin/tcsh |
le programme du LPI se concentre essentiellement sur le Bash, puisque c'est l'un des shells les plus couramment utilisés.
Le shell interactif
Les commandes shell suivent généralement la syntaxe suivante :
commande [options] {paramètres}
Afficher du texte à l'écran
Le bash utilise la commande echo pour afficher du texte à l'écran :
echo “Voici une courte ligne.”
Chemins relatif et absolu
Le shell interprète le premier "mot" de toute chaîne de caractère donnée comme une commande. Si cette chaîne est un chemin relatif ou absolu vers un fichier exécutable, alors le programme est exécuté. Si ce premier mot n'est pas précédé de /, alors le shell recherchera dans les répertoires définis dans la variable PATH et tentera de lancer la première commande qui correspondra à la chaîne.
Par exemple, si la variable PATH contient les répertoires /bin et /usr/bin, alors le système ne trouvera pas la chaîne xeyes puisque xeyes se trouve dans /usr/X11R6/bin/xeyes. Dans ce cas, vous devez entrer le chemin absolu de la commande :
/usr/X11R6/bin/xeyes
Mais on peut également utiliser le chemin relatif. Par exemple, si l'utilisateur est dans le répertoire où se trouve le programme xeyes, il peut taper :
./xeyes
Variables
Les variables du shell sont équivalentes aux variables utilisées dans les langages de programmation. Les noms de variables ne doivent contenir que des caractères alphanumériques. Par exemple, CREDIT=300 assigne tout simplement la valeur 300 à la variable nommée CREDIT.
initialiser une variable : Nom_Variable=valeur (sans espace !)
appeler une variable : $Nom_Variable
CREDIT=300 echo $CREDIT
On peut supprimer la valeur d'une variable avec la commande unset.
export, set et env
Il y a deux types de variables : les variables locales et les variables globales (exportées).
Les variables locales ne sont accessibles que sur le shell actif. Les variables exportées ou globales sont accessibles à la fois par le shell actif et par tous les processus fils lancés à partir de ce shell.
Les commandes set et env listent les variables définies.
Les commandes set et env |
|
set |
Liste toutes les variables |
env |
Liste les variables exportées |
Une variable globale est globale dans le sens où elle est accessible par tous les processus fils.
Variable locale |
Variable locale |
||
Parent |
Fils |
Parent |
Fils |
VAR=val |
VAR=? |
VAR=val |
VAR=val |
Exemple : exportez la variable CREDIT puis testez si elle est listée par set ou env.
export CREDIT env | grep CREDIT
Lancez un nouveau shell (processus fils) (NdT : en tapant bash) et vérifiez que la variable CREDIT est accessible. Peut-on lancer n'importe quel SHELL et être sûr que la variable CREDIT est toujours déclarée ?
Liste de variables courantes pré-définies :
Variable pré-définie |
Signification |
DISPLAY |
Utilisé par X pour identifier ou lancer une application cliente |
HISTFILE |
Chemin vers le fichier utilisateur .bash_history |
HOME |
Répertoire personnel de l'utilisateur |
LOGNAME |
Identifiant de connexion de l'utilisateur |
PATH |
Liste des répertoires utilisés par le shell pour exécuter des programmes quand une commande est entrée dans chemin |
PWD |
Répertoire de travail actuel |
SHELL |
Shell utilisé (bash dans la plupart des distributions Linux) |
TERM |
Émulation de terminal utilisée |
Variables spéciales
Les variables suivantes sont relatives à la gestion des processus :
Variable |
Signification |
$! |
PID du dernier processs fils |
$$ |
PID du shell actif |
$? |
valeur de sortie de la dernière commande : 0 = succès, 1 sinon |
Entrées, sorties et redirections
Les processus UNIX ouvrent trois descripteurs de fichiers standards (NdT : correspondant aux flux standards) qui permettent de traiter les entrées et sorties. Ces descripteurs standards peuvent être redéfinis pour chaque processus. Dans la plupart des cas, le descripteur stdin (entrée standard) est le clavier, et les deux descripteurs de sortie, stdout (sortie standard) et stderr (l'erreur standard), sont l'écran.
Un processus et ses 3 descripteurs de fichiers
STDIN < ------ PROCESSUS ---- > | ---- >> STDOUT | ---- | | 2> STDERR
Valeurs numériques pour stdin, stdout et stderr |
|
flux |
Valeur numérique |
stdin |
0 |
stdout |
1 |
stderr |
2 |
Redirection de la sortie standard
programme > fichier
Les données vont de gauche à droite.
fdisk –l > partitions.txt
Ceci lance fdisk et redirige la sortie vers le fichier partitions.txt. La sortie n'est pas visible a l'écran. Notez que le shell lit cette commande à partir de la droite : le fichier partitions.txt est d'abord créé s'il n'existait pas auparavant, écrasé dans le cas contraire car l'opérateur ">" est utilisé.
L'opérateur ">>" ajoute la sortie standard à un fichier.
Redirection de la sortie standard :
---- > ---- PROCESSUS ---- >> ---- FICHIER / PÉRIPHÉRIQUE ---- 1> ----
Redirection de l'entrée standard
programme < fichier
Dans ce cas, les données vont de droite à gauche. L'opérateur "<" ne peut être utilisé qu'avec stdin donc on ne peut pas l'utiliser avec les flux de sortie.
Si le fichier contient les instructions p, m et q (une instruction par ligne), alors dans l'exemple suivant fdisk affichera la table des partitions de /dev/hda, puis affichera l'aide puis quittera :
fdisk /dev/hda < instructions
Redirection de l'entrée standard :
PROCESSUS ---- < ---- FICHIER / PÉRIPHÉRIQUE ---- 0< ----
Redirection de l'erreur standard
programme 2> fichier_erreur
stdin, stdout et stderr sont représentés respectivement par 0, 1 et 2. Cela nous permet de choisir le flux d'erreur standard :
find / 2> /dev/null
Redirection de l'erreur standard :
PROCESSUS ---- 2> ---- FICHIER / PÉRIPHÉRIQUE
Les tubes
programme1 | programme2
Les tubes sont représentés par l'opérateur "|". Les données vont de gauche à droite. La figure suivante indique comment la sortie standard du premier processus est redirigée vers l'entrée standard du second processus.
Redirection à partir d'un tube :
PROCESSUS1 (stdout) ---- | ---- (stdin) PROCESSUS2
Exemple :
cat /var/log/messages | less
Note : Les redirections de sortie multiples sont analysées de droite à gauche, ainsi les commandes suivantes ne sont pas équivalentes :
commande 2>&1 > fichier commande >fichier 2>&1
La commande tee
commande | tee FICHIER
La commande tee est utilisée après un tube et prend comme paramètre un nom de fichier. La sortie standard de la commande précédente est alors écrite dans le fichier (NdT : comme avec ">") mais tee laisse le flux vers la sortie standard. La sortie standard est dupliquée.
Méta-caractères et guillemets
Les méta-caractères ont un sens spécial pour le shell. Ils sont la plupart du temps utilisés comme jokers, pour correspondre à plusieurs noms de fichiers ou de répertoires en utilisant un minimum de lettres.
Les caractères d'entrée (<), de sortie (>) et le tube (|) sont également des caractères spéciaux ainsi que le dollar ($) utilisé pour les variables. Nous ne les listerons pas ici, mais notez que ces caractères sont rarement utilisés pour nommer des fichiers standards.
Caractères génériques ou jokers
Le caractère * remplace n'importe quel nombre de caractères :
ls /usr/bin/b*
Liste tous les programmes commençant par "b".
Le caractère ? remplace n'importe quel caractère unique :
ls /usr/bin/?b*
Liste tous les programmes ayant un "b" pour seconde lettre.
[] est utilisé pour définir une plage de valeurs :
ls a[0-9]
liste tous les fichiers commençant par un "a" suivis d'un chiffre en seconde position.
ls [!Aa]*
liste tous les fichiers qui ne commencent pas par un "a" ni par un "A"
{chaîne1,chaîne2}; même si ce n'est pas simplement un joker de nom de fichiers, on peut l'utiliser pour filtrer des noms de fichiers :
ls index.{htm,html}
Guillemets et caractères d'échappement
On peut annuler la signification des jokers en utilisant des caractères d'échappement, qui sont également des caractères génériques.
L'antislash (\), qu'on appelle le caractère d'échappement, annule le sens de tous les caractères génériques, en forçant le shell à les interpréter littéralement.
Les guillemets simples, ou apostrophes (' ') annulent le sens de tous les caractères génériques sauf l'antislash.
Les guillemets (doubles) (" ") sont les guillemets faibles mais annulent la plupart des méta-caractères entourés à l'exception du tube (|), de l'antislash (\) et des variables ($var).
Les guillemets inversés ̀`
Les guillemets inversés exécutent la commande entourée. L'exemple suivant définit la variable TIME à partir de la commande date.
TIME="La date d'aujourd'hui est le `date +%a:%d:%b`” echo $TIME La date d'aujourd'hui est le mar.:06:juil.
Pour exécuter des commandes, on peut également utiliser $(). La commande sera exécutée et traitée comme une variable.
TIME=$(date)
L'historique des commandes
Pour voir la liste des commandes que vous avez tapé, vous pouvez utiliser la commande interne de bash history.
history 1 ls 2 grep 500 /etc/passwd
history liste les commandes en cache ainsi que celles sauvées dans ~/.bash_history. Lorsque que l'utilisateur quitte le shell, les commandes en cache sont inscrites dans ~/.bash_history.
Vous pouvez récupérer les commandes tapées en utilisant les flèches directionnelles (haut et bas) de votre clavier. Vous pouvez également utiliser des raccourcis emacs qui vous permettent d'exécuter et même de modifier ces lignes.
Raccourcis clavier Emacs pour l'historique des commandes :
Ctrl+p |
Ligne précédente (équivalent à la flèche haute) |
Ctrl+n |
Ligne suivante (Next) (= flèche basse) |
Ctrl+b |
Aller au caractère précédent sur la ligne (Back) (= flèche gauche) |
Ctrl+f |
Aller au caractère suivant (Forward) (=flèche droite) |
Ctrl+a |
Aller au début de la ligne (= touche Orig) |
Ctrl+e |
Aller en fin de ligne (End) (= touche Fin) |
Le point d'exclamation ! peut être utilisé pour relancer une commande.
Exemple :
!x lance la dernière commande de l'historique commençant par un "x" !2 lance la commande n°2 de l'historique !-2 lance l'avant dernière commande !! lance la dernière commande ^chaine1^chaine2 lance la dernière commande en remplaçant chaine1 par chaine2
Autres commandes
alias
Vous pouvez créer des alias pour des commandes nécessitant beaucoup de paramètres. La syntaxe d'alias est :
alias monprog='commande [options]{paramètres}'
alias tout seul donne la liste des alias déjà définis.
Auto-complètement de commandes
En appuyant sur TAB, le shell complète les commandes que vous avez commencé à taper.
<< est une redirection de EOF (fin de fichier)
Par exemple
cat << stop
accepte des entrées jusqu'à ce que "stop" soit tapé.
Commandes en chaîne
commande1; commande2; commande3
Ces trois commandes sont exécutées en séquence sans se préoccuper du résultat de la commande précédente.
commande1 && commande2 && commande3
Chaque commande sera exécutée seulement si la commande précédente a réussi (code de sortie 0) (NdT : && est un ET logique).
commande1 || comande2 || commande3
La commande suivante sera lancée uniquement si la précédente a échoué (code de sortie différent de 0) (NdT : || est un OU logique).
La commande "exec"
exec est une commande interne du bash utilisée pour lancer d'autres commandes. Normalement, quand vous lancez une commande, un sous-processus est créé. Si vous utilisez la commande exec pour lancer le nouveau programme, il remplace le processus qui l'a lancé, c'est à dire le shell pour un script ou un shell interactif.
Quand la commande se termine, le contrôle n'est pas redonné au shell, mais retourne au processus qui avait lancé le shell.
echo $$ 414 $ bash $ echo $$ 455 $ echo hello hello $ echo $$ 455 $ exec echo hello hello $ echo $$ 414
L'exemple précédent montre que le contrôle revient au second shell (processus 455) quand on lance la commande echo normalement, et au premier shell (processus 414) lorsqu'on utilise exec.
Les pages de manuel et la base whatis
Les pages de manuel sont organisées en sections, voici les principales sections que l'on devrait trouver dans une page de manuel :
NOM |
Le nom du sujet du manuel suivi par une brève ligne de description |
SYNOPSYS |
La syntaxe de la commande |
DESCRIPTION |
Une description plus détaillée |
OPTIONS |
Un tour de toutes les options possibles et leur fonction |
FICHIERS |
Fichiers en lien avec le sujet (fichiers de configuration, etc.) |
VOIR AUSSI |
Autres pages de manuel en lien avec le sujet |
La base de données whatis est un index de la description courte (section NOM) de l'ensemble des pages de manuel du système. Elle est actualisée par une tâche quotidienne cron. La base de données d'indexation whatis contient les deux champs suivants :
nom (clé) – description courte
La syntaxe de whatis est :
whatis <chaîne>
La sortie de la commande est la section NOM des pages de manuel pour lesquels la chaîne correspond à nom (clé).
La commande man permet également d'interroger la base de données d'indexation whatis en utilisant la syntaxe suivante :
man -k <chaîne>
Cette commande est équivalente à apropos. Contrairement à la commande whatis, ces commandes recherchent les correspondances dans les champs "nom" et "description courte". Si la chaîne correspond à un mot dans l'un des deux champs, la requête précédente renverra la section NOM entière.
Exemples : (les correspondances seront indiquées en gras quand je saurais le faire dans un espace de code...)
whatis lilo lilo (8) - Installer le chargeur de démarrage lilo.conf [lilo] (5) - Fichier de configuration pour lilo man -k lilo grubby (8) - Outil en ligne de commande pour configurer grub, lilo, et elilo lilo (8) - Installer le chargeur de démarrage lilo.conf [lilo] (5) - Fichier de configuration pour lilo
La FHS recommande de placer les pages de manuel dans /usr/share/man. Cependant, on peut rechercher dans d'autres répertoires en utilisant la variable d'environnement MANPATH, que l'on configure dans /etc/man.config. Chaque répertoire est ensuite divisé en sous-répertoires correspondants aux sections du manuel. (NdT : il ne faut pas confondre les sections du manuel avec les sections d'une page de manuel que nous venons de voir).
Sections du manuel |
|
Section 1 |
Programmes exécutables ou commandes de l'interpréteur de commandes (shell) |
Section 2 |
Appels système, par exemple mkdir(2) |
Section 3 |
Appels de bibliothèque, par exemple stdio(3) |
Section 4 |
Fichiers spéciaux (situés généralement dans /dev) |
Section 5 |
Formats des fichiers et conventions |
Section 6 |
Jeux |
Section 7 |
Divers |
Section 8 |
Commandes de gestion du système |
Section 9 |
Sous-programmes du noyau |
Pour accéder à une section du manuel en particulier, il faut utiliser la syntaxe suivante :
man N command
Exemples :
man mkdir man 2 mkdir man crontab man 5 crontab
Exercices et résumé
Questions de révision
Oui ou Non
Si la variable PATH n'est pas correctement paramétrée, les utilisateurs ne peuvent lancer les programmes qu'en tapant leur chemin complet ou relatif : _
On peut "tuber" la sortie standard STDOUT dans un fichier : _
Une fois qu'un flux de donnée est passé dans un tube, ce flux n'est généralement plus visible sur STDOUT : _
Toutes les commandes tapées dans le SHELL sont sauvegardées dans une base MySQL : _
Glossaire
Terme |
Description |
commandes chaînées |
Plusieurs commandes tapées sur une seule ligne en utilisant des séparateurs? Suivant le séparateur, le shell lancera les commandes différemment |
méta-caractère |
Caractère qui n'est pas interprété littéralement par le shell parce qu'il a un sens |
Expansion de nom de fichier (file globbing) |
Terme utilisé pour le traitement de plusieurs fichiers avec l'utilisation des méta-caractères. Le nom vient du sous-programme glob sur les anciens shell UNIX qui était utilisé pour "développer" les caractères génériques donnés en ligne de commande |
Redirection et tubes |
Opérations qui manipulent les flux de données et les descripteurs de fichiers d'un processus. Une redirection implique un processus et un fichier, alors qu'un tube n'implique qu'un processus |
stderr, stdin, stdout |
Nom des descripteurs de fichiers disponibles pour chaque processus pour diriger les messages d'erreur, lire les flux d'entrée et écrire les sorties (hors erreurs) |
caractères génériques |
Les méta-caractères suivants utilisés pour correspondre à plus d'un caractère lorsqu'on travaille en ligne de commande : *, ?, "{}" ou "[]" |
Commandes
Commande |
Description (ou apropos) |
alias |
configure un alias pour une commande ou une séquence de commandes (voir man builtins ou help alias) |
echo |
Affiche du texte sur STDOUT |
env |
Liste les variables exportées (voir man builtins ou help env) |
exec |
Commande intégrée au shell utilisée pour lancer un programme mais en remplaçant le processus qui l'a appelé au lieu de créer un processus fils |
export |
exporte la valeur de la variable dans l'environnement pour les commandes exécutées par la suite (voir man builtins ou help export) |
history |
Affiche la liste de l'historique des commandes avec le numéro des lignes (voir man builtins ou help history) |
tee |
Lire depuis l'entrée standard et écrire sur la sortie standard et dans des fichiers |
set |
Liste toutes les variables dans l'environnement du shell courant (voir aussi man builtins et help set) |
Travaux pratiques
Attention : Pour suivre les exercices, vous aurez besoin des commandes uuencode et uudecode. Vous les trouverez dans le paquet shareutils.
Stdin-stdout-stderr
Tapez les commandes suivantes et représentez si possible les séquences d'exécution sous la forme d'un diagramme équivalent à ceux utilisés dans ce chapitre.
ls /etc ; df > /tmp/out.1 (ls /etc ; df) > /tmp/out.2 find /etc -type f 2> /dev/null | sort tr [a-z] [A-Z] < /etc/passwd | sort > /tmp/passwd.tmp cat /tmp/passwd.tmp | tr [A-Z] [a-z]
Ligne de commande
- Affichez tous les fichiers de /usr/X11R6/bin qui ne commencent pas par un x
ls /usr/X11R6/bin/[!x]*
- La commande xterm a les options suivantes :
-bg <couleur> couleur d'arrière plan
-fg <couleur> couleur de premier plan
-e <commande> exécute
Créez un alias pour que la commande su ouvre un nouveau xterm en couleur et qu'il vous demande le mot de passe root.
alias su=”xterm -bg orange -fg brown -e su - &”
Où placeriez-vous cet alias pour le conserver sur le système ? Vous pouvez coder des fichiers (NdT : en fait, les convertir de binaires en texte) avec uuencode. Le fichier codé est redirigé vers stdout. Par exemple :
uuencode /bin/bash super-shell > uufichier
Cette commande convertit /bin/bash et produira un fichier nommé super-shell quand on utilisera uudecode sur le fichier codé uufichier.
Envoyez le fichier convertit uufichier par mail à un utilisateur local : vous pouvez soit utiliser uuencode et un tube | ou sauvegarder la sortie de uuencode dans un fichier uufichier, ce que l'on vient de faire, et utiliser un redirection de STDIN <.
- Coupez uufchier en 5 :
uuencode /bin/bash super-shell > uufichier split –b 150000 uufichier fichier-coupe
- Vous récupérerez des fichiers fichier-coupe.aa, fichier-coupe.ab, etc. Pour récupérer le fichier uufichier avec les données d'origine, faites :
cat fichier-coupe.* > uufichier.new
- Enfin, lancez uudecode sur ce fichier et regardez si ça fonctionne.
uudecode uufichier.new
Cette commande devrait créer un fichier binaire nommé super-shell.
- Quel outil indique le chemin complet vers un exécutable en examinant la variable PATH ?
Variables
- Suivez les instructions suivantes :
- Assignez la valeur "virus" à la variable ALERT :
ALERT=virus
Vérifiez que la variable est définie en utilisant la commande set :
set |grep ALERT
La variable ALERT est-elle listée si vous utilisez env au lieu de set ? Ensuite, tapez "bash". Pouvez-vous accéder à votre variable ALERT ?
bash echo $ALERT
- Notez la value de ALERT : (est-ce vide ?)
Tapez exit ou (^D) pour retourner à votre session.
Utilisez la commande export pour rendre la variable ALERT globale
export ALERT
Vérifiez que la variable est globale avec env.
env | grep ALERT
- Lancez un nouveau shell bash et vérifiez que ALERT est définie dans ce shell :
bash echo $ALERT
- Dans ce nouveau shell, modifiez la variable ALERT et exportez la :
export ALERT=green
Quittez ce shell. Quelle est la valeur de ALERT dans le shell d'origine ?
- Assignez la valeur "virus" à la variable ALERT :
- À l'invite de commande, tapez les lignes suivantes :
CREDIT01=300;CREDIT02=400 for VAR in CREDIT01 CREDIT02;do echo $VAR;done
Remarquez que la variable VAR est référencée avec $VAR.- Relancez cette (deuxième) commande
- Relancez cette (deuxième) commande en remplaçant CREDIT01 par $CREDIT01
- Modifiez la variable PS1 pour afficher le chemin complet de votre répertoire de travail.
(Indication : la valeur de PS1 est [\u@ \W]\$, il vous suffit de remplacer \W par \w).
PS1='[\u@\h \w ]\$ '
Réponses aux questions
Oui
Non : STDOUT peut être redirigé vers un fichier
Oui
Non : les commandes sont en général stockées dans le fichier .bash_history du répertoire personnel de l'utilisateur.