GNU/Linux >> Tutoriels Linux >  >> Linux

Quel est le moyen le plus sûr et le plus portable d'invoquer le binaire echo ?

Notez que coreutils est un ensemble de logiciels développé par le projet GNU pour fournir un ensemble d'utilitaires de base Unix aux systèmes GNU. Vous ne trouverez que coreutils echo prêt à l'emploi sur les systèmes GNU (Debian , trisquel , Cygwin , Fedora , CentOS ...). Sur d'autres systèmes, vous trouverez un autre (généralement avec un comportement différent comme echo est l'une des applications les moins portables). FreeBSD aura FreeBSD echo , la plupart des systèmes basés sur Linux auront busybox echo , AIX aura AIX echo ...

Certains systèmes en auront même plus d'un (comme /bin/echo et /usr/ucb/echo sur Solaris (ce dernier faisant partie d'un package désormais facultatif dans les versions ultérieures de Solaris, comme le package d'utilitaires for GNU à partir duquel vous obtiendriez un /usr/gnu/bin/echo ) tous avec des CLI différentes).

GNU coreutils a été porté sur la plupart des systèmes de type Unix (et même non-Unix comme MS Windows), vous pourrez donc compiler coreutils ' echo sur la plupart des systèmes, mais ce n'est probablement pas ce que vous recherchez.

Notez également que vous trouverez des incompatibilités entre les versions de coreutils echo (par exemple, il ne reconnaissait pas \x41 séquences avec -e ) et que son comportement peut être affecté par l'environnement (POSIXLY_CORRECT variable).

Maintenant, pour exécuter le echo du système de fichiers (trouvé par une recherche de $PATH ), comme pour toutes les autres commandes intégrées, la manière typique est avec env :

env echo this is not the builtin echo

En zsh (lorsqu'il n'émule pas d'autres shells), vous pouvez également faire :

command echo ...

sans avoir à exécuter un env supplémentaire commande.

Mais j'espère que le texte ci-dessus indique clairement que cela ne va pas aider en ce qui concerne la portabilité. Pour la portabilité et la fiabilité, utilisez printf à la place.


# $(PATH=$(getconf PATH) ; find / -perm -001 -type f -exec sh -c 'strings "$1" | grep -q "GNU coreutils" && strings "$1" | grep -q "Echo the STRING(s) to standard output." && printf "%s" "$1"' sh {} \; | head -n 1) --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
  or:  /bin/echo LONG-OPTION
...
or available locally via: info '(coreutils) echo invocation'

Je pense que c'est une mauvaise idée, pour être honnête, mais cela fera un travail assez solide pour trouver les coreutils echo dans un environnement raisonnable. Ce sont des commandes compatibles POSIX tout du long (getconf , find , sh , grep , strings , printf , head ), il devrait donc se comporter de la même manière partout. Le getconf nous donne les versions compatibles POSIX de chacun de ces outils en premier dans le chemin, dans les cas où les versions par défaut ne sont pas standard.

Il trouve tout exécutable contenant à la fois les chaînes imprimables "GNU coreutils" et "Echo the STRING(s) to standard output", qui apparaissent dans le GNU echo est --help sortie et sont littéralement dans le texte du programme. S'il y a plus d'une copie, il sélectionne arbitrairement la première qu'il a trouvée. S'il n'y en a pas, il échoue - le $(...) se développe en une chaîne vide.

Je ne l'appellerais pas "sûr", cependant, car la présence de ce script (exécutable) n'importe où sur le système vous causerait des problèmes :

#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /

Donc pour réitérer, je pense que c'est une très mauvaise idée. Sauf si vous allez mettre en liste blanche les hachages de echo connus s, il n'existe aucun moyen raisonnable et portable d'en trouver une version donnée qui soit sûre pour fonctionner sur des systèmes inconnus. À un moment donné, vous devrez exécuter quelque chose en vous basant sur une supposition.

Je vous encourage à utiliser le printf commande à la place, qui accepte un format et tous les arguments que vous souhaitez utiliser littéralement.

# printf '%s' -e
-e

printf est en POSIX et devrait se comporter de la même manière pour tous les systèmes si vous fournissez un format.


Personnellement, j'évite echo complètement dans mes scripts shell et utiliser printf '%s\n' blablabla lorsque la chaîne est courte et documentez ici lorsque la chaîne est longue.

Citant le §11.14 Limitations des commandes intégrées du shell du manuel autoconf :

écho

Le simple echo est probablement la source la plus surprenante de problèmes de portabilité. Il n'est pas possible d'utiliser echo portable sauf si les options et les séquences d'échappement sont omises. Ne vous attendez à aucune option.

N'utilisez pas de barres obliques inverses dans les arguments, car il n'y a pas de consensus sur leur traitement. Pour echo '\n' | wc -l , le sh de Solaris affiche 2 , mais Bash et Zsh (en sh mode d'émulation) sortie 1 . Le problème est vraiment echo :tous les shells comprennent '\n' sous la forme d'une chaîne composée d'une barre oblique inverse et d'un n . Dans une substitution de commande, echo 'string\c' gâchera l'état interne de ksh88 sur AIX 6.1 pour qu'il imprime le premier caractère s uniquement, suivi d'une nouvelle ligne, puis supprimez entièrement la sortie de l'écho suivant dans une substitution de commande.

En raison de ces problèmes, ne transmettez pas une chaîne contenant des caractères arbitraires à echo . Par exemple, echo "$foo" n'est sûr que si vous savez que foo La valeur de ne peut pas contenir de barres obliques inverses et ne peut pas commencer par - .

Si cela peut ne pas être vrai, printf est en général plus sûr et plus facile à utiliser que echo et echo -n . Ainsi, les scripts où la portabilité n'est pas une préoccupation majeure doivent utiliser printf '%s\n' chaque fois que echo pourrait échouer, et de même utiliser printf %s au lieu de echo -n . Pour les scripts shell portables, il est plutôt suggéré d'utiliser un document ici comme celui-ci :

          cat <<EOF
          $foo
          EOF

Linux
  1. Quel a été le moment le plus important de l'histoire de Linux ?

  2. Quel est le moyen le plus sûr d'obtenir les privilèges root :Sudo, Su ou Login ?

  3. La méthode portable (posix) pour réaliser la substitution de processus ?

  4. Sauvegarde cloud vs sauvegarde locale :le moyen le plus sûr de stocker des données

  5. Quel est le moyen le plus sûr de vider un répertoire dans *nix ?

Quel est le moyen le plus simple de libérer de l'espace sur un disque dur ?

Le moyen le plus sûr de partitionner Linux ?

Quelle est la meilleure façon d'apprendre SELinux ?

Quel est le moyen le plus rapide d'exécuter un script ?

Quelle est la manière la plus légère de rendre des graphiques Gentoo ?

Quelle est la meilleure façon de vérifier si un volume est monté dans un script Bash ?