Je cherche un moyen simple et fiable pour obtenir le nom du shell actuel à l'intérieur d'un script ou d'un fichier source ( pas à partir de la ligne de commande). Je m'attendrais à le faire, $(basename "$SHELL")
mais si mon shell de connexion est zsh
et j'ai le code suivant dans some_script.sh
this_shell=$( basename "$SHELL" )
echo "The Shell is $this_shell"
echo "The Shell is $0"
et je l'exécute avec bash some_script.sh
, il répertorie toujours zsh
au lieu de bash
même si l'interpréteur utilisé l'est /bin/bash
. Je ne sais pas pourquoi les concepteurs de shell ont choisi d'afficher le shell par défaut au lieu du shell actuel, mais cela semble être ce avec quoi nous sommes coincés.
Il y a d'autres questions légèrement similaires ( ici et ici ), mais leurs réponses sont insuffisantes à bien des égards.
- Ils supposent souvent que l'utilisateur essaie de comprendre quel shell interactif ils utilisent actuellement, mais c'est fou. Je sais dans quel shell je tape des commandes - j'ai besoin de code qui pourrait être exécuté n'importe où pour pouvoir déterminer dans quel shell il utilise.
- Ils donnent souvent plusieurs choses différentes à essayer - encore une fois comme si vous êtes sur la ligne de commande et pouvez simplement jouer jusqu'à ce que vous appreniez que vous utilisez bash - mais j'ai besoin d'une seule chose qui est fiable dans tous les contextes.
- Ils donnent souvent des choses totalement inutiles à partir de scripts, comme
echo $0
. Cela échoue comme indiqué dans le script ci-dessus. (Oui, cela fonctionne dans une ligne de commande de shell interactive, mais pourquoi ne sauriez-vous jamais quel shell vous utilisez?) - Ils donnent parfois des commandes qui (dans mes tests limités) incluent les informations correctes, comme
ps -p $$
, mais manquent de commandes sed / awk multi-plateformes et compatibles shell pour les diriger pour obtenir uniquement le nom du shell et ignorer les autres informations qui viennent Pour le trajet. - Ils incluent des choses qui ne fonctionneront que sur quelques coques, comme
$BASH_VERSION
et$ZSH_VERSION
. Je veux soutenir autant de coquilles que possible, commefish
,csh
,tcsh
.
Comment détecter de manière fiable et précise un shell actuel ? Je cherche quelque chose qui fonctionnera sur toutes les plateformes, dans les scripts, et pour autant de shells que possible et raisonnable 1 .
MISE À JOUR : Quand j'ai posté cette question, je m'attendais à ce qu'il y ait une installation intégrée dans les obus pour nous donner cette information, ce qui ne semble pas être le cas. Puisqu'il semble inévitable maintenant de s'appuyer sur quelque chose en dehors des coquilles, je devrais préciser que je demande unesolution multiplateforme (qui, bien que sous-entendue par mes objections aux autres réponses ci-dessus, pourrait être facile à manquer si vous ne lisez pas la question attentivement).
Mise à jour 2 Si quelqu'un pense toujours que c'est un double de la question Linux uniquement parce que la réponse de Stéphane n'est pas Linux uniquement, voici les différences entre ce que je demande et ce qu'il a fourni. (Notez que ce qu'il a écrit est ingénieux, et je ne le frappe pas, mais cela ne résout pas mon problème.)
- Je cherche quelque chose de simple et fiable , qui
- peut être ajouté à une définition de script ou la fonction (qui proviendraient par un
.zshrc
ou.bash_profile
ou autre) à la branche. - Vous ne pouvez pas utiliser son script comme un utilitaire externe qui transmet le nom de l'interpréteur au script / fonction appelant, car il sera toujours interprété par l'interpréteur par défaut et le renverra. Cela rend son utilisation difficile ou impossible à mes fins. Si c'est possible, c'est encore très très difficile, et la solution pour le faire fonctionner n'est pas donnée dans la réponse. Il n'a donc pas répondu à ma question, il ne s'agit donc pas d'un doublon.
Si vous voulez voir quelque chose qui va travailler, jetez un oeil à ShellDetective sur GitHub . Cela peut permettre de voir plus facilement les différences entre ce qui est déjà présent sur SE et ce que recherche cette question (et a en fait été écrite afin de répondre aux besoins de cette question, qui n'étaient satisfaits nulle part ailleurs).
(PS si vous ne pouvez pas croire qu'il ya un cas d'utilisation pour cela, imaginez les fonctions qui se sourced dans .zshrc
, .bash_profile
ou en .profile
fonction de ce serveur est utilisé et ce que les coquilles dont il dispose. Ils sont source de sorte qu'ils ont pas de ligne de tralala. Ils sont plus utiles s'ils peuvent fonctionner dans n'importe quel shell, mais parfois ils doivent savoir dans quel shell ils se trouvent pour savoir comment se comporter.)
1 Je ne m'intéresse pas aux "obus" qui ne sont pas des obus au sens traditionnel du terme. Je ne suis pas préoccupé par un obus qu'un gars a écrit pour lui-même. Je ne m'intéresse qu'aux vrais shells qui se produisent réellement dans la nature, et que quelqu'un pourrait éventuellement utiliser lors de la connexion à un serveur sur lequel il ne peut pas simplement installer les shells qu'il souhaite.
sh -c "…"
, puis faites l'essentiel du travail dans la syntaxe du shell POSIX.fish
et je l'utilise pour exécuter votre script, voulez-vousfish
oucsh
?Réponses:
J'ai eu d'excellents résultats avec cette combinaison:
Sur Tru64 (OSF / 1), la sortie a des parenthèses autour du shell. Tack
tr -d '()'
pour les supprimer.Semble fonctionner sur tous les shells, sur Solaris 10 et RHEL 5.7 / 6.4. Je n'ai pas testé d'autres distributions telles que Debian, Ubuntu ou Mint, mais je pense qu'elles devraient toutes fonctionner de la même manière; Je n'ai également aucune idée si FreeBSD fonctionnerait.
la source
Donc j'essaie toujours d'étoffer cela, mais je pense avoir une idée qui fonctionnera. Comme vous l'avez remarqué, ce que vous essayez de faire est sinon impossible, extrêmement difficile à faire dans tous les shells (chaque variante que vous ajoutez au polyglotte augmente la complexité à un rythme supérieur à linéaire). vous pourriez probablement le faire si vous vous divisez en Bourne (sh, ash, dash, bash, ksh, pdksh, zsh, etc.) et des coquilles de style c (csh, tcsh, fish, etc.), mais la variation entre les
csh
variantes présente diverses intéressantes défis.Alors trichons et écrivons notre routine de détection dans un langage connu (bash avec une ligne shebang, C, perl, python, peu importe) et déterminons le nom de l'exécutable du parent. nous pouvons ensuite utiliser deux astuces pour renvoyer les informations au parent, à savoir les valeurs de retour et un seul mot écrit en sortie standard. Sur les sh sh descendus, nous retournerions 0 et écrivions le nom du shell car ils ont tous une bonne gestion du backtick. sur la famille C de shells, nous pouvons commencer à incrémenter la valeur de retour pour chaque ensemble d'incompatibilités que nous devons contourner. Des valeurs de retour supérieures à deux cents indiqueraient que des erreurs commençant par tout semblent correctes, mais je ne peux tout simplement pas dire qui est mon parent à deux cents.
Le programme interne semble facile sur Linux (
/proc/ppid/exe
c'est la moitié de la bataille). Je suis presque sûr que cela peut être fait sur bsd avec des options ps, mais je n'ai pas de système bsd en cours d'exécution pour le moment, et mon mac a besoin d'un nouveau disque dur (et n'est que de 10,4 de toute façon). Bien qu'il réduise considérablement les problèmes de syntaxe du shell, il introduit un ensemble différent de problèmes de compatibilité. Je pense toujours qu'il a des possibilités.la source
sh -c "..."
, qu'il a tiré d' une autre question . (Désolé: j'ai ignoré votre réponse au début parce que je n'y ai pas vu de code, et je ne suis revenu que plus tard.)case $shell in sh)...
(c'est la syntaxe Bourne uniquement), ouswitch ($shell)
(csh uniquement).test "$shell" = "sh" && do-something
travaille danscsh
/sh
/rc
/es
, mais pasfish
.../dev/null
. Mais j'ai une solution, que je publierai une fois que tout aura fonctionné.essayez quelque chose comme ça
la source
csh
ettcsh
.fish
, mais seulementfish
, malheureusement:ps h -p %self -o args='' | cut -f1 -d' '
. Cela crée un problème de poule et d'oeuf ... vous devez savoir que vous êtesfish
dans le but d'exécuter lafish
version du code ...set shell_bin=`ps -p $$ -o args='' | cut -f1 -d' '`
- fonctionnera avec CSH mais pas avec les autrescsh
/tcsh
, il était cette partie:ps -p $$ -o args='' | cut -f1 -d' '
qui retourne-sh
surcsh
, et-csh
surtcsh
.Je crois que vous ne pouvez pas toujours obtenir le nom du shell actuel , et je pense que vous devez être conscient des limites de ce qui est possible.
Sur les distributions Linux, la plupart des utilisateurs auraient
bash
comme login et shell interactif (carbash
c'est le shell par défaut sur la plupart des distributions). Certains utilisateurs définiraient leur shell surzsh
,csh
(et variantes) ou surfish
.(Comme d' autres commentaires et réponses expliquent, trouver de manière fiable la coquille sur
bash
,zsh
,tcsh
,fish
est déjà difficile)Mais certains utilisateurs étranges peuvent définir leur shell de connexion à tout autre chose - un interprète Lisp,
scsh
,es
, un langage de script à la Python, ou Ocaml ou Perl, etc ...- et il est leur liberté de le faire. Probablement, certaines personnes codent leur propre shell et l'utilisent de manière interactive. Même si vous avez trouvé leur étrange coquille, vous ne pourrez rien faire d'utile (donc je pense que vous ne devriez pas essayer d'obtenir le nom de la coquille).Je suppose donc que vous codez un fichier source (peut-être en générant un) pour configurer certains logiciels. Il suffit donc d'expliquer ce que vous faites et de coder pour le cas commun de
bash
(et peut-êtrezsh
&tcsh
) ....la source
utiliser ci-dessous à ses propres risques
la source
-f
optionreadlink
, certaines implémentations n'ont pas ce commutateur-f
est une option disponible, prenant l'format
argument comme.readlink
ne fonctionne pas sur mon puredarwin vm donc je ne sais pas ce qui se passe là-bas.