Serveur d'impression

Script shell Unix avec ksh / bash – Serveur d’impression

Le 3 mai 2019 - 76 minutes de lecture

Script shell Unix avec ksh / bash

Sommaire

Document du cours: (dernière mise à jour le 22 mars 2012)

Ces notes sont disponibles sur http://www.dartmouth.edu/~rc/classes/ksh. La version en ligne contient de nombreux liens vers des informations supplémentaires et peut être plus à jour que les notes imprimées.


Les objectifs de cette classe sont de vous permettre de:

  • Découvrez quels types de problèmes conviennent aux scripts shell
  • Passez en revue les commandes Unix les plus couramment utilisées et utiles dans les scripts de shell.
  • Écrire des scripts shell simples en utilisant les shells Bourne, Korn ou Bash

Ces notes sont destinées à être utilisées dans un cours en deux parties, d’une durée totale de 3 heures.

Hypothèses:
On suppose que vous savez déjà comment:

  • connectez-vous et obtenez une fenêtre de ligne de commande (n'importe quel shell)
  • exécuter des commandes de base, naviguer dans les répertoires
  • utiliser une redirection simple d'E / S et des tubes
  • utiliser un éditeur de texte (n'importe lequel)
  • recherche des détails sur l'utilisation des commandes dans les pages de manuel

Des exemples de commandes sont affichés comme ça. Beaucoup de commandes
sont affichés avec des liens vers leurs pages de manuel complètes
(sh)
La sortie des commandes est affichée comme ça;
les éléments optionnels sont [ in brackets ].

Certaines descriptions dans ces notes ont plus de détails disponibles,
et sont notés comme ceci:

Plus de détails sur cet article apparaissent ici. Les notes imprimées
inclure toutes les informations supplémentaires


La permission est donnée de télécharger et d’utiliser ces notes et exemples de scripts, à condition que
tous les avis de droits d'auteur sont conservés intacts. Certains exemples sont tirés de textes
ou des ressources en ligne qui ont autorisé la redistribution.


Ces notes sont mises à jour de temps en temps. Le développement"
ensemble de notes sont
 http://northstar-www.dartmouth.edu/~richard/classes/ksh
(Dartmouth seulement)

Richard Brittain, Services informatiques du Dartmouth College.

© 2003,2004,2010 Dartmouth College.

Commentaires et questions, contactez Richard.Brittain @ dartmouth.edu


Meilleur visionné avec n'importe quel navigateur
Propulsé par Vi


Table des matières

(1)

  • Un fichier texte contenant des commandes qui auraient pu être saisies directement dans le shell.

    Il n'y a pas de différence de syntaxe entre l'utilisation interactive de la ligne de commande et le placement des commandes
    dans un fichier. Certaines commandes ne sont utiles que lorsqu'elles sont utilisées de manière interactive (par exemple, rappel de l'historique en ligne de commande).
    et les autres commandes sont trop complexes pour pouvoir être utilisées de manière interactive.

  • Le shell lui-même a des capacités limitées – le pouvoir provient de son utilisation comme "colle"
    langue pour combiner les utilitaires Unix standard et un logiciel personnalisé, pour produire un outil
    plus utile que les composants seuls.
  • Tout shell peut être utilisé pour écrire un script shell. Pour permettre cela, la première ligne de chaque script
    est:
    #! / chemin / vers / shell (par exemple. #! / bin / ksh).

    le #! les caractères indiquent au système de localiser le chemin suivant, de le démarrer et de
    alimentez le reste du fichier en entrée.
    Tout programme capable de lire les commandes d’un fichier peut être démarré de cette manière, à condition que
    reconnaît le # convention de commentaires. Le programme est lancé, puis le fichier de script
    est donné comme argument. Pour cette raison, le script doit être lisible et exécutable.
    Les exemples sont perl, awk, tcl et python.

  • Tout fichier peut être utilisé comme entrée dans un shell en utilisant la syntaxe suivante:
    ksh myscript
  • Si le fichier est rendu exécutable avec chmod, cela devient une nouvelle commande
    et disponible pour utilisation (sujet à la recherche habituelle de $ PATH).
    chmod + x myscript

Un script shell peut être aussi simple qu'une séquence de commandes que vous tapez régulièrement. En mettant
les dans un script, vous les réduisez à une seule commande.

Exemple: ex0 affichage, texte


            1: #! / bin / sh
            2: rendez-vous amoureux
   3: pwd
            4: du -k

(2)

  • Combinez des séquences de commandes longues et répétitives en une seule commande simple.
  • Généraliser une séquence d'opérations sur un ensemble de données, en une procédure pouvant être
    appliqué à tout ensemble similaire de données.

    (par exemple.
    appliquer la même analyse à chaque fichier de données sur un CD, sans avoir à répéter les commandes)

  • Créer de nouvelles commandes en utilisant des combinaisons d’utilitaires comme les auteurs originaux
    jamais pensé à.
  • Des scripts shell simples peuvent être écrits sous la forme d'alias shell, mais le script peut être mis à la disposition de tous les utilisateurs.
    et tous les processus. Les alias de shell s'appliquent uniquement au shell actuel.
  • Enveloppez les programmes sur lesquels vous n'avez aucun contrôle dans un environnement que vous pouvez contrôler.

    par exemple. définir des variables d'environnement, basculer vers un répertoire spécial, créer ou sélectionner un fichier de configuration,
    redirigez la sortie, enregistrez l’utilisation, puis exécutez le programme.

  • Créez des jeux de données personnalisés à la volée et appelez des applications (par exemple, matlab, sas, idl, gnuplot) pour fonctionner
    sur eux, ou créer des commandes / procédures d’application personnalisées.
  • Prototypage rapide (mais évitez de laisser les prototypes devenir production)

Utilisations typiques

  • Scripts de démarrage du système (/etc/init.d)
  • Administrateurs système, pour automatiser de nombreux aspects de la maintenance informatique, compte utilisateur
    création etc.
  • Outils d'installation du package d'application

    D'autres outils peuvent créer des installateurs plus sophistiqués (par exemple, tcl / tk), mais ne peuvent pas être considérés comme déjà installés. Les scripts shell sont utilisés car ils sont très portables. Certains logiciels sont livrés avec une installation complète de l'outil qu'il veut utiliser
    (tcl / tk / python) pour être autonome, mais cela conduit à un gonflement logiciel.

  • Scripts de démarrage d'application, en particulier
    applications sans surveillance (par exemple, à partir de cron ou à)
  • Tout utilisateur ayant besoin d'automatiser le processus de configuration et d'exécution d'applications commerciales,
    ou leur propre code.

AUTOMATISER, AUTOMATISER, AUTOMATISER

(3)

sh
"Bourne", écrit par Steve Bourne chez AT & T Bell Labs pour Unix V7 (1979).
Petit, simple et (à l'origine) très peu de commandes internes, donc il a appelé des programmes externes pour même le plus simple
des tâches. Il est toujours disponible sur tout ce qui ressemble vaguement à Unix.

csh

La coquille "C". (Bill Joy, à Berkeley).
Beaucoup de choses en commun
avec le shell Bourne, mais de nombreuses améliorations pour améliorer l’utilisation interactive. L'interne
les commandes utilisées uniquement dans les scripts sont très différent de "sh", et
similaire (par conception) à la syntaxe du langage "C".


tcsh

Le shell "TC". Librement disponible et basé sur "csh".
Il comporte de nombreuses fonctionnalités supplémentaires pour rendre l'utilisation interactive plus pratique.

Nous l'utilisons comme shell interactif par défaut pour les nouveaux comptes sur tous nos systèmes publics.

Peu de gens écrivent des scripts dans
Voir la programmation de Csh considérée comme nuisible par
Tom Christiansen pour une discussion sur les problèmes de programmation des scripts csh.

ksh
Le "Korn" shell, écrit par David Korn de AT & T Bell Labs (maintenant AT & T Research).
Écrit comme une mise à niveau majeure vers "sh" et une compatibilité ascendante avec celui-ci, mais possède de nombreuses commandes internes pour le
fonctions les plus fréquemment utilisées. Il intègre également de nombreuses fonctionnalités de tcsh qui améliorent
utilisation interactive (rappel de l'historique de ligne de commande, etc.).

L’acceptation a été lente, car les versions précédentes étaient grevées de licences AT & T.
Ce shell est maintenant disponible gratuitement sur tous les systèmes, mais n'est parfois pas installé par défaut sur Unix "libre".
Il existe deux versions principales. ksh88 était la version intégrée à AT & T SVR4 Unix, et peut encore être installé
par certains des vendeurs Unix commerciaux. ksh93 a ajouté plus de fonctionnalités, principalement pour la programmation, et une meilleure conformité POSIX.

POSIX 1003.2 Standard Shell.
Les comités de normalisation ont travaillé sur le shell Bourne et ont ajouté de nombreuses fonctionnalités au shell Korn (ksh88).
C shell pour définir un ensemble standard de fonctionnalités que doivent posséder tous les shells conformes.

Sur la plupart des systèmes, / bin / sh est maintenant un shell compatible POSIX.
Korn shell et Bash sont compatibles POSIX, mais possèdent de nombreuses fonctionnalités qui vont au-delà de la norme.
Sous Solaris, les commandes POSIX / XPG4 qui diffèrent
légèrement dans le comportement des commandes SunOS traditionnelles se trouvent dans / usr / xpg4 / bin

frapper
La coquille "Bourne again". Ecrit dans le cadre de l’effort Open Source GNU / Linux et du shell par défaut pour Linux et
Mac OS X. C'est un clone fonctionnel de sh, avec des fonctionnalités supplémentaires pour améliorer l'utilisation interactive,
ajouter la conformité POSIX et la compatibilité partielle de ksh.

zsh
Un clone fonctionnel gratuit de sh, avec des éléments de ksh, bash et une conformité POSIX complète, et
nombreuses nouvelles fonctionnalités d'édition en ligne de commande interactives.
Il a été installé en tant que shell par défaut sur les anciens systèmes MacOSX.

(4)

Tous les shells énumérés ci-dessus partagent certaines caractéristiques communes et les différences majeures de syntaxe.
généralement, n'affectent que les scénaristes. Ce n'est pas inhabituel
utiliser un shell (par exemple, tcsh) pour une utilisation interactive, mais un autre (sh ou ksh)
pour écrire des scripts.

Principales similitudes (et récapitulation de l'utilisation de base de la ligne de commande)

Chacun de ces éléments est traité plus en détail ultérieurement.

  • Analyser les lignes par des espaces, rechercher des commandes externes à l'aide de $ PATH.
  • Peut exécuter un script shell en utilisant shellname scriptfile, ou exécuter un seul
        commande en utilisant shellname -c "commande"
  • Transmettez les arguments de ligne de commande développés aux programmes; récupérer le statut de sortie.
  • Passer des variables d'environnement aux programmes.
  • Développez les jokers de nom de fichier en utilisant []*?. Chaque coquille a quelques autres
    métacaractères génériques, mais ceux-ci sont communs à tous les shells.
  • Redirection I / O standard et tuyauterie avec <,>, >>, |
  • Quelques fonctions internes (CD)
  • Commandes d'arrière-plan avec Et
  • Règles de cotation: les "guillemets" protègent la plupart des choses, mais permettent $ var interprétation;
    Les "guillemets simples" protègent tous les métacaractères de l'interprétation.
  • Extension du répertoire personnel à l'aide de ~ utilisateur (à l'exception de sh)
  • # commentaires
  • Substitution de commande en utilisant `commande` (backtics)
  • Développez les variables en utilisant $ varname syntaxe
  • Exécution conditionnelle utilisant && et ||
  • Suite de ligne avec ""

Principales différences

entre sh (+ dérivés) et csh (+ dérivés).

  • Syntaxe de toutes les constructions de contrôle de flux et des tests conditionnels.
  • Syntaxe de manipulation des chaînes dans les scripts
  • Syntaxe pour la manipulation arithmétique à l'intérieur des scripts
  • Syntaxe de définition des variables locales (utilisées uniquement dans le script) et des variables d’environnement
    passé aux processus enfants). setenv contre exportation
  • Syntaxe de redirection des flux d'E / S autres que stdin / stdout
  • Fichiers de démarrage de connexion (.cshrc et .s'identifier, contre .profil) et les options par défaut
  • Lecture d’autres scripts shell dans le shell actuel (nom de fichier source, contre . nom de fichier)
  • Traitement des signaux (interruptions)

(5)

Il existe de nombreux autres programmes qui lisent un fichier de commandes et exécutent
une séquence d'actions. le "#! / chemin / à / programme" convention
permet à n'importe lequel d'entre eux d'être utilisé comme langage de script pour créer de nouvelles commandes.
Certains sont hautement spécialisés, et certains sont beaucoup plus efficaces que leurs équivalents
scripts shell à certaines tâches. Il n'y a jamais qu'un seul moyen d'effectuer une fonction,
et souvent, le choix dépend de facteurs tels que:

  • ce qui est déjà installé – beaucoup d'autres langages de script ne sont pas disponibles par défaut
  • quel code similaire existe déjà
  • ce que vous connaissez et pouvez utiliser de la manière la plus efficace.
    Votre temps est toujours plus coûteux que les cycles informatiques.

Certains des principaux acteurs (tous disponibles gratuitement) dans les langages de script à usage général sont:

  • awk

    Un outil de correspondance de modèle et de manipulation de données (texte et numérique). Prédate perl. Installé sur
    tous les systèmes Unix. Souvent utilisé en combinaison avec des scripts shell.

  • perl

    Le langage de script le plus utilisé pour les applications Web CGI et les tâches d'administration système. Perl
    est plus difficile à apprendre et est généralement installé par défaut maintenant.
    Il est plus efficace et dispose d’une énorme bibliothèque de fonctions. Vous pouvez utiliser Perl pour
    presque toutes les tâches de script, mais la syntaxe est très différente de la ligne de commande du shell

  • python

    Un langage de script orienté objet. Communément installé par défaut sur les systèmes modernes.

  • tcl/tk

    Langage de commande de l'outil. Un autre langage de script à usage général. Le composant "tk" est un
    interface scriptée vers les composants graphiques X-windows standard, la combinaison est donc souvent utilisée
    créer des interfaces utilisateur graphiques.

    Ksh93 peut être étendu en se connectant à des bibliothèques partagées fournissant des commandes internes supplémentaires. Un exemple
    d'une coquille étendue est
    tksh

    qui intègre Tcl / Tk avec ksh et permet la génération de
    scripts utilisant les deux langues. Il peut être utilisé pour le prototypage d'applications d'interface graphique.

(6)

Ksh et bash sont les deux super-ensembles de sh. Pour une portabilité maximale, même très ancienne
ordinateurs, vous devriez vous en tenir aux commandes trouvées dans sh. Si possible, fonctionnalités spécifiques à ksh ou bash
sera noté dans les pages suivantes. En général, les nouveaux obus courent un peu plus vite
et les scripts sont souvent plus lisibles, car la logique peut être exprimée plus proprement au plus récent
syntaxe. De nombreuses commandes et tests conditionnels sont maintenant internes.

La philosophie des outils Unix séparés effectuant chacun un seul
opération a été suivie de près par les concepteurs de la coque d'origine, de sorte qu'il
avait très peu de commandes internes et
utilisé des outils externes pour des opérations très triviales
(comme écho et [[[[). Ksh et bash en interne
effectue un grand nombre de manipulations numériques et de chaînes de base et de tests conditionnels. Problèmes occasionnels
se pose parce que les versions internes de certaines commandes comme écho ne sont pas entièrement compatibles avec
l'utilitaire externe ils ont remplacé.

L'action entreprise chaque fois qu'un shell doit exécuter un programme externe consiste à localiser le programme.
(via $ PATH), fourchette(), qui crée une deuxième copie du shell,
ajustez l'entrée / sortie standard pour le
programme externe, et exec (), qui remplace le second shell par le programme externe.
Ce processus est onéreux en termes de calcul (relativement), donc lorsque le script fait quelque chose de trivial
plusieurs fois dans une boucle, cela fait gagner beaucoup de temps si la fonction est gérée en interne.

Si vous suivez des manuels sur la programmation du shell Bourne, tous les conseils doivent être valables
lequel des coquillages dérivés de Bourne que vous utilisez. Malheureusement, de nombreux fournisseurs ont ajouté des fonctionnalités au fil des ans
et atteindre la portabilité complète peut être un défi. Écrire explicitement pour ksh (ou bash) et insister
sur ce shell en cours d'installation, peut souvent être plus simple.

Le sh et le ksh homme les pages utilisent le terme commande spéciale pour les commandes internes – gérées par le shell
lui-même.

(7)

Le script shell le plus élémentaire est une liste de commandes exactement telles qu’elles pourraient être.
dactylographié de manière interactive, préfacé par le #! en-tête magique.
Toutes les règles d'analyse, les caractères génériques de nom de fichier, les recherches $ PATH, etc., qui ont été résumés
ci-dessus, appliquer.

En outre:

# en tant que premier caractère non blanc sur une ligne
marque la ligne en tant que commentaire et le reste de la ligne est complètement ignoré. Utilisation
commente librement dans vos scripts, comme dans toutes les autres formes de programmation.
comme dernier caractère d'une ligne
provoque la jointure logique de la ligne suivante avant interprétation. Ceci permet
commandes très longues à saisir dans le script de manière plus lisible. Tu peux continuer
la ligne autant de fois que nécessaire.

Ceci est en fait juste un cas particulier de Être à échapperou supprimer
la signification spéciale de, le caractère suivant.

; comme séparateur entre les mots d'une ligne
est interprété comme une nouvelle ligne. Il vous permet de placer plusieurs commandes sur une seule ligne. Il y a
quelques occasions où vous doit faire cela, mais souvent il est utilisé pour améliorer la mise en page
des commandes composées.

Exemple: affichage ex1, texte


            1: #! / bin / ksh
            2: # Aux fins d’affichage, certaines parties du script ont 
            3: # été rendu en technicolor glorieux.
            4: ## Certains commentaires sont en gras pour signaler les sections spéciales
            5: 
            6: # Les numéros de ligne à gauche ne font pas partie du script.
            7: # Ils sont simplement ajoutés au HTML pour référence.
            8: 
            9: # Les commandes intégrées et les mots-clés (par exemple, print) sont en bleu
        dix: # Les substitutions de commandes sont violettes. Les variables sont noires
        11: impression "Résumé de l'utilisation du disque pour $ USER sur `rendez-vous amoureux`"
  12: 
        13: # Tout le reste est rouge - ce qui est principalement externe 
        14: # commandes et les arguments de toutes les commandes.
        15: impression Ce sont mes fichiers       # commentaire de fin de ligne pour impression
        16: # Liste les fichiers en colonnes
        17: ls -C
  18: # Résumer l'utilisation du disque
        19: impression
        20: impression Utilisation de l'espace disque
  21: du -k 
  22: sortie 0

Statut de sortie

Chaque commande (programme) a un valeur ou statut de sortie
qu'il retourne au programme appelant. Ce
est séparé de toute sortie générée. Le statut de sortie d'un script shell peut être défini explicitement à l'aide de
sortie Nou la valeur par défaut de la dernière commande exécutée.

Le statut de sortie est un entier compris entre 0 et 255. Conventionnellement 0 = succès et
toute autre valeur indique un problème. Pensez-y comme à un seul moyen pour que tout
travailler, mais de nombreuses façons d’échouer. Si la commande s'est terminée par un signal, la valeur est 128 plus
la valeur du signal.

(8)

Le shell interprète les caractères suivants comme des caractères génériques de nom de fichier, et
tout mot les contenant est remplacé par une liste triée de tous les fichiers correspondants.

Les caractères génériques peuvent être utilisés dans les parties de répertoire d'un chemin ainsi que dans la partie de nom de fichier.
Si aucun fichier ne correspond au caractère générique, celui-ci reste inchangé.
Les caractères génériques ne sont pas des expressions régulières complètes. Sed, grep, awk etc. fonctionnent avec plus de souplesse (et plus
complexes) opérateurs de correspondance de chaînes.

*
Correspond à zéro ou plusieurs caractères.
?
Correspondre à n'importe quel personnage
[...]
Faites correspondre n'importe quel caractère de l'ensemble entre crochets. Une plage de caractères peut être spécifiée
avec [ - ]
[!...]
Associez n'importe quel caractère non inclus dans l'ensemble entre crochets.
  • Une initiale "." dans un nom de fichier ne correspond pas à un caractère générique, sauf si explicitement
    donné dans le motif. En ce sens, les noms de fichiers commençant par "." sont cachés.
    UNE "." ailleurs dans le nom de fichier n'est pas spécial.
  • Les opérateurs de modèle peuvent être combinés

Exemple:
chapitre[1-5]. * pourrait correspondre chapitre1.tex, chapitre4.tex, chapitre5.tex.old.
Cela ne correspond pas chapitre10.tex ou chapitre 1

(9)

Les scripts ne sont pas très utiles si toutes les commandes, options et noms de fichiers sont explicitement
codé. En utilisant des variables, vous pouvez créer un script générique et l’appliquer à différents
des situations. Les noms de variables sont composés de lettres, de chiffres et de traits de soulignement
 ([a-zA-Z0-9_], ne peut pas commencer par un nombre, et sont des cas
sensible. Plusieurs variables spéciales (toujours des noms en majuscule) sont utilisées par le système – en les réinitialisant.
peut provoquer un comportement inattendu. Certaines variables spéciales peuvent être en lecture seule.
L'utilisation de noms minuscules pour vos propres variables est la plus sûre.

Définition et exportation de variables

srcfile = dataset1
Crée (si elle n’existait pas) une variable nommée "srcfile" et lui attribue la valeur "dataset1". Si la
La variable existait déjà, elle est écrasée. Les variables sont traitées comme des chaînes de texte, sauf si le contexte
implique une interprétation numérique. Vous pouvez faire en sorte qu'une variable soit toujours traitée comme un nombre. Notez ici
doit être sans espaces autour du "=".
ensemble
Afficher toutes les variables actuellement définies dans le shell
non fixé srcfile
Supprimer la variable "srcfile"
srcfile =
Donnez à la variable une valeur nulle (ce n'est pas la même chose que de la supprimer).
exportation srcfile
Ajout de srcfile à la liste des variables qui seront mises à la disposition du programme externe via
l'environnement. Si vous ne le faites pas, la variable est locale pour cette instance de shell.
exportation
Répertorie toutes les variables en cours d’exportation – c’est l’environnement qui sera transmis.
aux programmes externes.

En utilisant des variables

$ srcfile
Préfacer le nom de la variable avec $ provoque la valeur de la variable à
être substitué à la place du nom.
$ srcfile
Si la variable n'est pas entourée d'espaces (ou d'autres caractères qui ne peuvent pas être dans un nom),
le nom doit être entouré d'accolades ""
afin que le shell sache quels caractères vous voulez faire partie du nom.

Exemple:



fichier de données = recensement2000
# Essaie de trouver $ datafile_part1, qui n'existe pas
echo $ datafile_part1.sas
# C'est ce que nous voulions
echo $ datafile _part1.sas  

Modificateurs conditionnels

Il existe différentes manières d’utiliser conditionnellement une variable dans une commande.

$ datafile-default
Substituez la valeur de $ fichier de données, s’il a été défini, sinon utilisez la chaîne "default". C'est facile
moyen de permettre des variables optionnelles, et avoir des valeurs par défaut raisonnables si elles n’ont pas été définies. Si fichier de données était
indéfini, il en reste ainsi.
$ datafile = default
Similaire à ce qui précède, sauf si fichier de données n'a pas été défini, définissez-le sur la chaîne "default".
$ datafile + default
Si variable fichier de données a été défini, utilisez la chaîne "default", sinon utilisez null. Dans ce cas, le
valeur actuelle $ fichier de données N'est pas utilisé.
$ datafile? "message d'erreur"
Substituez la valeur de $ fichier de données, s'il a été défini, sinon affichez datafile: message d'erreur.
Ceci est utilisé pour les diagnostics lorsqu'une variable aurait dû être définie et qu'il n'y a pas de valeur par défaut raisonnable à utiliser.

Placer un colon (:) avant que le caractère opérateur dans ces constructions ait pour effet de compter un
nul valeur identique à une variable non définie. Les variables peuvent recevoir une valeur nulle en les définissant
en une chaîne vide, par exemple fichier de données = .

Exemple:
echo $ datafile: -mydata.dat
Écho de la valeur de variable fichier de données s'il a été défini et est non nul, sinon
echo "mydata.dat".

Préfixe de commande d'attribution de variable

Il est possible d’exporter une variable pour la durée d’une seule commande en utilisant le
syntaxe:

var = valeur commande args

(dix)

Le système utilise plusieurs variables spéciales. Vous pouvez les utiliser, mais vous ne pourrez peut-être pas
pour les changer.
Les variables spéciales utilisent des noms en majuscules ou des caractères de ponctuation.
Certaines variables sont définies par le processus de connexion et héritées par le shell (par exemple, $ USER),
tandis que d'autres ne sont utilisés que par le shell.
Essayez de courir ensemble ou env
Voici quelques-uns des plus couramment utilisés:

Environnement de connexion

$ USER, $ LOGNAME
Prédéfini sur le nom d'utilisateur actuellement connecté.
$ PATH
La liste des répertoires qui seront recherchés pour les commandes externes. Vous pouvez changer cela dans un script
pour vous assurer que vous obtenez les programmes que vous avez l'intention, et ne pas obtenir accidentellement d'autres versions qui pourraient avoir été
installée.
$ TERM
Le type de terminal dans lequel la session shell est en cours d'exécution. Habituellement, "xterm" ou "vt100". Beaucoup de programmes
Vous devez savoir cela pour savoir quelles séquences de caractères spéciaux envoyer pour obtenir des effets spéciaux.
$ PAGER
S'il est défini, il contient le nom du programme que l'utilisateur préfère utiliser pour afficher les fichiers texte. habituellement
régler sur "plus" ou "moins" ou quelque chose de similaire. De nombreux programmes devant présenter des informations sur plusieurs pages
l'utilisateur respectera ce paramètre (par exemple, homme). Ce n'est pas réellement utilisé par le shell lui-même, mais
Les scripts shell doivent l’honorer s’ils doivent émettre une page vers l’utilisateur.
$ EDITEUR
Si défini, ceci contient le nom du programme que l'utilisateur préfère utiliser pour l'édition de fichier texte. Un programme
qui doit obliger l’utilisateur à éditer manuellement un fichier peut choisir de démarrer ce programme au lieu de
par défaut intégré (par exemple "crontab -e". Ceci détermine également la modification de la ligne de commande par défaut.
comportement dans des coquilles interactives.

Paramètres internes du shell

$ PWD
Toujours définir le répertoire de travail actuel (en lecture seule)
$ OLDPWD
Le répertoire précédent (avant le plus récent CD commander). Cependant, changer de répertoire
dans un script est souvent dangereux.
$? (lecture seulement)
Définissez le statut de sortie de la dernière commande exécutée afin de pouvoir tester le succès ou l'échec. Chaque commande réinitialise cette
il faut donc le sauvegarder immédiatement si vous voulez l’utiliser plus tard.
$ -
Définissez les options actuellement définies.
$ IFS
Séparateurs de champs internes: ensemble de caractères (normalement des espaces et des tabulations) utilisés pour analyser
une ligne de commande en arguments séparés. Ceci peut être défini par l'utilisateur à des fins spéciales, mais
les choses deviennent très déroutantes si rien n'est changé.

Variables d'ID de processus

$$ (lecture seulement)
Défini sur l'ID de processus du shell actuel – utile pour créer des fichiers temporaires uniques, par exemple. /tmp/$0.$$
$ PPID (lecture seulement)
Défini sur l'ID de processus du processus parent de ce shell – utile pour découvrir comment le script a été appelé.
$! (lecture seulement)
Défini sur l'ID de processus de la dernière commande démarrée en arrière-plan – utile pour vérifier les processus en arrière-plan.

ksh / bash fonctionnalités supplémentaires

$ SECONDES (lecture seulement)
Nombre entier de secondes depuis le démarrage de ce shell. Peut être utilisé pour les commandes de chronométrage.
$ RANDOM
Chaque fois qu'il est valorisé, $ RANDOM renvoie un entier aléatoire compris entre 0 et 32k. AU HASARD

peut être réglé sur "semer" le générateur de nombres aléatoires.

$ LINENO (lecture seulement)
Evalue toujours le numéro de ligne actuel du script en cours d'exécution – utile pour le débogage.

(11)

Pour personnaliser le comportement d'un script au moment de l'exécution,
vous pouvez lui donner un nombre quelconque d'arguments sur la commande
ligne.

Ce sont souvent des noms de fichiers, mais peuvent être interprétés par le script de quelque manière que ce soit. Les options
sont souvent spécifiés en utilisant la convention "-flag" utilisée par la plupart des programmes Unix, et une commande ksh
getopts est disponible pour aider à les analyser.

Le shell développe les caractères génériques et rend variable et
substitutions de commandes comme d'habitude, puis analyse les mots obtenus par des espaces (en réalité
variable spéciale $ IFS) et place les chaînes de texte résultantes dans
variables de position
comme suit:

0 $, 1 $, 2 $, ... 9 $
Les 9 premiers arguments sont disponibles directement sous forme de $ 1-9 $. Pour accéder à plus de 9, utilisez
décalage, ou $ *, $ @. La variable 0 $ contient le nom du
script lui-même.
$ 10, $ 11, ...
Les arguments positionnels supérieurs à 9 sont définis par ksh et bash. N'oubliez pas d'utiliser des accolades pour vous y référer.
décalage
ignore $ 1 et renumérote toutes les autres variables. "décalage N"déplacera N arguments à la fois.
$ #
contient le nombre d'arguments définis (non compris $ 0).
$ *
contient tous les arguments dans une seule chaîne, avec un espace les séparant.
$ @
semblable à $ *, mais s'il est utilisé entre guillemets, il cite efficacement chaque argument et les maintient séparés.
Si un argument contient des espaces, la distinction est importante.

par exemple. si la liste d'arguments est: a1 a2 "a3 qui contient des espaces" a4
alors: $ 1 = a1, $ 2 = a2, $ 3 = a3 qui contient des espaces, $ 4 = a4
et: $ * = a1 a2 a3 qui contient des espaces a4
et: "$ @" = "a1" "a2" "a3 qui contient des espaces" "a4"

Utiliser uniquement le formulaire "$ @" préserve les arguments cités. Si les arguments sont passés du script
directement à un autre programme, cela peut faire une grande différence quant à la signification.

Exemple: affichage ex7, texte


            1: #! / bin / sh
            2: #
            3: # Vérifier la gestion des arguments de position
            4: écho "Nombre d'arguments: $ #"
   5: écho "0 $ = 0 $"
   6: 
            7: écho "Boucle sur $ *"
   8: pour un dans $ *; faire
            9:    écho  "$ a "
  dix: terminé
        11: 
        12: écho "Boucle sur " $ @ ""
  13: pour un dans "$ @"; faire
        14:    écho  "$ a "
  15: terminé

Définir de nouveaux arguments de position

le ensemble commande, suivie d'un ensemble d'arguments, crée un nouvel ensemble de
arguments de position. Ceci est souvent utilisé, en supposant que les arguments originaux ne sont plus nécessaires, pour analyser
un ensemble de mots (en utilisant éventuellement des séparateurs de champs différents). Les arguments peuvent être réinitialisés autant de fois que nécessaire.

Exemple: affichage ex2, texte


            1: #! / bin / sh
            2: # Trouver une entrée dans le fichier de mots de passe
            3: pwent =`grep '^ root:' / etc / passwd`
   4: # Turn off globbing - les lignes de mot de passe contiennent souvent '*'
            5: set -o noglob
   6: # Le "nom complet" et les autres commentaires sont en
            7: # champ 5, délimité par deux points. Obtenir ce champ en utilisant le fractionnement des mots de passe
            8: OIFS =$ IFS; IFS =:; ensemble $ pwent; IFS =$ OIFS
            9: écho 5 $

Exemple: affichage pickrandom, texte
Sélectionne un fichier aléatoire dans un répertoire.
Utilise la fonctionnalité ksh RANDOM.


            1: #! / bin / ksh
            2: 
            3: # Sélectionnez une image aléatoire dans la collection de logos en arrière-plan.
            4: # Ceci pourrait être utilisé pour configurer un économiseur d'écran, par exemple.
            5: #
            6: # Cela fonctionne même si les noms de fichiers contiennent des espaces.
            7: 
            8: # passer au répertoire des logos pour éviter les longs chemins
            9: logos =/ afs / northstar / commun / usr / lib / X11 / logos / arrière-plans
  dix: CD logos $
        11: 
        12: # '*' est un joker de nom de fichier qui correspond à tous les fichiers du répertoire en cours.
        13: ensemble *
  14: 
        15: # Utilisez la syntaxe pour les expressions arithmétiques. "%" est l'opérateur modulo
        16: # Décale les arguments d'un nombre aléatoire entre 0 et le nombre de fichiers
        17: décalage $ (($ RANDOM % $ #))
        18: 
        19: # Affiche le premier argument résultant
        20: écho "logos $/1 $"

(12)

Options de démarrage. ksh -options scriptname

-X
echo ligne stderr avant de l'exécuter
-n
lit les commandes et vérifie les erreurs de syntaxe, mais ne les exécute pas.
-une
toutes les variables sont automatiquement exportées
-F
désactiver l'expansion des noms de fichiers génériques (globbing)
set -x
Définir une option dans un script shell
$ -
contient les lettres d'option actuellement définies

Il y a beaucoup d'autres options, pas souvent nécessaires. Les options en ksh et bash peuvent aussi être
définir en utilisant des noms longs (par exemple -o noglob au lieu de -F). De nombreuses options
sont uniques à ksh ou bash.

(13)

syntaxe sh

`commande`
Une commande (plus des arguments optionnels) entourés de backticks est exécutée et la sortie standard
de cette commande est substitué. Si la commande produit une sortie multiligne, les nouvelles lignes sont conservées.
Si la chaîne résultante est affichée, sans guillemets, en utilisant écho, les nouvelles lignes et les espaces multiples seront supprimés.

syntaxe ksh / bash

$ (commande)
Cette syntaxe est fonctionnellement identique à celle des backticks, mais les commandes peuvent être plus facilement imbriquées.
$ (<fichier)
Ceci est équivalent à `cat file`, mais mis en œuvre en interne pour plus d'efficacité.

Exemple: affichage ex3, texte


            1: #! / bin / ksh
            2: 
            3: écho Aujourd'hui c'est `rendez-vous amoureux`
   4: 
            5: fichier =/ etc / hosts
   6: écho Le fichier fichier $ a $ (wc -l < fichier $) lignes
   7: 
            8: nom_hôte -s> nom_hôte
   9: écho Ce système a le nom d’hôte $ (<monhôte)

(14)

Toute commande simple (ou fonction shell, ou commande composée) peut avoir son entrée et sa sortie
redirigé à l'aide des opérateurs suivants. Ceci est effectué par le shell avant
la commande est exécutée.

Redirection de sortie

> nom de fichier
La sortie standard (descripteur de fichier 1) est redirigée vers le fichier nommé. Le fichier est écrasé
à moins que le noclobber l'option est définie. Le fichier est créé s'il n'existe pas.

Le fichier de périphérique spécial / dev / null peut être utilisé pour ignorer explicitement les sorties indésirables.
La lecture de / dev / null entraîne un statut de fin de fichier.

>> nom de fichier
La sortie standard est ajoutée au fichier nommé. Le fichier est créé s'il n'existe pas.
> | nom de fichier
Sortie redirection, et remplacer le noclobber option, si définie.

Redirection d'entrée

< nom de fichier
L'entrée standard (descripteur de fichier 0) est redirigée vers le fichier nommé. Le fichier doit déjà
exister.

Pipelines de commande

commande | commander [ | command ...]
Pipe plusieurs commandes ensemble. La sortie standard de la première commande devient la norme
entrée de la deuxième commande. Toutes les commandes sont exécutées simultanément et le transfert de données s'effectue via la mémoire.
des tampons. C'est l'une des constructions les plus puissantes d'Unix. Composé les commandes peuvent aussi être
utilisé avec des tuyaux. Les pipes jouent très bien avec les systèmes multiprocesseurs.

Un seul pipeline dans un pipeline doit être interactif (tentative de lecture depuis
le terminal). Cette construction est beaucoup plus efficace que l’utilisation de fichiers temporaires, et la plupart des
Les utilitaires Unix sont conçus pour fonctionner correctement dans les pipelines.

L'état de sortie d'un pipeline est l'état de sortie de la dernière commande. Dans les commandes composées, un pipeline
peut être utilisé n'importe où une simple commande pourrait être utilisée.

(15)

Les scripts shell peuvent générer directement des sorties ou lire des entrées dans des variables à l'aide des commandes suivantes:

Sortie de script

écho
Imprimez les arguments, séparés par des espaces, et terminés par une nouvelle ligne, sur stdout.
Utilisez des guillemets pour préserver l’espacement. Echo comprend également les conventions d’échappement de type C.

Attention ça
le shell peut traiter les barres obliques inverses avant écho les voit (peut avoir besoin de doubler la barre oblique inverse).
Interne dans la plupart des coquilles, mais était à l'origine externe.

b retour arrière c ligne d'impression sans nouvelle ligne (certaines versions)
F formulaire d'alimentation n nouvelle ligne
r retour chariot t languette
v onglet vertical \ barre oblique inverse

0n où n est le caractère de 8 bits dont le code ASCII
      code est le nombre octal à 1, 2 ou 3 chiffres
      représentant ce personnage.

-n
supprimer newline
impression (ksh interne)
Imprimez les arguments, séparés par des espaces, et terminés par une nouvelle ligne, sur stdout.
Print observe les mêmes conventions d'échappement que l'écho.

-n
supprimer newline
-r
mode brut – ignore les conventions -escape
-R
mode brut – ignore les conventions et les options -escape sauf -n.

Entrée de script

lis var1 var2 reste
lit une ligne de stdin, analyse de $ IFS et place les mots dans les variables nommées.
Tous les mots restants entrent tous dans la dernière variable. Un '' comme dernier caractère d'une ligne
supprime l’importance de la nouvelle ligne et l’entrée continue avec la ligne suivante.

-r
mode brut – ignore les conventions -escape

Exemple: affichage ex4a, texte


            1: #! / bin / sh
            2: écho "Test de la saisie utilisateur interactive: saisissez quelques touches et appuyez sur la touche Retour"
   3: lis x plus
   4: écho "Le premier mot était "$ x ""
   5: écho "Le reste de la ligne (le cas échéant) était "$ plus ""

(16)

La plupart des opérateurs de contrôle de flux utiles impliquent de faire des tests conditionnels et
branchement sur le résultat (vrai / faux). Le test peut être soit le tester

commande, ou son alias, [[[[, ou le ksh / bash intégré [[[[[ ... ]]

commande, qui a des options légèrement différentes, ou il peut être toute commande qui retourne
un statut de sortie approprié
. Zéro est considéré comme "vrai", tandis que toute valeur autre que zéro est "faux".
Notez que ceci est inversé par rapport à la convention du langage C.

Tests de fichiers

-e fichier
Vrai si fichier existe (peut être de tout type).
-F fichier
Vrai si fichier existe et est un fichier ordinaire.
-ré fichier
Vrai si fichier existe et est un répertoire.
-r fichier
Vrai si fichier existe et est lisible
De même, -w = accessible en écriture, -X = exécutable, -L = est un lien symbolique.
-s fichier
Vrai si fichier existe et a une taille supérieure à zéro
-t archiveur de notes
Vrai si l'ouvert archiveur de notes est associé à un terminal. Par exemple. c'est
utilisé pour déterminer si la sortie standard a été redirigée vers un fichier.

Tests de chaînes de caractères

-n "chaîne"
vrai si chaîne a une longueur non nulle
-z "chaîne"
vrai si chaîne a une longueur nulle

Avec [[[[, l'argument doit être cité, car s'il s'agit d'une variable
a une valeur nulle, l'expansion résultante ( [ -z ] ) est une erreur de syntaxe. Un
les extensions générant "" comptent comme une chaîne nulle.
Pour [[[[ seulement, un cité
la chaîne seule est équivalente au test -n, par ex. [ « $var » ]. Dans les coquilles plus anciennes pour lesquelles
[[[[ est un programme externe, le seul moyen de tester une chaîne nulle est:
si [ "X€var" = "X" ]
C'est rarement nécessaire maintenant, mais on le trouve encore souvent.

$ variable = texte
Vrai si $ variable allumettes texte.
$ variable < texte
Vrai si $ variable vient avant (lexicalement) texte
De même, > = vient après

(17)

Arithmetic tests

$variable -eq nombre
True if $variable, interpreted as a number, is equal to nombre.
$variable -ne nombre
True if $variable, interpreted as a number, is ne pas égal à nombre.
De même, -lt = less than, -le = less than or equal,
-gt = greater than, -ge = greater than or equal

Additional tests for [[…]](ksh and bash)

$variable = modèle
True if $variable allumettes modèle. Si modèle contains no wildcards,
then this is just an exact text match. The same wildcards as used for filename matching are used.

le modèle must not be quoted. Puisque [[…]]is internal to the shell, the pattern in this case is
treated differently and not filename-expanded as an external command would require.

file1 -nt file2
True if file1 is newer than file2.
De même -ot = older than
file1 -ef file2
true if file1 is effectively the same as file2, after following
symlinks and hard links.

Negating and Combining tests

Tests may be negated by prepending the ! operator, and combined with boolean
ET et OU operators using the syntax:

conditionnel -a conditionnel, conditionnel -o conditionnel
ET et OU syntax for tester et [[[[
conditionnel && conditionnel, conditionnel || conditionnel
ET et OU syntax for [[[[[ ... ]]

Parentheses may be inserted to resolve ambiguities or override the default operator precedence rules.

Exemples:



si [[  -x /usr/local/bin/lserve && 
       -w /var/logs/lserve.log ]]; puis
   /usr/local/bin/lserve >> /var/logs/lserve.log &
fi

pwent=`grep '^richard:' /etc/passwd`
si [ -z "$pwent" ]; puis
   echo richard not found
fi

(18)

UNE liste in these descriptions is a simple command, or a pipeline.
The value of the liste is the value of the last simple command run in it.

UNE liste can also be a set of simple commands or
pipelines separated by ";,&,&&,||,|&".
For the compound commands which branch on the success or failure
de certaines liste, it is usually [[[[ ou [[[[[[[[, but can be anything.

Conditional execution: if/else

liste && liste
Execute the first liste. If true (success), execute the second one.
liste || liste
Execute the first liste. If false (failure), execute the second one.

Exemple:



mkdir tempdir && cp workfile tempdir

sshd || echo "sshd failed to start"

You can use both forms together (with care) – they are processed left to right, and && must come first.

Exemple:



mkdir tempdir && cp workfile tempdir || 
 echo "Failed to create tempdir"

si liste; puis liste ; elif liste; puis liste; autre liste; fi
Execute the first liste, and if true (success), execute the "then" list, otherwise
execute the "else" list. The "elif" and "else" lists are optional.

Exemple:



si [ -r $myfile ]
puis
   cat $myfile
autre
   echo $myfile not readable
fi

Looping: 'while' and 'for' loops

tandis que liste; faire liste; terminé

jusqu'à ce que liste; faire liste; terminé
Execute the first liste and if true (success), execute the second liste. Repeat as
long as the first liste est vrai. le jusqu'à ce que form just negates the test.

Exemple: ex4 display, text


            1: #!/bin/ksh
            2: count=0
   3: max=dix
   4: tandis que [[[[[[[[$count -lt $max ]]
   5: faire 
            6:   écho $count
            7:   count=$((count + 1))
            8: terminé
            9: écho "Value of count after loop is: $count"

pour identifiant [in[in[in[inmots ]; do; liste; terminé
Ensemble identifiant in turn to each word in mots and execute the liste.
Omitting the "in mots" clause implies using [email protected], i.e. the identifiant est mis en
turn to each positional argument.

Exemple:



for file in *.dat
faire
    echo Processing $file
terminé

As with most programming languages, there are often several ways to express the same action.
Running a command and then explicitly examining $? can be used instead of some of the above.

Compound commands can be thought of as running in an implicit subshell. Ils
can have I/O redirection independant of the rest of the script. Setting of variables in a real subshell does not
leave them set in the parent script. Setting variables in implicit subshells varies in behaviour among shells.
Older sh could not set variables in an implicit subshell and then use them later,
but current ksh can do this (mostly).

Exemple: ex11 display, text
Reading a file line by line. The book by Randal Michael contains 12 example ways to read a file line by line,
which vary tremendously in efficiency. This example shows the simplest and fastest way.


            1: #!/bin/sh
            2: 
            3: # Demonstrate reading a file line-by-line, using I/O
            4: # redirection in a compound command
            5: # Also test variable setting inside an implicit subshell.
            6: # Test this under sh and ksh and compare the output.
            7: 
            8: line="TEST"
   9: save=
        10: 
        11: si [-z"[-z"[-z"[-z"$1" ]; puis
        12:    écho "Usage: 0 $ filename"
  13: autre
        14:    si [-r[-r[-r[-r$1 ]; puis
        15:       tandis que read line; faire
        16:          écho "$line"
  17:          save=$line
        18:       terminé < $1
        19:    fi
        20: fi
        21: écho "End value of $line est $line"
  22: écho "End value of $save est $save"

(19)

Case statement: pattern matching

Cas mot dans modèle) liste;; esac
Comparer mot avec chaque modèle) in turn, and executes the first liste
pour lequel le mot allumettes. le les patrons follow the same rules as for filename
wildcards.

(ksh and bash only)
A pattern-list is a list of one or more patterns separated
from each other with a |. Composite patterns can be formed
with one or more of the following:

?(pattern-list)
Optionally matches any one of the given patterns.
*(pattern-list)
Matches zero or more occurrences of the given patterns.
+(pattern-list)
Matches one or more occurrences of the given patterns.
@(pattern-list)
Matches exactly one of the given patterns.
!(pattern-list)
Matches anything, except one of the given patterns.

Exemple:

    
    
    
    case $filename in
    *.dat)
        echo Processing a .dat file
        ;;
    *.sas)
        echo Processing a .sas file
        ;;
    *)
        # catch anything else that doesn't match patterns
        echo "Don't know how to deal with $filename"
        ;;
    esac

Miscellaneous flow control and subshells

Pause [n]
Break out of the current (or n'th) enclosing loop. Control jumps to the next statement
after the loop
continuer [n];
Resume iteration of the current (or n'th) enclosing loop. Control jumps to the top of the loop,
which generally causes re-evaluation of a tandis que or processing the next element of a
pour.
. nom de fichier
Read the contents of the named file into the current shell and execute as if in line. Uses $PATH
to locate the file, and can be passed positional parameters. This is often used to read in shell
functions that are common to multiple scripts. There are security implications if the pathname is not
fully specified.
( ... ) Command grouping
Commands grouped in "( )" are executed in a subshell, with a separate environment
(can not affect the variables in the rest of the script).

(20)

As with most aspects of shell scripting, there are usually several possible ways to accomplish
a task. Certain idioms show up commonly. These are five ways to examine and branch on the
initial character of a string.

Utilisation Cas with a pattern:
case $var in
/*) echo "starts with /" ;;

Works in all shells, and uses no extra processes

Utilisation `cut`:
si [ "`echo $var | cut -c1`" = "/" ] ; puis .

Works in all shells, but inefficiently uses a pipe and external process for a trivial task.

Use POSIX variable truncation:
si [ "$var%$var#?" = "/" ]; puis

Works with ksh, bash and other POSIX-compliant shells. Not obvious if you have not seen
this one before. Fails on old Bourne shells.
Dave Taylor in "Wicked Cool Shell Scripts" likes this one.

Use POSIX pattern match inside of [[…]]:
si [[ $var = /* ]]; puis

Works with ksh, bash and other POSIX-compliant shells. Note that you must use [[…]]and no quotes around the pattern.

le [[…]]syntax is handled internally by the shell and can therefore interpret "wildcard" patterns
differently than an external command. An unquoted wildcard is interpreted as a pattern to be matched,
while a quoted wildcard is taken literally. le […] syntax, even if handled internally, is treated
as though it were external for backward compatability. This requires that wildcard patterns be expanded
to matching filenames.

Use ksh (93 and later) and bash variable substrings:
si [ "$var:0:1" = "/" ]; puis

ksh93 and later versions, and bash, have a syntax for directly extracting substrings by character
position. $varname:start:length

Exemple: ex17 display, text

(21)

The shells (ksh in particular) have many more internal commands. Some are used more in interactive
shells. The commands listed here are used in scripts, but don't conveniently fit elsewhere in the
classe.

eval args
The args are read as input to the shell and the resulting command executed. Allows "double" expansion
of some constructs. For example, constructing a variable name out of pieces, and then obtaining the value
of that variable.

netdev=NETDEV_ 
NETDEV_1=hme0         # As part of an initialization step defining multiple devices

devnum=1              # As part of a loop over those devices
ifname=$netdev€devnum # construct a variable name NETDEV_1
eval device=$$ifname # evaluate it - device is set to hme0
exec command args
The command is executed au lieu de the current shell. There is no return from an exec.
I/O redirection may be used. This is also used to change the I/O for the current shell.

:
The line is variable-expanded, but otherwise treated as a comment. parfois
used as a synonym for "true" in a loop.

while :; faire
  # this loop will go forever until broken by 
  # a conditional test inside, or a signal
terminé
unset var ...
Remove the named variables. This is not the same as setting their values to null.
composer [+/- options] [[[[prénom[=[=[=[=valeur]]... (ksh only,
bash uses déclarer for similar functions)
Set attributes and values for shell variables and functions. When used inside a function, a local
variable is created. Some of the options are:

-L[n]
Left justify and remove leading blanks. The variable always has length n if specified.
-R[n]
Right justify and fill with leading blanks. The variable always has length n if specified.
-l
The named variable is always treated as an integer. This makes arithmetic faster. The reserved word
entier is an alias for typeset -i.

-Z[n]
As for -R, but fill with zeroes if the value is a number
-je
Lower-case convert the named variables
-u
Upper-case convert the named variables
-r
Mark the variables as readonly
-x
Export the named variables to the enviroment
-ft
The variables are taken as function names. Turn on execution tracing.

(22)

Text variables

le modèle in the following uses the same wildcards as for filename matching.

$#var
returns the length of $var in characters
$var%pattern
removes the shortest suffix of $var patching modèle
$var%%pattern
removes the longest suffix of $var patching modèle
$var#pattern
removes the shortest prefix of $var patching modèle
$var##pattern
removes the longest prefix of $var patching modèle

Numeric variables

$(( integer expression ))
The $(( … )) construction interprets the contents as an arithmetic
expression (integer only). Variables are referenced by name without the "$". Most of the arithmetic
syntax of the 'C' language is supported, including bit manipulations
 (*,/,+,-,|,&,<<,>>. Use parentheses for changing precedence).

Exemples

datapath=/data/public/project/trials/set1/datafile.dat

filename=$datapath##*/
nom de fichier is set to "datafile.dat" since the longest préfixe
pattern matching "*/" is the
leading directory path (compare basename)
path=$datapath%/*
chemin is set to "/data/public/project/trials/set1" since the shortest suffixe
pattern matching "/*" is the
filename in the last directory (compare dirname)
i=$((i+1))
often used in tandis que boucles

(23)

All but the earliest versions of sh allow you define shell functions, which are visible only
to the shell script and can be used like any other command. Shell functions take precedence over
external commands if the same name is used. Functions execute in the same process as the caller,
and must be defined before use (appear earlier in the file). They allow a script to be broken
into maintainable chunks, and encourage code reuse between scripts.

Defining functions

identifiant() liste;
POSIX syntax for shell functions. Such functions do not restrict scope of variables
or signal traps.
The identifier follows the rules for variable names,
but uses a separate namespace.
une fonction identifiant liste;
Ksh and bash optional syntax for defining a function. These functions may define local
variables and local signal
traps and so can more easily avoid side effects and be reused by multiple scripts.

A function may read or modify any shell variable that exists in the calling script. Such variables
sont global.

(ksh and bash only) Functions may also declare local variables in the function using composer ou
déclarer.
Local variables are visible to the current function and any functions called by it.

revenir [n], sortie [n]
Return from a function with the given value, or exit the whole script with the given value.

Sans un revenir, the function returns when it reaches the end, and the value is the
exit status of the last command it ran.

Exemple:



die()

   # Print an error message and exit with given status
   # call as: die status "message" ["message" ...]
   exitstat=$1; décalage
   for i in "[email protected]"; faire
      print -R "$i"
   terminé
   exit $exitstat

Calling functions.

Functions are called like any other command. The output may be redirected independantly of the
script, and arguments passed to the function. Shell option flags like -x are unset in a function – you
must explicitly set them in each function to trace the execution. Shell functions may even be backgrounded
and run asynchronously, or run as coprocesses (ksh).

Exemple:

[ -w $filename ]    || 
  die 1 "$file not writeable" "check permissions"

Exemple: Backgrounded function call. ex12 display, text


            1: #!/bin/sh
            2: 
            3: background()
   4: 
   5:    sleep 10
   6:    écho "Background"
   7:    sleep 10
   8:    # Function will return here - if backgrounded, the subprocess will exit.
            9: 
  10: 
        11: écho "ps before background function"
  12: ps
  13: background &
  14: écho "My PID=$$"
  15: écho "Background function PID=$!"
  16: écho "ps after background function"
  17: ps
  18: sortie 0

Exemple:



vprint()

   # Print or not depending on global "$verbosity"
   # Change the verbosity with a single variable.
   # Arg. 1 is the level for this message.
   level=$1; décalage
   si [[ $level -le $verbosity ]]; puis
      print -R $*
   fi


verbosity=2
vprint 1 This message will appear
vprint 3 This only appears if verbosity is 3 or higher

Reuseable functions

By using only command line arguments, not global variables, and taking care to minimise the side
effects of functions, they can be made reusable by multiple scripts. Typically they would be
placed in a separate file and read with the "." operator.

Functions may generate output to stdout, stderr, or any other file or filehandle. Messages to stdout
may be captured by command substitution (`myfunction`, which provides another way for a function to
return information to the calling script. Beware of side-effects (and reducing reusability)
in functions which perform I/O.

(24)

Unix I/O is performed by assigning file descriptors to files or devices, and then
using those descriptors for reading and writing. Descriptors 0, 1, and 2 are always
used for stdin, stdout and stderr respectively. Stdin defaults to the keyboard,
while stdout and stderr both default to the current terminal window.

Redirecting for the whole script

Redirecting stdout, stderr and other file descriptors for the whole script
can be done with the exec commander.

exec > outfile < infile
with no command, the exec just reassigns the I/O of the current shell.
exec n>outfile
The form n<, n> opens file descriptor n instead of the default stdin/stdout.
This can then be used with read -u ou print -u.

Explicitly opening or duplicating file descriptors

One reason to do this is to save the current
state of stdin/stdout, temporarily reassign them, then restore them.

>&n
standard output is moved to whatever file descriptor n is currently pointing to
<&n
standard input is moved to whatever file descriptor n is currently pointing to
n>fichier
file descriptor n is opened for writing on the named fichier.
n>&1
file descriptor n is set to whatever file descriptor 1 is currently pointing to.

Exemple Sending messages to stderr (2) instead of stdout (1)

echo "Error: program failed" >&2 

Echo always writes to stdout, but stdout can be temporarily reassigned to duplicate stderr (or other file
descriptors).
Conventionally Unix programs send error messages to stderr to keep them separated from stdout.

Input and output to open file descriptors (ksh)

Printing to file descriptors (usually more efficient than open/append/close):

impression -u n args
print to file descriptor n.
-p
write to the pipe to a coprocess (opened by |&)

Reading from file descriptors other than stdin:

lis -u n var1 var2 rest
read a line from file descriptor n, parsing by $IFS, and placing the words into
the named variables. Any left over words all go into the last variable.
-p
read from the pipe to a coprocess (opened by |&)

Closing file handles

<&-
standard input is explicitly closed
>&-
standard output is explicitly closed

For example, to indicate to another program downstream in a pipeline that no more
data will be coming. All file descriptors are closed when a script exits.

I/O redirection operators are evaluated left-to-right. This makes a difference in a
statement like:
">filename 2>&1". (Many books with example scripts get this wrong)

"Here" documents

<&lt [-]chaîne
redirect input to the temporary file formed by everything up the matching chaîne
at the start of a line. Allows for placing file content inline in a script.

Exemple: ex5 display, text


            1: #!/bin/sh
            2: écho "Example of unquoted here document, with variable and command substitution"
   3: 
            4: cat <<EOF
   5:  This text will be fed to the "cat" program as 
   6:  standard input.  It will also have variable
   7:  and command substitutions performed.
   8:  I am logged in as $USER and today is `rendez-vous amoureux`
   9: EOF
  10: écho
        11: écho "Example of quoted here document, with no variable or command substitution"
  12: # The terminating string must be at the start of a line.
        13: cat <<"EndOfInput"
  14:  This text will be fed to the "cat" program as standard
  15:  input.  Since the text string marking the end was quoted, it does not get 
  16:  variable and command subsitutions.
  17:  I am logged in as $USER and today is `rendez-vous amoureux`
  18: EndOfInput

Exemple: duplex display, text


            1: #!/bin/sh
            2: # Add in the magic postscript preface to perform
            3: # duplex printer control for Xerox docuprint.
            4: 
            5: # To have this script send the files directly to the printer, use 
            6: # a subshell to collect the output of the two 'cat' commands.
            7: 
            8: ## (
            9: cat << EOP
  10: %!PS
  11: %%BeginFeature: *Duplex DuplexTumble
  12: <> setpagedevice
  13: %%EndFeature
  14: EOP
  15: cat "[email protected]"
  16: ## ) | lpr

(25)

More complicated manipulations of file descriptors can be arranged.
Two such examples are shown here:

This short test script can be used to generate suitable output.
ex13: display, text



echo "This goes to stdout"
echo "This goes to stdout and has foo in the line"
echo "This goes to stderr" >&2
exit 99

Pass stderr of a command into a pipeline for further processing

Exemple: ex14 display, text

exec 3>&1
./ex13.sh 2>&1 1>&3 3>&- | sed 's/stderr/STDERR/' 1>&2

We duplicate stdout to another file descriptor (3), then run the first command with stderr redirected
to stdout and stdout redirected to the saved descriptor (3). The result is piped into other commands
comme requis. The output of the pipeline is redirected back to stderr, so that stdout and stderr of the script
as a whole are what we expect.


            1: #!/bin/sh
            2: # Example 14
            3: # Take stderr from a command and pass it into a pipe
            4: # for further processing.
            5: 
            6: # Uses ex13.sh to generate some output to stderr
            7: # stdout of ex13 is processed normally
            8: 
            9: # Save a copy of original stdout
        10: exec 3>&1
  11: 
        12: # stdout from ex13.sh is directed to the original stdout (3)
        13: # stderr is passed into the pipe for further processing.
        14: # stdout from the pipe is redirected back to stderr
        15: ./ex13.sh 2>&1 1>&3 3>&-  | sed 's/stderr/STDERR/' 1>&2
  16: 
        17: # 3 is closed before running the command, just in case it cares
        18: # about inheriting open file descriptors.

Capture the exit status of a command in the middle of a pipeline

Exemple: ex15 display, text

exec 3>&1
ex13stat=`((./ex13.sh; echo $? >&4) | grep 'foo' 1>&3) 4>&1`

This script uses nested subshells captured in backtics.
Again we first duplicate stdout to another file descriptor (3).
The inner subshell runs the first command, then writes the exit status
to fd 4. The outer subshell redirects 4 to stdout so that it is
captured by the backtics. Standard output from the first command
(inner subshell) is passed into the pipeline as normal, but the final output
of the pipeline is redirected to 3 so that it appears on the original stdout
and is not captured by the backtics.

If any of the commands really care about inheriting open file
descriptors that they don't need then a more correct command line
closes the descriptors before running the commands.


            1: #!/bin/sh
            2: # Example 15
            3: 
            4: # Uses ex13.sh to generate some output and give us an 
            5: # exit status to capture.
            6: 
            7: # Get the exit status of ex13 into $ex13stat.  
            8: # stdout of ex13 is processed normally
            9: 
        10: # Save a copy of stdout
        11: exec 3>&1
  12: # Run a subshell, with 4 duplicated to 1 so we get it in stdout.  
        13: # Capture the output in ``
        14: # ex13stat=`( ...  ) 4>&1`
        15: # Inside the subshell, run another subshell to execute ex13, 
        16: # and echo the status code to 4
        17: # (./ex13.sh; écho $? >&4)
        18: # stdout from the inner subshell is processed normally, but the 
        19: # subsequent output must be directed to 3 so it goes to the 
        20: # original stdout and not be captured by the ``
        21: ex13stat=`((./ex13.sh; écho $? >&4) | grep 'foo' 1>&3) 4>&1`
  22: 
        23: écho Last command status=$?
  24: écho ex13stat=$ex13stat
        25: 
        26: # If any of the commands really care about inheriting open file 
        27: # descriptors that they don't need then a more correct command line 
        28: # closes the descriptors before running the commands
        29: exec 3>&1
  30: ex13stat=`((./ex13.sh 3>&- 4>&- ; écho $? >&4) | 
  31:    grep 'foo'  1>&3 3>&- 4>&- ) 4>&1`
  32: écho Last command status=$?
  33: écho ex13stat=$ex13stat

Combine the above two techniques:

Exemple: ex16 display, text

exec 3>&1
ex13stat=`((./ex13.sh 2>&1 1>&3 3>&- 4>&- ; echo $? >&4) |
sed s/err/ERR/ 1>&2 3>&- 4>&- ) 4>&1`


            1: #!/bin/sh
            2: # Example 16
            3: 
            4: # Uses ex13.sh to generate some output and give us an 
            5: # exit status to capture.
            6: 
            7: # Get the exit status of ex13 into ex13stat. 
            8: # stderr of ex13 is processed by the pipe, stdout
            9: # is left alone.
        10: 
        11: # Save a copy of stdout
        12: exec 3>&1
  13: 
        14: # Run a subshell, with 4 copied to 1 so we get it in stdout.  
        15: # Capture the output in backtics`
        16: # ex13stat=`(    ) 4>&1`
        17: 
        18: # In the subshell, run another subshell to execute ex13, and 
        19: # echo the status code to 4
        20: # (./ex13.sh; écho $? >&4)
        21: 
        22: # stdout from the inner subshell is directed to the original stdout (3)
        23: # stderr is passed into the pipe for further processing.
        24: # stdout from the pipe is redirected back to stderr
        25: 
        26: # Close the extra descriptors before running the commands
        27: exec 3>&1
  28: ex13stat=`((./ex13.sh 2>&1 1>&3 3>&- 4>&- ; écho $? >&4) | 
  29:   sed s/err/ERR/ 1>&2 3>&- 4>&- ) 4>&1`
  30: 
        31: écho Last command status=$?
  32: écho ex13stat=$ex13stat
        33: 

A practical application of this would be running a utility such as dd

where the exit status is important to capture, but the error output is overly chatty and
may need to be filtered before delivering to other parts of a script.

(26)

Scripts can start any number of background jobs (any external command),
which run in parallel with the
parent script, and asynchronously. Processes which require no further interaction
or synchronization (fire and forget) are easy.
Interaction with background jobs is tricky. Vous pouvez
use signals, pipes, named pipes, or disk files for communication.

commander Et
Début commander as a background process. Control returns immediately to the shell.
bgpid=$!
The special variable $! contains the process ID of the last background job
that was started. You can save that and examine the process later
(ps -p $bgpid) or send it a signal (kill -HUP $bgpid).

ksh coprocesses

Coprocesses are a way of starting a separate process which
runs asychronously, but has stdin/stdout connected to the parent script via pipes.

commander |&
Start a coprocess with a 2-way pipe to it
lis -p var
Read from the pipe to the coprocess, instead of standard input
impression -p args
Write to the pipe connected to the coprocess, instead of standard output

Multiple coprocesses can be handled by moving the special file descriptors connected
to the pipes onto standard input and output, and or to explicitly specified file descriptors.

exec <&p
The input from the coprocess is moved to standard input
exec >&p
The output from the coprocess is moved to standard output

Exemple: ex9 display, text
A script wants to save a copy of all output in a file, but also wants a copy
à l'écran. This is equivalent to always running the script as
scénario | tee outfile


            1: #!/bin/ksh
            2: 
            3: # If we have not redirected standard output, save a copy of
            4: # the output of this script into a file, but still send a
            5: # copy to the screen.
            6: 
            7: si [[ -t 1 ]]; puis
            8:   # Only do this if fd 1 (stdout) is still connected
            9:   # to a terminal
        10: 
        11:   # We want the standard output of the "tee" process
        12:   # to go explicitly to the screen (/dev/tty)
        13:   # and the second copy goes into a logfile named $0.out
        14: 
        15:   tee 0 $.out >/dev/tty |&
  16: 
        17:   # Our stdout all goes into this coprocess
        18:   exec 1>&p
  19: fi
        20: 
        21: # Now generate some output
        22: impression "User activity snapshot on $(hostname) at $(date)"
  23: impression
        24: qui

Exemple: ex10 display, text
Start a coprocess to look up usernames in some database.
It is faster to run a single process than to run a separate
lookup for each user.


            1: #!/bin/ksh
            2: # This example uses a locally written tool for Dartmouth Name Directory lookups
            3: 
            4: # Start the dndlookup program as a coprocess
            5: # Tell it to output only the canonical full name, and to not print multiple matches
            6: dndlookup -fname -u |&
   7: 
            8: # move the input/output streams so we 
            9: # can use other coprocesses too
        10: exec 4>&p
  11: exec 5<&p
  12: 
        13: écho "Name file contents:"
  14: cat namefile
  15: écho
        16: 
        17: # read the names from a file "namefile"
        18: tandis que read uname; faire
        19:   impression -u4 $uname
        20:   lis  -u5 dndname
  21:   Cas $dndname dans
  22:   *many matches*)
  23:     # handle case where the name wasn't unique
        24:     impression "Multiple matches to "$uname" in DND"
  25:     ;;
  26:   *no match*)
  27:     # handle case where the name wasn't found
        28:     impression "No matches to "$uname" in DND"
  29:     ;;
  30:   *)
  31:     # we seem to have a hit - process the
        32:     # canonical named retrieved from dndlookup
        33:     impression "Unique DND match: full name for "$uname" is "$dndname""
  34:     ;; 
  35:   esac
        36:   sleep 2
  37: terminé < namefile
  38: 
        39: # We've read all the names, but the coprocess
        40: # is still running.  Close the pipe to tell it
        41: # we have finished.
        42: exec 4>&-

(27)

Both ksh and bash implement arrays of variables, but in somewhat different ways.

ksh distinguishes between numerically indexed (small) arrays, and string indexed (associative) arrays.
bash uses integers for all array indexing, but the integers need not be consecutive and unassigned array elements
do not exist. Arrays must be declared before use, e,g. typeset -A myarray (ksh associative array), or
typeset -a myarray (bash).

Array elements are set with the syntax:
myarray[index]=value

and referenced with the syntax $myarray[index]

This example shows use of an array indexed by IP addresses, as strings in ksh or as non-consecutive numbers in bash.
It also demonstrates use of getopt for options processing

Exemple: getauthlogs display, text


            1: #! / bin / bash
            2: # $Header: $
            3: # First attempt at a consolidated auth log collection from kaserver
            4: # Timestamps in the raw files are NOT designed for easy sorting.
            5: #
            6: # Options:
            7: #  -i  -- translate hex IP addresses to dotted-decimal (relatively quick)
            8: #  -h  -- translate hex IP addresses to DNS names (somewhat slower - DNS lookups)
            9: #  -u user -- filter for the named user before translating addresses
        10: 
        11: hextodec()
  12: 
  13:    # convert the IP address in reverse-hex to dotted-decimal
        14:    écho $((0x$1:6:2)).$((0x$1:4:2)).$((0x$1:2:2)).$((0x$1:0:2))
        15: 
  16: 
        17: hostlookup()
  18:  tr 'A-Z' 'a-z'
  30:       ;;
  31:    esac
        32: 
  33: 
        34: # Options
        35: iptranslate=0
  36: gethostnames=0
  37: filter=chat
  38: tandis que getopts ihu: o ; faire
        39:    Cas $o dans
  40:    i) iptranslate=1 ;;
  41:    h) gethostnames=1; iptranslate=1 ;;
  42:    u) filter="grep $OPTARG" ;;
  43:    esac
        44: terminé
        45: décalage $(($OPTIND-1))
        46: 
        47: # We could get the DB server names from 'fs checkservers', but it isn't obvious what is from our cell. nous
        48: # could also grep CellServDB.  I cop out and hard code one known DB server and get the others from it.
        49: masterserver=halley.dartmouth.edu
  50: serverlist=$(bos listhosts -server $masterserver| grep 'Host .* is ' | awk 'print 4 $')
  51: 
        52: # If we want to filter usernames, it is more efficient to do it inline, before sorting, translation and hostname lookups
        53: 
        54: # Array to hold IP address/name conversions (associative array, ksh only)
        55: # ksh - use -A for associative array.  bash - use -a and numeric array
        56: composer -a hostnames
  57: 
        58: (
  59: pour dbserver in $serverlist; faire
        60:    bos getlog -server $dbserver -file /usr/afs/logs/AuthLog
  61: terminé
        62: ) | grep -v 'Fetching log file' | $filter | sed -e 's/^... //' -e 's/  ([1-9]) / 01 /' | sort --month-sort | 
  63:     sed '-e s/ ([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])$/ 01/' |
  64:     tandis que read line; faire
        65:    si [[[[[[[[$iptranslate == 1 ]]; puis
        66:       # Ugly!
        67:       # Sometimes we get a 7-digit hex code in the log - the kaserver apparently drops leading zeros.
        68:       # The second 'sed' in the pipe catches these are fixes them.
        69:       Cas $line dans
  70:       * from [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])
  71:          # translate the reverse-hex address
        72:          iphex=$line##* from 
        73:          # bash version - index by numeric value only, but can be sparse array -- use the raw IP 
        74:          ipdec=$((0x$iphex))
        75:          frontpart=$line% from *
        76:          si [[[[[[[[$gethostnames == 1 ]]; puis
        77:             # ksh - index on hex value as a string (iphex)
        78:             # bash - index on numeric value (ipdec)
        79:             index=$ipdec
        80:             si [[-z"[[-z"[[-z"[[-z"$hostnames[[[[$index]" ]]; puis
        81:                hostnames[[[[$index]="$(hostlookup $(hextodec $iphex))" 
  82:             fi
        83:             écho "$frontpart de $hostnames[[[[$index]"
  84:          autre
        85:             écho "$frontpart from $(hextodec $iphex)"
  86:          fi
        87:          ;;
  88:       *)
  89:          écho "$line"
  90:          ;;
  91:       esac
        92:    autre
        93:       # No ip translation, just echo the whole line
        94:       écho "$line"
  95:    fi   
        96: terminé
        97: 

(28)

Unix signals (software interrupts) can be sent as asynchronous events to shell scripts, just
as they can to any other program. The default behaviour is to ignore some signals and immediately
exit on others. Scripts may detect signals and divert control to a handler function or external
programme. This is often used to perform clean-up actions before exiting, or restart certain
procedures. Execution resumes where it left off, if the signal handler returns. Signal traps
must be set separately inside of shell functions. Signals can be sent to a process with
tuer.

piège gestionnaire sig ...
gestionnaire is a command to be read (evaluated first) and executed on receipt of
le spécifié sigs. Signals can be specified by name or number (see kill(1))
par exemple. HUP, INT, QUIT, TERM. A Ctrl-C at the terminal generates a INT.
  • A handler of - resets the signals to their default values
  • A handler of '' (null) ignores the signals
  • Special signal values are as follows:
    EXIT
    the handler is called when the function exits, or when the whole script exits. le
    exit signal has value 0.
    ERR (ksh)
    the handler is called when any command has a non-zero exit status
    DEBUG (ksh)
    the handler is called after chaque commander.

Exemple: ex8 display, text


            1: #! / bin / bash
            2: # Try this under bash, ksh and sh
            3: 
            4: piège huphandler  HUP
   5: piège ''          QUIT
   6: piège exithandler TERM INT
   7: 
            8: huphandler()
   9: 
  10:    écho 'Received SIGHUP'
  11:    écho "continuing"
  12: 
  13: 
        14: exithandler()
  15: 
  16:    écho 'Received SIGTERM or SIGINT'
  17:    sortie 1
  18: 
  19: ## Execution starts here - infinite loop until interrupted
        20: # Use ":" or "true" for infinite loop
        21: # SECONDS is built-in to bash and ksh.  It is number of seconds since script started
        22: : is like a comment, but it is evaluated for side effects and evaluates to true
  23: seconds=0
  24: tandis que : ; faire
        25: # while true; faire
        26:    sleep 5
  27:    seconds=$((seconds + 5))
        28:    écho -n "$SECONDS $seconds - "
  29: terminé

Exit handlers can be defined to clean up temporary files or reset the state of devices. Ce
can be useful if the script has multiple possible exit points.

(29)

Shell scripts are often used by system administrators and are run as a priviledged user.

  • Don't use set-UID scripts.

    Most systems don't even allow a script to be made set-UID. It is
    impossible (due to inherent race conditions) to ensure that a set-uid script cannot be compromised.
    Use wrapper programs like sudo instead.

  • Always explicitly set $PATH at the start of a script, so that you know exactly
    which external programs will be used.
  • If possible, don't use temporary files. If they cannot be avoided, use $TMPDIR,
    and create files safely (e.g. mktemp).

    Often scripts will write to a fixed, or trivially generated temporary filename in /tmp. If the
    file already exists and you don't have permission to overwrite it, the script will fail. Si vous
    do have permission to overwrite it, you will delete the previous contents. Since /tmp is public write,
    another user may create files in it, or possibly fill it completely.

    Exemple:

    1. A link is created by an unprivileged user in /tmp: /tmp/scratch -> /vmunix
    2. A root user runs a script that blindly writes a scratch file to /tmp/scratch, and overwrites the
      operating system.

    Environment variable $TMPDIR is often used to indicate a preferred location for
    temporary files (e.g., a per-user directory). Some systems may use $TMP ou $TEMP.
    Safe scratch files can be made by creating a new directory, owned
    and writeable only by you, then creating files in there.

    Exemple:

    
    
    (umask 077 && mkdir /tmp/tempdir.$$) || exit 1
    

    or (deluxe version)

    tmp=$TMPDIR:-/tmp
    tmp=$tmp/tempdir.$RANDOM.$RANDOM.$RANDOM.$$
    (umask 077 && mkdir $tmp) || 
        echo "Could not create temporary directory" 1>&2
        exit 1
    
    

    Alternatively, many systems have mktemp to safely create a temporary file and return
    the filename, which can be used by the script and then deleted.

  • Check exit status of everything you do.
  • Don't trust user input
    • contents of files
    • data piped from other programs
    • fichier des noms. Output of filename generation with wildcards, or directly from
      ls ou trouver

Exemple:

Consider the effects of a file named "myfile;cd /;rm *" if processed,
unquoted, by your script.

One possible way to protect against weirdo characters in file names:

# A function to massage a list of filenames 
# to protect weirdo characters
# e.g. find ... | protect_filenames | xargs command
#
# We are backslash-protecting the characters '" ?*;
protect_filenames()

   sed -es/\\/\\\\/g 
       -es/\'/\\'/g   
       -es/\"/\\"/g   
       -es/\;/\\;/g   
       -es/\?/\\?/g   
       -es/\*/\\*/g   
       -es/\ /\\ /g

If using GNU trouver et xargs, there is a much cleaner option
to null-terminate generated pathnames.

(30)

Shell scripts are very frequently written quickly for a single purpose, used once and discarded.
They are also as frequently kept and used many times, and migrate into other uses, but often
do not receive the same level of testing and debugging that other software would be given
in the same situation. Il est possible to apply general principles of good software
engineering to shell scripts.

  • Preface scripts with a statement of purpose, author, date and revision notes
  • Use a revision control system for complex scripts with a long lifetime
  • Assume your script volonté have a long lifetime unless you are certain it won't
  • Document any non-standard external utilities which your script needs
  • Document your scripts with inline comments – you'll need them in a few months when you edit it.
  • Treat standard input and output in the normal way, so that your script can be used
    in combination with other programs (the Unix toolkit philosophy)
  • Be consistent in the format of your output, so that other programs can rely on it
  • Use options to control behaviour such as verbosity of output. Overly chatty programs are
    very hard to combine with other utilities
  • Use interactive features (prompting the user for information) très parcimonieusement.
    Doing so renders the script unuseable in pipeline combinations with other programs, or in unattended
    operations.
  • Test (a lot)

When not to use shell scripts

  • If an existing tool already does what you need – use it.
  • If the script is more than a few hundred lines, you are probably using the wrong tool.
  • If performance is horrible, and the script is used a lot, you might want to consider another language.

(31)

The class accounts have directories with all of the examples from the books by Blinn,
Michael, Rosenblatt, and Taylor. These can also be downloaded (see the References page).
Some of these are linked below (but not included in the printed notes), with additional comments.

Download a compressed tar file of all example scripts used in these notes.

  • postprint display, text
    A wrapper script for printing a mix of text and postscript files
  • checkpath display,
    texte
    Check all the directories in the $PATH for possibly conflicting programs.

  • run-with-timeout display,
    texte
    Run a command with a timeout. Kill the command if it hasn't finished when the timeout expires.

  • MailPkg display, text
    Tar, compress, split and uuendcode a set of files for mailing. (Blinn)
  • Ptree (original) display, text
  • Ptree (ksh version) display, text
    Runs "ps" to get a process listing and then
    reformats to show the process family hierarchies. The original example is pure Bourne shell
    and inefficient. The ksh version is a fairly simple translation to use ksh internal commands
    where possible, and avoid writing scratch files, and runs very much faster. (Blinn).

This entire tutorial was created from individual HTML pages using a content management system written
as ksh scripts (heavily using sed to edit the pages), coordinated by faire.
<! –



  • buildhtml afficher, texte

    Turns a stand-alone HTML file into a component of the tutorial, with navigation links and frames.

  • buildslidelist afficher, texte

    Creates the slide list which appears as the left frame of the tutorial.

  • buildframeset afficher, texte

    Creates a top level frameset to call the slide list and content pages.

  • ksh2html afficher, texte

    Creates the colourized HTML page of a shell script.

  • Makefile texte

    Makefile used to build the site using the above tools


->

You can even write an entire web server as a shell script. This one is part of the
LEAF
(Linux Embedded Appliance Firewall) project. This wouldn't be suitable for much load, but handles occasional queries on
static HTML and CGI scripts.
(www.nisi.ab.ca/lrp/Packages/weblet.htm)

(32)

The following commands are very frequently used in shell scripts. Many of them are used
in the examples in these notes. This is just a brief recap — see the man pages for details on usage.
The most useful are flagged with *.

Most of these commands will operate on a one or more named files, or will operate on a stream of
data from standard input if no files are named.

Listing, copying and moving files and directories

ls *
list contents of a directory, or list details of files and directories.

mkdir; rmdir *
Make and Remove directories.

rm; cp; mv *
Remove (delete), Copy and Move (rename) files and directories

toucher *
Update the last modifed timestamp on a file, to make it appear to have just been written.

If the file does not exist, a new zero-byte file is created, which is often useful to signify that
an event has occurred.

tee
Make a duplicate copy of a data stream – used in pipelines to send one copy to a log file
and a second copy on to another program. (Think plumbing).

Displaying text, files or parts of files

écho *
Echo the arguments to standard output — used for messages from scripts.
Some versions of "sh", and all csh/ksh/bash shells internalized "echo".

Conflicts
sometimes arise over the syntax for echoing a line with no trailing CR/LF.
Some use "c" and some use option "-n". To avoid these problems, ksh also provides the "print"
command for output.

chat *
Copy and concatenate files; display contents of a file

tête, queue *
Display the beginning of a file, or the end of it.

Couper
Extract selected fields from each line of a file. Often awk is easier to use, even though it is
a more complex program.

toilettes
Count lines, words and characters in the input.

Compression and archiving

compresse; gzip, Zip *: français; le goudron *
Various utilities to compress/uncompress individual files, combine multiple files into a single archive, or
do both.

Sorting and searching for patterns

Trier *
Sort data alphabetically or numerically.

grep *
Search a file for lines containing character patterns. The patterns can be simple fixed text, or very complex
regular expressions.

The name comes from "Global Regular Expression and Print" — a function from
the Unix editors which was used frequently enough to warrant getting its own program.

uniq *
Remove duplicate lines, and generate a count of repeated lines.

toilettes *
Count lines, words and characters in a file.

System information (users, processes, time)

rendez-vous amoureux *
Display the current date and time (flexible format). Useful for conditional execution based on
time, and for timestamping output.

ps *
List the to a running processes.

tuer *
Send a signal (interrupt) to a running process.

identifiant
Print the user name and UID and group of the current user (e.g. to distinguish priviledged users before
attempting to run programs which may fail with permission errors)

qui
Display who is logged on the system, and from where they logged in.

uname *
Display information about the system, OS version, hardware architecture etc.

courrier *
Send mail, from a file or standard input, to named recipients. Since scripts are often used to automate
long-running background jobs, sending notification of completion by mail is a common trick.

enregistreur
Place a message in the central system logging facility. Scripts can submit messages
with all the facilities available to compiled programs.

nom d'hôte
Display the hostname of the current host – usful to keep track of where your programs are running

Conditional tests

tester; [[[[ *
The conditional test, used extensively in scripts, is also an external program which evaluates
the expression given as an argument and returns true (0) or false (1) exit status. The name "[" is a
link to the "test" program, so a line like:
si [ -w logfile ]
actually runs a program "[« , with arguments « -w logfile ]", and returns a true/false value to the "if"
commander.

In ksh and most newer versions of sh, "[" is replaced with a compatible internal command, but the
argument parsing is performed as if it were an external command.
Ksh also provides the internal "[[" operator, with simplified syntax.

Stream Editing

awk *
A pattern matching and data manipulation utility, which has its own scripting language. It also duplicates
much functionality from 'sed','grep','cut','wc', etc.

Complex scripts can be written entirely using awk, but it is
frequently used just to extract fields from lines of a file (similar to 'cut').

sed *
Stream Editor. A flexible editor which operates by applying editing rules to every line in a data stream
in turn.

Since it makes a single pass through the file, keeping only a few lines in memory at once,
it can be used with infinitely large data sets. It is mostly used for global search and replace operations.
It is a superset of 'tr', 'grep', and 'cut', but is more complicated to use.

tr
Transliterate – perform very simple single-character edits on a file.

Finding and comparing files

trouver *
Search the filesystem and find files matching certain criteria (name pattern, age, owner, size,
last modified etc.)

xargs *
Apply multiple filename arguments to a named command and run it.

Xargs is often used in combination
with "find" to apply some command to all the files matching certain criteria. Since "find" may result in a very
large list of pathnames, using the results directly may overflow command line buffers. Xargs avoids this problem,
and is much more efficient than running a command on every pathname individually.

diff *
Compare two files and list the differences between them.

basename pathname
Returns the base filename portion of the named pathname, stripping off all the directories

dirname pathname
Returns the directory portion of the named pathname, stripping off the filename

Arithmetic and String Manipulation

expr *
The "expr" command takes an numeric or text pattern expression as an argument, evaluates it, and
returns a result to stdout. The original Bourne shell had no built-in arithmetic operators.
Par exemple.
expr 2 + 1
expr 2 '*' '(' 21 + 3 ')'
Used with text strings, "expr" can match regular expressions and extract sub expressions. Similar functionality
can be achived with sed.
par exemple.
expr SP99302L.Z00 : '[A-Z0-9]4\([0-9]3\)L.*'

dc
Desk Calculator – an RPN calculator, using arbitrary precision arithmetic and
user-specified bases. Useful for more complex arithmetic expressions than can be performed
internally or using expr

avant JC
A preprocessor for dc which provides infix notation and a C-like syntax for
expressions and functions.

Merging files

coller
Merge lines from multiple files into tab-delimited columns.

joindre
Perform a join (in the relational database sense) of lines in two sorted input files.

(33)

The standard man pages for sh et ksh are quite complete, but not easy to
learn from. The following is a sampling of the many available books on the subject. The Bolsky and Korn
book might be viewed as the standard "reference". The Blinn book is Bourne shell, but everything in it should
work for either shell.
The links are to publisher's web sites, or Amazon.com. Some links are also given to the example
scripts provided with the books.

Livres

  • The New KornShell Command And Programming Language, by Morris I. Bolsky, David G. Korn (Contributor).

    Plus d'informations
  • Learning the Korn Shell, 2nd Edn. by Bill Rosenblatt and Arnold Robbins.

    Plus d'informations
  • Korn Shell Programming by Example, by Dennis O'Brien, David Pitts (Contributor).

    Plus d'informations
  • The Korn Shell Linux and Unix Programming Manual (2nd Edn) by Anatole Olczak.

    Plus d'informations
  • Portable Shell Programming: An Extensive Collection of Bourne Shell Examples by Bruce Blinn.

    Plus d'informations

    Examples from this book can be downloaded for study.
  • Linux Shell Scripting with Bash by Ken O. Burtch.

    Plus d'informations
  • Unix Shell Programming by Stephen Kochan and Patrick Wood (third Edition).

    Plus d'informations
  • Teach yourself Shell Programming in 24 Hours,
    by S. Veeraraghavan. SAMS 2nd Edn. (2002)
    Plus d'informations
  • Mastering Unix Shell Scripting
    by Randal K. Michael, Wiley (2003)
    Plus d'informations
    Light on basics, but develops scripting through examples. Ksh only.
    Examples can be
    téléchargé
    from the Wiley site (www.wiley.com/legacy/compbooks/michael/).
  • Wicked Cool Shell Scripts
    by Dave Taylor, No Starch Press (2004)
    Plus d'informations
    Develops scripting entirely through examples, drawn from Linux and OSX in addition to traditional Unix.
    Recommended, but not for beginners.
    Examples can be
    téléchargé
    from the Intuitive site (www.intuitive.com/wicked/wicked-cool-shell-script-library.shtml).
  • Unix Power Tools, by S. Powers, J. Peek, T. O'Reilly, M. Loudikes et al.

    Plus d'informations

Online Resources

  • Shelldorado (http://www.shelldorado.com)
    Lots of links to scripting resources
  • Kornshell (http://www.kornshell.com)
    The official Korn shell home page, with download links.
  • Mac OSX Unix tutorial (http://www.osxfaq.com/Tutorials/LearningCenter/)
    Good resource on advanced use of OSX and Unix shell scripting in general

Unix-like shells and utilities for Microsoft Windows

  • U/Win (http://www.research.att.com/sw/tools/uwin/)

    A free port of ksh and Unix command line utilities, plus Windows DLL for Unix compatability. Developed by AT&T Research.

  • Cygwin (http://www.cygwin.com/)

    A free Linux-like environment for Windows. Provides bash, command line utilities and DLLs. Developed by RedHat. Un
    X server is also available.

  • MKS Toolkit (http://www.mkssoftware.com/)

    A commercial ksh clone and command line utilities, plus DLL for Unix compatability. An X server is also available.

  • Microsoft Services for UNIX (http://www.microsoft.com/windows/sfu/)

    A POSIX environment for Windows, with ksh, csh, command line tools, libraries and software development tools.
    Developed by Interix and bought by Microsoft. Free download.


Unix shell scripting with ksh/bash: Course Handout
[an error occurred while processing this directive]

(last update   22 March 2012)  ©Dartmouth College
    http://www.dartmouth.edu/~rc/classes/ksh

Commentaires

Laisser un commentaire

Votre commentaire sera révisé par les administrateurs si besoin.