Bonjour,
J’étais en train d’écrire un script pour AIX en Korn shell et étant donné que c’est un script très simple je me suis dit : « tiens mais pourquoi pas rendre mon script compatible également Linux ? » et là je tombe sur un os… :/
Même avec un shell compatible POSIX de chaque côté (#!/usr/bin/env sh
), je me rends compte que la commande echo ne fonctionne pas de la même manière sur AIX et Linux :(
Sous AIX les caractères tels que \n, \t, etc… sont bien interprétés. Sous Linux il faut pour ça utiliser l’option -e de echo, option qui n’existe pas sous AIX (ce serait trop simple).
Je subodore qu’il faut utiliser printf plutôt que echo mais avec printf je ne peux pas, à ma connaissance, faire ce genre de truc :
export HELP="\n\
### check_files.sh #####################################################################\n\
# #\n\
# Checks if presence of files in a directory on AIX. #\n\
# #\n\
# Arguments : #\n\
# #\n\
# -d <path> Directory to search files in. #\n\
# -a <int> Search files older than this parameter, in minutes. #\n\
# -s <int> Size of each file must be superior to this value, in bytes #\n\
# -n <int> Maximum number of files #\n\
# -h Show this help. #\n\
# #\n\
########################################################################################\n\
\n";
Si j’ai le code ci-dessus, pour que l’affichage soit correct sous AIX il faut faire echo "$HELP"
alors que sous Linux je devrais faire echo -e "$HELP"
. Si je mets l’option -e sous AIX ça va m’afficher ce '-e' dans la sortie.
Est-ce que vous voyez une solution à laquelle je n’aurais pas pensé ?
# Contournement
Posté par root_rtfm . Évalué à 3.
Hello,
En utilisant un variable ECHO :
[
uname -a| grep -ci linux
-gt 0 ] && ECHO="echo -e " || ECHO="echo "Puis
$ECHO $HELP
Cdlt
[^] # Re: Contournement
Posté par benja . Évalué à 4.
Encore mieux que de déduire à partir du nom du système, c'est de tester la feature directement. Genre
PS: au lieu de terminer les lignes avec \n\, il suffit de ne rien mettre, faire du POSIX c'est aussi apprendre à ne pas se compliquer la vie ;-)
PS2: Un cat <<HEREDOC marcherait très bien aussi…
[^] # Re: Contournement
Posté par benja . Évalué à 2.
PS3: Si on veut vraiment utiliser uname (mais pourquoi?) alors au moins ne matcher que sur le "-s". "-a" inclue le hostname et plein d'infos superflues, ton code risque ne marchera plus si ton hostname contient "linux" (les gens qui mandatent d'utiliser AIX suivent souvent d'autres conventions étranges).
[^] # Re: Contournement
Posté par benja . Évalué à 1.
PS4: pourquoi faire un "export" de la variable ? pourquoi printf ne marcherait pas ? Attention aussi à longueur maximale d'une ligne de commande qui est plus restreinte sur AIX que sur linux, un HEREDOC serait vraiment plus approprié en fait. Le ';' n'a rien à faire là non plus.
[^] # Re: Contournement
Posté par Dabowl_75 . Évalué à 1.
ça fait bien longtemps que cette limitation n'existe plus….
c'est le paramètre ncargs.
Pour visualiser la valeur : lsattr -El sys0 -a ncargs
On peut le changer à chaud mais ça fait bien longtemps que la valeur par défaut "should be enough for everyone"
[^] # Re: Contournement
Posté par benja . Évalué à 0.
Il y a une différence entre ne plus exister et devrait être suffisante. Le jour où il lancera son script avec set -x, il va bien rigoler aussi d'avoir mis toute son aide dans un argument de commande… 'fin bon je dis ça…
[^] # Re: Contournement
Posté par Marotte ⛧ . Évalué à 2.
Quand je fais
echo "toto tatat titi"
ça compte trois arguments ?De plus je ne comprends pas « dans un argument de commande ». J’ai mis l’aide dans une variable, cette variable est "lue" si l’argument de la commande est "-h"… Tu peux m’expliquer ?
[^] # Re: Contournement
Posté par benja . Évalué à 1.
Ton shell fais l'expansion de variables sur la commande afin de construire un ARGV. Je ne crois pas que même pour une builtin (echo/printf), il fonctionne de manière différente, ça ne serait plus posix pour le coût je suppose. Bref, le contenu de ta variable se retrouve expansé dans un buffer qui sert de ARGV, buffer qui est limité. Autant utiliser la sortie de cat directement, éventuellement à travers un autre programme en utilisant un pipe ("|") si tu dois réellement faire un traitement dessus avant de l'afficher.
Essaye avec "set -x" dans ton script, tu vas vite voir la différence.
[^] # Re: Contournement
Posté par benja . Évalué à 1. Dernière modification le 12 juillet 2016 à 14:51.
Argument de la commande "echo" bien sûr. Qui se retrouve dans la sortie de debug quand tu actives set -x, sortie qui deviendrait largement moins lisible pour le coups.
[^] # Re: Contournement
Posté par Michaël (site web personnel) . Évalué à 2.
Non un seul. Si tu programmes en shell, il faut absolument clarifier le remplacement des variables, et les règles de lecture des lignes, sans quoi tu vas constamment te créer des difficultés inutiles (du type triple échappement croisé des caractères de fin de ligne comme dans l'exemple du début ;) ).
Le petit programme ci-dessous te permet d'expérimenter pour savoir ce que reçoit une fonction ou un programme comme vecteur d'arguments:
[^] # Re: Contournement
Posté par benja . Évalué à 2. Dernière modification le 12 juillet 2016 à 16:26.
Primo: c'est faux, tu l'écris toi-même .
Deuxio: si IBM a augmenté le défaut, je parie que c'est pour éviter de "casser" des scripts qui "fonctionnent" sous linux. J'imagine du coups qu'ils ont aussi augmenté la taille de la stack par défaut, ai-je bon ? Pour la même raison qu'il y a des buffers alloués plus grands, histoire d'éviter de "casser" tous ces programmes qui font des "petis" buffer-overflow. De là à considérer que ces programmes soient techniquement corrects, voire se comportent correctement, il y a un pas que je ne franchis pas. Autant ne pas emprunter cette route du "si c'est pas assez, on augmente puis on croise les doigts".
Tersio: Pourquoi cette limitation existe en premier lieu, i.e. pourquoi ça n'est pas complètement dynamique ? Par ce que cela a un cout, non ? À toi de me montrer qu'augmenter le défaut n'engendre pas un coût supplémentaire… (avec un peu de chance, c'est documenté par IBM). En d'autres mots, en augmentant le défaut, tout le monde paye pour les quelques utilisateurs qui programment n'importe comment… C'est pour ça que je préfère avoir un défaut plus petit, et en bonus on se rend plus vite compte que l'on fait n'importe quoi.
BTW: AIX c'est pas aussi l'OS qui mappe qq chose à l'adresse NULL ?
[^] # Re: Contournement
Posté par Dabowl_75 . Évalué à 1.
La limitation historique (avant AIX 6.1) méritait quand même d'être retouchée.
Non je n'ai pas remarqué que la taille de la stack kernel par défaut a augmentéen AIX 6.1, même si je n'ai pas fait de recherche très approfondies. En tous cas ce n'est pas écrit dans le redbook "aix 6.1 diff guide".
Plus simplement, IBM a implémenté ça la SED (Stack Execution Disable protection)
https://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.security/stack_exec_disable.htm
Je pense que ça devrait répondre à ta question…
Sous Linux aussi cette limitation avait cours jusqu'en 2.6.22 (ce qui n'est pas si loin que ça) :
http://www.in-ulm.de/~mascheck/various/argmax/
Depuis AIX 6.1 (2007), le défaut est désormais 4096 * 256 (1 048 576) mais on peut aller jusqu'à 4096 * 1024 (4 194 304).
Côté Linux, à peu près à la même époque, ils ont préféré faire autrement, aller jusqu'à 1/4 de la Stack.
Et sinon évidemment oui que cela a un coût de toucher au noyau.
Et comme AIX n'est pas open source, ce genre d'initiative ne peut provenir que de l'éditeur.
Donc à l'ère du 64 bits, tu préfères revenir à l'âge de pierre et avoir une limitation forte sur la taille des arguments ?
Je trouve ça bien que le défaut ait augmenté. Cela ne veut pas dire qu'on fait forcément n'importe quoi. Il y a toujours une limite, mais cette fois beaucoup plus grande.
[^] # Re: Contournement
Posté par benja . Évalué à 2.
Ok merci pour cette réponse et ton lien factuel.
Oui car je ne suis pas d'accord avec ta proposition suivante. Au passage, 4MO=22bits d'adressage, ça reste rien du tout hein ;-) Si tu passes 4MO, ben pourquoi pas à 8 et pourquoi pas à 16, etc. ?
Si car en ce faisant 1) tu deviens de-facto non portable (cf ton lien!) 2) l'argv n'a jamais été prévu pour transmettre plus que le stricte minimum entre les processus. Un exemple de déficience: il n'y a pas moyen libérer cette mémoire. Corolaire du 2) unix propose d'autres moyens—portables, optimaux et efficaces—pour transmettre de l'information entre processus. Pourquoi le faire alors si ce n'est par fainéantise ?
(Je me permets de dire fainéantise car j'ai déjà "pêché" moi aussi… rétrospectivement j'aurais du mettre en place un meilleur design tout de suite, 'fin bon j'étais jeune et sous pression. tant pis pour mon employeur qui finalement a perdu plus que moi dans l'histoire: moi j'ai gardé la leçon, lui le code pourri :p).
[^] # Re: Contournement
Posté par Marotte ⛧ . Évalué à 2.
Oui l’export sert à rien ici. Le ';' non plus mais j’aime bien le mettre quand même par endroit :) Pour printf j’ai répondu plus bas.
Je vais tester la méthode donnée par Michaël plus bas (plutôt qu’une commande personnalisée dans une variable), je suppose que c’est ça qu’on appelle un HEREDOC.
# printf
Posté par eggus . Évalué à 2.
Pourquoi l'utilisation de printf n'est elle pas possible ?
Je n'ai pas d'AIX sous la main pour tester mais sous linux un script avec les lignes suivantes affiche correctement le texte sous bash :
[^] # Re: printf
Posté par Marotte ⛧ . Évalué à 2.
Oui grave… en fait il suffit de ne pas spécifier de format, ou plutôt, utiliser directement la variable comme template pour printf :) J’aurais dû y penser…
[^] # Re: printf
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 4.
C'est affreux.
Pour le question : qu'utiliser puisque
echo
n'est pas portable, la réponse est bienprintf
.En revanche, pour cet usage là, ce n'est pas la meilleure solution, mieux veut utiliser un
cat
, comme mentionné plus bas.# Tu cherches les ennuis :)
Posté par Michaël (site web personnel) . Évalué à 7. Dernière modification le 12 juillet 2016 à 11:46.
C'est beaucoup plus facile de faire comme ça:
À noter que les variables sont remplacées comme avec les
""
– ce qui permet d'afficher les valeurs par défaut. À noter que tu peux en profiter pour gérer ton aide en utf-8 en utilisant iconv à la place de cat (aveciconv -c -f utf-8
) ou faire plein d'autres choses avec sed ou awk par exemple, ou ton filtre préféré.L'affichage portable d'une chaîne quelconque se fait avec
printf '%s' "${HELP}"
.PS: Sinon tu peux aussi planquer des fichiers après le
exit
de ton programme et les extraire en utilisant les sélecteursawk '/DELIM1/,/DELIM2/'
mais je trouve ça moins propre au niveau de l'organisation logicielle. Par contre pour afficher l'aide d'un Makefile, cette astuce est très appréciable.[^] # Re: Tu cherches les ennuis :)
Posté par benja . Évalué à 2. Dernière modification le 12 juillet 2016 à 14:00.
Note pour la complétude: cela dépend en fait, il y a moyen de désactiver l'interpolation de variables tout comme il y a aussi moyen de supprimer une indentation.
PS: Je ne suis toujours pas convaincu que mettre tout dans une variable soit une si bonne idée. Cf mes remarques ci-dessus.
[^] # Re: Tu cherches les ennuis :)
Posté par benja . Évalué à 2. Dernière modification le 12 juillet 2016 à 14:08.
PS2:Surtout si on l'"export"e après… que je sache le coût de stocker ces variables sera payé par tous les programmes jamais lancés par le script et leurs descendants… Bon après on va encore me dire "mais si ça marche, etc…" mais bon avec une mentalité pareille, on fini vite par construire des usines à gaz.
[^] # Re: Tu cherches les ennuis :)
Posté par Marotte ⛧ . Évalué à 2.
Je vais probablement virer ces export car ces variables ne sont pas destinées à être utilisée dans un sous processus. Tu as raison.
[^] # Re: Tu cherches les ennuis :)
Posté par Michaël (site web personnel) . Évalué à 2. Dernière modification le 12 juillet 2016 à 14:50.
Comme ça:
[^] # Re: Tu cherches les ennuis :)
Posté par Michaël (site web personnel) . Évalué à 3.
À mon avis aussi c'est plutôt une mauvaise idée, j'ai juste reproduit la structure du programme existant. Normalement dans les variables du shell on ne stocke que des “objets du monde Unix” comme des noms de fichiers, des PID etc. mais tout ce qui fait l'objet de calculs se place dans des fichiers ou se balade entre les pipes d'une programme.
<Mode ironie>
Lire ce fabuleux article sur mon fabuleux blog :) http://michipili.github.io/shell/2015/04/12/shell-filter-programming.html[^] # Re: Tu cherches les ennuis :)
Posté par Marotte ⛧ . Évalué à 2.
Merci ! Je vais tester ça. Mon problème avec printf c’est qu’en faisant
printf '%s' "toto\ntiti"
ça n’interprète pas le "\n", mais avec ta méthode ça devrait marcher. Je testerai ça seulement vendredi par contre.En plus c’est cool, ça évite de coller explicitement des "\n\" à toutes les fins de ligne du texte d’aide, c’est plus joli :)
[^] # Re: Tu cherches les ennuis :)
Posté par benja . Évalué à 3. Dernière modification le 12 juillet 2016 à 14:23.
<Mode jaloux>
méthode mentionnée dans mon premier commentaire :p</>
Cela n'était pas nécessaire avec ta méthode non plus (aussi dans mon premier commentaire… :p).
[^] # Re: Tu cherches les ennuis :)
Posté par Marotte ⛧ . Évalué à 3.
Aujourd’hui j’ai appris que ça s’appelait un HEREDOC ;)
[^] # Re: Tu cherches les ennuis :)
Posté par Marotte ⛧ . Évalué à 2.
Effectivement :)
j’avais un peu fait nimp’ :)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.