Comment puis-je obtenir en toute sécurité la version de ksh à partir d'un script ksh?
J'ai vu les solutions suivantes :
ksh --version
echo ${.sh.version}
echo $KSH_VERSION
Et étant donné les bonnes circonstances, chacun de ces travaux fonctionne correctement. Cependant, je me soucie du cas non parfait.
Plus précisément, il y a plusieurs machines avec lesquelles je travaille qui ont des versions plus anciennes de ksh qui, pour mes besoins, manquent gravement de fonctionnalités. Quoi qu'il en soit, la raison pour laquelle je veux vérifier la version (par programme) est de voir si la version ksh est l'une des versions les moins capables; et si oui, je veux exécuter une branche avec du code moins impressionnant.
Cependant, sur les machines problématiques, l'ineptie du shell s'étend à la vérification de la version ...
- Si j'essaye
ksh --version
, il n'imprime rien et ouvre une nouvelle instance deksh
! Si j'essaie
echo ${.sh.version}
,ksh
traite cela comme une erreur de syntaxe qui ne peut pas être éliminée2> /dev/null
.$ echo ${.sh.version} 2> /dev/null ksh: ${.sh.version}: bad substitution
Bien sûr, cela
echo $KSH_VERSION
semble fonctionner correctement - je veux dire qu'il ne se bloquera pas - bien que sur ces machines, il soit vide. De plus, j'ai vu quelque part quiKSH_VERSION
n'est défini que parpdksh
.
Des questions:
- Comment puis-je vérifier en toute sécurité la version de par
ksh
programme? Pour mes besoins ici, je ne me soucie pas vraiment du numéro de version réel, juste s'il s'agit d'une version obsolète deksh
. - Est-ce
$KSH_VERSION
assez bon? Je veux dire si elle est vide, alors estksh
nécessairement une version obsolète? Est-ce que cet autre forum avait raison de ne pas être défini même pour les nouvelles versions deksh
? - N'y a-t-il simplement aucun moyen de vérifier cela?
la source
PS1
pour utiliser cette fonction. Cependant, Old ksh ne prend pas en charge$()
dansPS1
. Donc, si c'est une version moderne de ksh, je veuxPS1
utiliser la fonction que j'ai créée; si c'est l'ancienne version, j'utilise juste$PWD
.Réponses:
Je pense que cela
.sh.version
existe depuis la première version d'ATT ksh 93. Il n'est pas disponible en pdksh ou mksh. Puisqu'il${.sh.version}
s'agit d'une erreur de syntaxe dans des shells autres que ksh93, encapsulez le test dans un sous-shell et protégez-le derrièreeval
.KSH_VERSION
a commencé dans le clone ksh du domaine public (pdksh) et a été ajouté au shell Korn actuel relativement récemment, en 2008 avec ksh93t.Plutôt que de tester un numéro de version, vous devriez tester la fonctionnalité spécifique qui vous cause du chagrin. La plupart des fonctionnalités peuvent être testées en essayant une construction dans un sous-shell et voir si cela déclenche une erreur.
la source
${.sh.version}
comme une erreur de syntaxe qui ne peut pas être rapprochée. Le message que je reçois estbad substitution
./dev/null
et ignorez l'état de sortie.eval '_sh_version=$(echo "${.sh.version}")' 2>/dev/null
marche mieux?KSH_VERSION
n'a pas été implémentéksh93
avant la version 93t. Il sera mis enmksh
,pdksh
,lksh
. Donc, pour vérifier la version deksh
, nous pouvons essayer ces étapes:KSH_VERSION
de détectermksh
,pdksh
,lksh
ksh93
etksh88/86
( laissez David Korn nous le montrer ).En gardant cela à l'esprit, j'irai avec:
la source
$KSH_VERSION
n'est-elle pas non vide en premier? Sur ma machine Ubuntu, cela imprime "ksh93", maisKSH_VERSION
est encore défini..kshrc
.ENV
variable est définie (et elle est généralement définie sur~/.kshrc
), le script lira définitivement le.kshrc
fichier. Bien sûr, il serait assez étrange qu'un script définisse un faux KSH_VERSION mais cela est néanmoins possible, tout comme l'exécution explicite d'un script avec un interpréteur différent de celui spécifié dans sa première ligne est une situation possible.KSH_VERSION
. Etmksh
,pdksh
,lksh
,KSH_VERSION
est marqué en lecture seule.Pour les
ksh
versions "réelles" (c'est-à-dire basées sur AT&T), j'utilise cette commande:Voici différentes sorties que j'obtiens:
Ksh d'origine:
dtksh;
Ksh93 moderne:
Pour les
pdksh
/msh
ksh
clones et lesksh
versions AT&T modernes aussi, voici quelque chose qui fonctionne:Éditer:
J'ai oublié que vous demandiez de le faire depuis l'intérieur d'un script, pas en connaissant le chemin vers le binaire ksh testé.
En supposant que vous vouliez vraiment la version
ksh
utilisée, et non les fonctionnalités qu'il prend en charge, voici une façon de le faire en utilisant uniquement lastrings
commande qui devrait fonctionner au moins sur Linux et Solaris:Notez que cette méthode n'est pas fiable car elle
/proc
pourrait ne pas être montée, et il y a certainement d'autres faiblesses. Il n'est pas testé sur les autres OS Unix.la source
lksh
etpdksh
dans Debian Jessie.lksh
etpdksh
ne peut pas être trié de leurKSH_VERSION
?strings
dessus.KSH_VERSION
peut définitivement.ksh
sorties» », j'excluais explicitement les clones ksh non AT&T commepdksh
,mksh
etlksh
.strings
sur un binaire ksh est une mauvaise idée car vous ne savez pas si c'est celui qui exécute votre script. Peut-être que votre script est exécuté par/usr/local/bin/ksh
ou ou/home/bob/bin/ksh
ou/bin/sh
ou/usr/posix/bin/sh
ou ...Pendant que j'écrivais un script pour
ksh
, j'ai remarqué que l'-a
option de lawhence
commande intégrée de ksh ne semble pas être prise en charge dans les anciennes versions deksh
. Et cela semble être vrai sur tous les systèmes que j'ai vérifiés, y compris Solaris, AIX, HP-UX et Linux.Voici donc la solution en tant que fonction ksh:
Et voici comment l'utiliser:
la source
${.sh.version}
?whence
dans Zsh a-a
whence
commande intégrée qui n'est en aucun cas liée à ksh ou à sa version. Je ne sais même pas pourquoi vous voudriez vérifier si ksh est une ancienne version à partir d'une instance de zsh, qui est un shell complètement différent./bin/ksh
, par exemple sur Debian Linux. Maintenant, je ne l'utilise pas là-bas (et pour le moment je ne peux pas changer mon shell de connexion pour vérifier), donc je ne sais pas s'il lit.kshrc
ou non, mais je soupçonne que c'est le cas.CTRL+ ALT+V
ou
ESC, CTRL+V
Ils se sont généralement révélés très fiables en ce qui concerne la détermination interactive de la version de KSH que vous utilisez, mais leur création s'est avérée plus difficile.
la source
set -o vi
pour définir les raccourcis clavier comme vi. Avant cela, ou avec + o vi ou -o emacs, cela ne me montrait tout simplement pas. PD KSH v5.2.14 99/07 / 13.2 sur openbsd 6.1Je pense que le problème fondamental avec l'utilisation de $ {. Sh.version} est que ksh88 s'arrête juste, avec un code de sortie non nul.
Donc ma solution est de mettre le code qui fait référence à $ {. Sh.version} dans un sous-shell, puis de tester pour voir si le sous-shell sort non nul et d'avoir du code dans le sous-shell qui fonctionnera sur les versions de le ksh où référencer $ {. sh.version} fonctionne. Envelopper dans une fonction qui est ensuite appelée par une autre fonction qui inverse le code retour, de sorte que l'appel final vérifie vrai.
J'ai exécuté ceci sur AIX et Oracle Enterprise Linux 5 & 6, avec ksh88, ksh93 et pdksh.
Pete
la source
.sh.version
(en faitKSH_VERSION
est effectivement un alias pour cela). De plus, certains shells, par exemple NetBSD sh, arrêtent simplement la lecture après la rencontre${.sh.version}
et aucune redirection ne peut les faire fonctionner le script.Les éléments suivants semblent fonctionner raisonnablement bien pour tous les shells que j'ai testés, y compris les anciens ksh88e et une gamme presque complète de clones Ksh communs (bien qu'une seule version de chacun), bien que je n'aie pas encore testé un vrai Bourne shell original ( et cela peut nécessiter d'adapter l'
test
expression pour les anciennes versions ....Addenda:
J'ai également testé cela avec succès avec Heirloom Bourne Shell, bien qu'avec un programme externe (et plus moderne)
test
.la source
${.sh.version}
ne peuvent pas faire partie de la solution car certaines versions de ksh - les versions qui préoccupaient le message d'origine - se trompent fatalement sur cette syntaxe.