web-dev-qa-db-fra.com

Comment déterminer le Shell actuel sur lequel je travaille?

Comment puis-je déterminer le Shell actuel sur lequel je travaille?

La sortie de la commande ps suffira-t-elle?

Comment cela peut-il être fait dans différentes versions d'UNIX?

571
josh
  • Il existe 3 méthodes pour trouver le nom de l'exécutable du shell actuel:

    Veuillez noter que les trois approches peuvent être trompées si l'exécutable du shell est /bin/sh mais qu'il s'agit bien d'un bash renommé, par exemple (ce qui arrive fréquemment).

    Ainsi, votre deuxième question de savoir si la sortie de ps fera est résolue par "pas toujours".

    1. echo $0 - affichera le nom du programme ... qui, dans le cas de Shell, correspond au shell

    2. ps -ef | grep $$ | grep -v grep - Ceci recherchera l'ID de processus actuel dans la liste des processus en cours d'exécution. Comme le processus actuel est Shell, il sera inclus.

      Ce n’est pas fiable à 100%, car vous pourriez avoir d’AUTRES processus dont la liste ps inclut le même numéro que l’ID de processus de Shell, en particulier si cet ID est un petit # (par exemple, si le PID de Shell est "5", vous pouvez trouver processus appelés "Java5" ou "Perl5" dans la même sortie grep!!). C’est le deuxième problème de l’approche "ps", en plus de ne pas pouvoir compter sur le nom du shell.

    3. echo $Shell - Le chemin d'accès au shell actuel est stocké sous forme de variable Shell pour tout shell. La mise en garde pour celui-ci est que si vous lancez un Shell explicitement en tant que sous-processus (par exemple, ce n'est pas votre Shell de connexion), vous obtiendrez la valeur de votre Shell de connexion. Si cela est possible, utilisez l'approche ps ou $0.


  • Si, toutefois, l'exécutable ne correspond pas à votre shell actuel (par exemple, /bin/sh est en réalité bash ou ksh), vous avez besoin d'une heuristique. Voici quelques variables environnementales spécifiques à différents types de coques:

    • $version est défini sur tcsh

    • $BASH est réglé sur bash

    • $Shell (minuscule) est défini sur le nom du shell dans csh ou tcsh

    • $ZSH_NAME est défini sur zsh

    • ksh a $PS3 et $PS4, alors que Bourne Shell normal (sh) n'a que $PS1 et $PS2. Cela semble généralement être le plus difficile à distinguer - la SEULE différence entre un ensemble de variables d’environnement entre sh et ksh que nous avons installées sur le boîtier Solaris est $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS, $TMOUT.

726
DVK

ps -p $$

devrait fonctionner n'importe où les solutions impliquant ps -ef et grep do (sur toute variante Unix prenant en charge les options POSIX pour ps ) et ne souffriront pas des faux positifs introduit par grepping pour une séquence de chiffres pouvant apparaître ailleurs.

89
Matthew Slattery

Essayer

ps -p $$ -oargs=

ou

ps -p $$ -ocomm=
37
Nahuel Fouilleul

Si vous voulez juste vous assurer que l'utilisateur appelle un script avec bash:

if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
25
Peter Lamberg

Tu peux essayer:

ps | grep `echo $$` | awk '{ print $4 }'

Ou:

echo $Shell
19
karlphillip

$Shell n'a pas besoin de toujours montrer le shell actuel. Cela ne fait que refléter le shell par défaut à appeler.

Pour tester ce qui précède, dites que bash est le shell par défaut, essayez echo $Shell, puis dans le même terminal, entrez dans un autre shell (ksh par exemple) et essayez $Shell, vous verrez le résultat est bash dans les deux cas.

Pour obtenir le nom du shell actuel, utilisez cat /proc/$$/cmdline et le chemin d'accès à l'exécutable du shell par readlink /proc/$$/exe

11
sr01853

ps est la méthode la plus fiable. L'environnement de Shell n'est pas garanti et, même s'il l'est, il peut être facilement falsifié.

9
ennuikiller

J'ai un truc simple pour trouver le shell actuel. Il suffit de taper une chaîne aléatoire (qui n'est pas une commande). Il échouera et retournera une erreur "introuvable", mais en début de ligne, il indiquera quel shell il s'agit:

ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
8
user5659949

Cela donnera toujours le Shell utilisé - obtiendra le nom du fichier exécutable réel et non le nom du Shell (c'est-à-dire ksh93 au lieu de ksh etc.). Pour /bin/sh, le Shell utilisé: ie dash

ls -l /proc/$$/exe | sed 's%.*/%%'

Je sais qu'il y en a beaucoup qui disent que ls la sortie devrait être traitée plus récemment, mais quelle est la probabilité que vous utilisiez un Shell nommé avec des caractères spéciaux ou placé dans un répertoire nommé avec des caractères spéciaux? Si tel est toujours le cas, voici d’autres exemples qui procèdent différemment.

7
vadimbog

J'ai essayé de nombreuses approches différentes et la meilleure pour moi est:

ps -p $$

Cela fonctionne également sous Cygwin et ne peut pas produire de faux positifs en tant que grep de PID. Avec un peu de nettoyage, il ne sort qu’un nom d’exécutable (sous Cygwin avec chemin):

ps -p $$ | tail -1 | awk '{print $NF}'

Vous pouvez créer une fonction pour ne pas avoir à la mémoriser:

# print currently active Shell
shell () {
  ps -p $$ | tail -1 | awk '{print $NF}'
}

... puis exécutez simplement Shell.

Testé sous Debian et Cygwin.

Ma variante lors de l'impression du processus parent.

ps -p $$ | awk '$1 == PP {print $4}' PP=$$

Pourquoi exécuter des applications inutiles, quand 'awk' peut le faire pour vous?

4
Matthew Stier

À condition que votre /bin/sh prenne en charge le standard POSIX et que votre système ait la commande lsof installée - une alternative possible à lsof pourrait dans ce cas être pid2path - vous pouvez également utiliser ( ou adapter) le script suivant qui imprime les chemins complets:

#!/bin/sh
# cat /usr/local/bin/cursh
set -eu
pid="$$"

set -- sh bash zsh ksh ash dash csh tcsh pdksh mksh fish psh rc scsh bournesh wish Wish login

unset echo env sed ps lsof awk getconf

# getconf _POSIX_VERSION  # reliable test for availability of POSIX system?
PATH="`PATH=/usr/bin:/bin:/usr/sbin:/sbin getconf PATH`"
[ $? -ne 0 ] && { echo "'getconf PATH' failed"; exit 1; }
export PATH

cmd="lsof"
env -i PATH="${PATH}" type "$cmd" 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }

awkstr="`echo "$@" | sed 's/\([^ ]\{1,\}\)/|\/\1/g; s/ /$/g' | sed 's/^|//; s/$/$/'`"

ppid="`env -i PATH="${PATH}" ps -p $pid -o ppid=`"
[ "${ppid}"X = ""X ] && { echo "no ppid found"; exit 1; }

lsofstr="`lsof -p $ppid`" || 
   { printf "%s\n" "lsof failed" "try: Sudo lsof -p \`ps -p \$\$ -o ppid=\`"; exit 1; }

printf "%s\n" "${lsofstr}" | 
   LC_ALL=C awk -v var="${awkstr}" '$NF ~ var {print $NF}'
3
carlo
echo $$ # Gives the Parent Process ID 
ps -ef | grep $$ | awk '{print $8}' #use the PID to see what the process is.

de http://www.unix.com/unix-dummies-questions-answers/10390-how-do-you-know- what-your-current-Shell.html

2
Moisei

Aucune des réponses n'a fonctionné avec fish Shell (il n'a pas de variables $$ ou $0).

Cela fonctionne pour moi (testé sur sh, bash, fish, ksh, csh, true, tcsh, et zsh; openSUSE 13.2):

ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'

Cette commande génère une chaîne telle que bash. J'utilise ici uniquement ps, tail et sed (sans GNU extesions; essayez d'ajouter --posix pour le vérifier). Ce sont tous des commandes POSIX standard. Je suis sûr que tail peut être supprimé, mais mon sed fu n'est pas assez puissant pour le faire.

Il me semble que cette solution n’est pas très portable car elle ne fonctionne pas sous OS X. :(

2
rominf

Il existe de nombreuses façons de découvrir le shell et sa version correspondante. En voici quelques-uns qui ont fonctionné pour moi.

Droit devant

  1. $> echo $ (Vous donne le nom du programme. Dans mon cas, le résultat était - bash )
  2. $> $ Shell (Ceci vous emmène dans le shell et dans l'invite, vous obtenez le nom et la version du shell. Dans mon cas bash3.2 $ )
  3. $> echo $ Shell (Cela vous donnera un chemin exécutable. Dans mon cas /bin/bash )
  4. $> $ Shell --version (Ceci donnera des informations complètes sur le logiciel Shell avec le type de licence)

approche Hackish

$> ******* (Tapez un ensemble de caractères aléatoires et dans la sortie, vous obtiendrez le nom du shell. Dans mon cas - bash: chapitre2-a-sample-isomorphic- app: commande non trouvée )

2
Devang Paliwal

Ce n'est pas une solution très propre, mais fait ce que vous voulez.

Je me rends compte que la réponse est un peu tardive dans ce bon vieux 2015, mais ...

#MUST BE SOURCED..
getshell() {
    local Shell="`ps -p $$ | tail -1 | awk '{print $4}'`"

    shells_array=(
    # It is important that the shells are listed by the decrease of their length name.
        pdksh
        bash dash mksh
        zsh ksh
        sh
    )

    local suited=false
    for i in ${shells_array[*]}; do
        if ! [ -z `printf $Shell | grep $i` ] && ! $suited; then
            Shell=$i
            suited=true
        fi
    done

    echo $Shell
}
getshell

Maintenant, vous pouvez utiliser $(getshell) --version.

Cela ne fonctionne, cependant, que sur les coquilles ressemblant à ksh.

1
theoden

Sur Mac OS X (et FreeBSD):

ps -p $$ -axco command | sed -n '$p' 
1
zaga

Ma solution:

ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1

Cela devrait être portable sur différentes plates-formes et coques. Il utilise ps comme d'autres solutions, mais il ne s'appuie pas sur sed ou awk et filtre les fichiers indésirables de la tuyauterie et ps lui-même, de sorte que le shell doit toujours être le dernière entrée. De cette façon, nous n’avons pas besoin de recourir à des variables PID non portables ni de choisir les bonnes lignes et colonnes.

J'ai testé sur Debian et MacOS avec bash, zsh et fish (ce qui ne fonctionne pas avec la plupart de ces solutions sans changer l'expression spécifiquement pour fish, car elle utilise une variable PID différente).

1
wickles

Il n'est pas nécessaire d'insérer PID à partir de la sortie de "ps", car vous pouvez lire la ligne de commande correspondante pour tout PID de la structure de répertoire/proc:

echo $(cat /proc/$$/cmdline)

Cependant, cela pourrait ne pas être meilleur que simplement:

echo $0

À propos de l’exécution d’un shell différent de celui indiqué par le nom, l’idée est de demander une version de Shell au nom précédent:

<some_Shell> --version

sh semble échouer avec le code de sortie 2 alors que d'autres donnent quelque chose d'utile (mais je ne peux pas tout vérifier car je ne les ai pas):

$ sh --version
sh: 0: Illegal option --
echo $?
2
1
ajaaskel

Procédez comme suit pour savoir si votre shell utilise DASH/BASH.

1) ls –la/bin/sh, si le résultat est / bin/sh ->/bin/bash ==> Ensuite, votre shell utilise BASH.

si le résultat est / bin/sh ->/bin/dash ==> Votre shell utilise alors DASH.

Si vous souhaitez passer de BASH à DASH ou inversement, utilisez le code ci-dessous ln -s/bin/bash/bin/sh (changez Shell en BASH)

REMARQUE: Si la commande ci-dessus entraîne une erreur indiquant que/bin/sh existe déjà, supprimez le fichier/bin/sh et réessayez.

1
Shiva

Si vous voulez juste vérifier que vous utilisez (une version particulière de) Bash, le meilleur moyen de le faire est d'utiliser la variable de tableau $BASH_VERSINFO. En tant que variable de tableau (en lecture seule), il ne peut pas être défini dans l'environnement. Vous pouvez donc être sûr qu'elle provient (le cas échéant) du Shell en cours. Cependant, Bash ayant un comportement différent lorsqu'il est appelé sh, vous devez également vérifier que la variable d'environnement $BASH se termine par /bash.

Dans un script que j'ai écrit qui utilise des noms de fonction avec - (sans trait de soulignement) et dépend de tableaux associatifs (ajoutés dans Bash 4), j'ai le contrôle de cohérence suivant (avec un message d'erreur utile à l'utilisateur):

case `eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null` in
    */bash@[456789])
        # Claims bash version 4+, check for func-names and associative arrays
        if ! eval "declare -A _ARRAY && func-name() { :; }" 2>/dev/null; then
            echo >&2 "bash $BASH_VERSION is not supported (not really bash?)"
            exit 1
        fi
        ;;
    */bash@[123])
        echo >&2 "bash $BASH_VERSION is not supported (version 4+ required)"
        exit 1
        ;;
    *)
        echo >&2 "This script requires BASH (version 4+) - not regular sh"
        echo >&2 "Re-run as \"bash $CMD\" for proper operation"
        exit 1
        ;;
esac

Dans le premier cas, vous pouvez omettre la vérification fonctionnelle quelque peu paranoïaque des fonctionnalités et supposer que les futures versions de bash seront compatibles.

1
Alex Dupuy

Veuillez utiliser la commande ci-dessous:

 # ps -p $$ | tail -1 | awk '{print $4}'
0
Ranjithkumar T