Tester des capacités particulières (par exemple, fait-il de la !substitution?) Est probablement plus portable que de trouver le nom du shell. La coutume locale pourrait vous faire exécuter quelque chose nommé /bin/shqui pourrait en fait être ash, dash, bash, etc.
msw
1
@msw: On dirait un bon commentaire sauf qu'il me laisse me demander "comment?".
nobar
Il semble qu'il n'y ait pas de réponse simple à cette question. Si nous ne pouvons pas interroger le shell, la meilleure approche est peut-être de toujours spécifier le shell. Je ne suis pas sûr que ce soit toujours possible, mais c'est peut-être plus facile à réaliser que les gens ne le pensent généralement.
@Aniket, pas autant d'aide qu'on pourrait le penser - qui ne s'intéresse qu'aux processus shell interactifs .
Toby Speight
Réponses:
794
Il existe trois approches pour trouver le nom de l'exécutable du shell actuel:
Veuillez noter que les trois approches peuvent être dupées si l'exécutable du shell l'est /bin/sh, mais c'est vraiment un renommé bash, par exemple (ce qui arrive fréquemment).
Ainsi, votre deuxième question de savoir si la pssortie fera l'affaire est répondue par " pas toujours ".
echo $0 - affichera le nom du programme ... qui dans le cas du shell est le shell réel.
ps -ef | grep $$ | grep -v grep- cela recherchera l'ID de processus actuel dans la liste des processus en cours d'exécution. Puisque le processus actuel est le shell, il sera inclus.
Ce n'est pas fiable à 100%, car vous pourriez avoir d' autres processus dont la psliste comprend le même numéro que l'ID de processus du shell, en particulier si cet ID est un petit nombre (par exemple, si le PID du shell est "5", vous pouvez trouver des processus appelés "java5" ou "perl5" dans la même grepsortie!). C'est le deuxième problème avec l'approche "ps", en plus de ne pas pouvoir s'appuyer sur le nom du shell.
echo $SHELL- Le chemin vers le shell courant est stocké comme SHELLvariable pour n'importe quel 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 à la place. Si c'est une possibilité, utilisez l' approche psou $0.
Si, cependant, l'exécutable ne correspond pas à votre shell réel (par exemple, /bin/shest en fait bash ou ksh), vous avez besoin d'une heuristique. Voici quelques variables environnementales spécifiques à différents coques:
$version est défini sur tcsh
$BASH est réglé sur bash
$shell (en minuscules) est défini sur le nom réel du shell dans csh ou tcsh
$ZSH_NAME est défini sur zsh
ksh a $PS3et $PS4mis, tandis que le shell Bourne normal ( sh) n'a que $PS1et $PS2mis. Cela semble généralement comme les plus difficiles à distinguer - la seule différence dans l'ensemble des variables d'environnement entre shet kshnous avons installé sur Solaris Boxen est $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDSet $TMOUT.
ps -p $$comme le souligne Matthew Slattery . Pour ksh: echo $KSH_VERSIONou echo ${.sh.version}.
pause jusqu'à nouvel ordre.
@Dennish - mon ksh en ce moment n'a pas KSH_VERSION défini. et echo ${.sh.version}renvoie "Bad Substitution". Voir ma solution ci
DVK
3
« ps -ef | grep …... Ce n'est pas fiable à 100% que ... » En utilisant une expression régulière simple via egrepou grep -epeut apporter facilement la fiabilité jusqu'à pour-tout-et-intentions fins 100%: ps -ef | egrep "^\s*\d+\s+$$\s+". Les ^marques que nous commençons dès le début de la ligne, les \d+Eats l'UID, le $$correspond au PID, et \s*et \s+compte et assurer des espaces entre les autres parties.
Slipp D. Thompson
2
@ SlippD.Thompson ne fonctionnait pas sous GNU / Linux. Mais cela semble fonctionner:ps -ef | awk '$2==pid' pid=$$
jarno
98
ps -p $$
devrait fonctionner partout où les solutions impliquent ps -efet grepfont (sur toute variante Unix qui prend en charge les options POSIXps ) et ne souffrira pas des faux positifs introduits par la recherche d'une séquence de chiffres qui peut apparaître ailleurs.
Certains shells ont leur propre version intégrée psqui peut ne pas comprendre -p, vous devrez donc peut-être l'utiliser /bin/ps -p $$.
pause jusqu'à nouvel ordre.
13
Tous les obus que je connais comprennent, $$sauf ceux fishavec lesquels vous auriez à utiliser ps -p %self.
pause jusqu'à nouvel ordre.
3
En fait, vous ne devriez pas compter sur des chemins difficiles tels que /bin/ps. pspourrait facilement (en fait c'est tout à fait normal de nos jours) être installé dans /usr/bin. $(which ps) -p $$est une meilleure façon. Bien sûr, cela ne fonctionnera pas dans les poissons, et éventuellement dans d'autres coquilles. Je pense que c'est (which ps) -p %selfdans le poisson.
Aron Cederholm
1
Dans certains systèmes minimaux comme un docker debian-slim, ps peut ne pas être là. Dans ce cas, cette approche fonctionne toujours:readlink /proc/$$/exe
mxmlnkn
si votre shest émulé par bash, ps -p vous donne /usr/bin/bashmême si vous l'exécutez commesh
Ceci est un joli court. Je m'utilisais ps -o fname --no-headers $$.
Anne van Rossum
Merci. J'ai trouvé que c'était la meilleure option à utiliser dans un script pour protéger des commandes spécifiques à bash test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash. (La ligne suivante de mon script a l'équivalent de csh.)
craq
1
J'ai trouvé que si vous faites cela à partir d'un sous-shell, cela peut conduire à des lignes supplémentaires parasites en faisant correspondre le PID du parent ainsi que le processus de shell réel. Pour cela, j'utilise à la -qplace de -p:SHELL=$(ps -ocomm= -q $$)
Steve
35
Si vous voulez simplement vous assurer que l'utilisateur invoque un script avec Bash:
if[!-n "$BASH"];then echo Please run this script $0 with bash;exit1;fi
Ce devrait être celui le plus proche du sommet. Merci beaucoup.
Alex Skrypnyk
4
Il ne devrait pas être plus proche du sommet, car il ne répond pas du tout à la question. Si la question est "Comment vérifier si le script s'exécute sous bash", je vote pour.
David Ferenczy Rogožan
2
@DawidFerenczy - Cette question est le meilleur résultat lorsque vous recherchez cette phrase. À long terme, je pense qu'il est beaucoup plus important que les réponses répondent à ce que les gens recherchent plutôt que de répondre à la question d'origine.
ArtOfWarfare
3
De plus, la variable $ BASH est définie sous tcsh si le tcsh est
appelé
C'est très utile, merci. Juste adapté un peu, en mettant cela comme la deuxième ligne après #!/bin/bash: if [ ! -n "$BASH" ] ;then exec bash $0; fi. Avec cette ligne, le script est exécuté à l'aide de bash même s'il a commencé à utiliser ksh ou sh. Mon cas d'utilisation n'a pas besoin d'arguments de ligne de commande, mais ils pourraient être ajoutés après $0si nécessaire.
Quel est l'intérêt de grep suivi de awk, quand /pattern/ { action }va faire?
Jens
# dans l'alias zshell shell = 'echo $ {SHELL: t}'
SergioAraujo
4
$SHELLLa variable d'environnement contient un shell, qui est configuré par défaut pour un utilisateur actuel. Il ne reflète pas un shell en cours d'exécution. Il est également préférable d'utiliser ps -p $$que de saluer $$ en raison de faux positifs.
David Ferenczy Rogožan
Le $ SHELL env. La variable pointe vers le shell «parent», comme spécifié dans la spécification POSIX: SHELL Cette variable doit représenter un chemin d'accès de l'interpréteur de langage de commande préféré de l'utilisateur. Par conséquent, la valeur de $ SHELL peut ne pas être le shell actuel.
Theo
tous à l'intérieur awk,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
go2null
16
$SHELLn'a pas toujours besoin d'afficher le shell actuel. Il ne reflète que le shell par défaut à invoquer.
Pour tester ce qui précède, disons bashest le shell par défaut, essayez echo $SHELL, puis dans le même terminal, entrez dans un autre shell ( KornShell (ksh) par exemple) et essayez $SHELL. Vous verrez le résultat comme bash dans les deux cas.
Pour obtenir le nom du shell actuel, utilisez cat /proc/$$/cmdline. Et le chemin vers le shell exécutable par readlink /proc/$$/exe.
ps est la méthode la plus fiable. La variable d'environnement SHELL n'est pas garantie d'être définie et même si elle l'est, elle peut être facilement usurpée.
+1 $ SHELL est le shell par défaut pour les programmes qui doivent en générer un. Il ne reflète pas nécessairement le shell en cours d'exécution.
Jim Lewis
8
J'ai une astuce simple pour trouver le shell actuel. Tapez simplement une chaîne aléatoire (qui n'est pas une commande). Il échouera et renverra une erreur "introuvable", mais au début de la ligne, il dira de quel shell il s'agit:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
Pas bon dans un script. echo 'aaaa' > script; chmod +x script; ./scriptdonne./script.sh: 1: aaaa: not found
slim
6
Ce qui suit donnera toujours le shell réel utilisé - il obtient le nom de l'exécutable réel et non le nom du shell (c'est- ksh93à- dire au lieu de ksh, etc.). Pour /bin/sh, il montrera le shell réellement utilisé, ie dash.
ls -l /proc/$$/exe | sed 's%.*/%%'
Je sais qu'il y en a beaucoup qui disent que la lssortie ne devrait jamais être traitée, mais quelle est la probabilité que vous ayez un shell que vous utilisez qui est 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, il existe de nombreux autres exemples pour le faire différemment.
Comme l'a souligné Toby Speight , ce serait une façon plus appropriée et plus propre d'y parvenir:
Cela ne fait que des erreurs sur tous les Unices qui ne fournissent pas /proc. Tout le monde n'est pas une boîte Linux.
Jens
5
Et si vous êtes sous Linux, nous préférerions basename $(readlink /proc/$$/exe)à ls+ sed+ echo.
Toby Speight
1
Cela donnera le nom de l' exécutable réel , pas le shell réel . Lorsque le shell réel est lié en tant qu'applet busybox, disons ash -> /bin/busybox, cela donnera / bin / busybox.
stepse
6
J'ai essayé de nombreuses approches différentes et la meilleure pour moi est:
ps -p $$
Il fonctionne également sous Cygwin et ne peut pas produire de faux positifs comme greffe PID. Avec un peu de nettoyage, il sort juste un nom 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}'}
Depuis ma configuration (Cygwin | Windows 7), votre réponse est la meilleure, et ps -p $$ | queue -1 | gawk '{print $ NF}' fonctionne même à partir de cmd sans $ bash. Veuillez noter gawk au lieu de awk, car awk ne fonctionne que depuis bash.
WebComer
@WebComer Désolé, je ne suis pas sûr de ce que vous entendez par " fonctionne même à partir de cmd sans $ bash ". Même si vous avez des ports Windows ps, tailet gawk, cmd ne se définit pas $$comme étant un PID, il ne peut donc certainement pas fonctionner sous la cmd standard.
David Ferenczy Rogožan
Pourquoi pas simplement ps -p$$ -o comm=? POSIX indique que la spécification de tous les en-têtes vides supprime complètement l'en-tête. Nous échouons toujours (comme toutes les psréponses) lorsque nous sommes sourcés par un script exécuté directement (par exemple #!/bin/sh).
Toby Speight
5
Ma variante sur l'impression du processus parent:
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
N'exécutez pas d'applications inutiles quand AWK peut le faire pour vous.
Pourquoi exécuter un inutile awk, quand ps -p "$$" -o 'comm='peut-il le faire pour vous?
Toby Speight
5
Il existe de nombreuses façons de découvrir le shell et sa version correspondante. Voici quelques-uns qui ont fonctionné pour moi.
Simple
$> echo $ 0 (vous donne le nom du programme. Dans mon cas, la sortie était -bash .)
$> $ SHELL (Cela vous emmène dans le shell et à l'invite vous obtenez le nom et la version du shell. Dans mon cas bash3.2 $ .)
$> echo $ SHELL (Cela vous donnera un chemin exécutable. Dans mon cas / bin / bash .)
$> $ SHELL --version (Cela 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: chapter2-a-sample-isomorphic-app: command not found )
À condition que votre /bin/shsupporte la norme POSIX et que votre système ait la lsofcommande installée - une alternative possible à lsofpourrait 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/curshset-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";exit1;}export PATH
cmd="lsof"
env -i PATH="${PATH}" type "$cmd"1>/dev/null2>&1||{ echo "$cmd not found";exit1;}
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";exit1;}
lsofstr="`lsof -p $ppid`"||{ printf "%s\n""lsof failed""try: sudo lsof -p \`ps -p \$\$ -o ppid=\`";exit1;}
printf "%s\n""${lsofstr}"|
LC_ALL=C awk -v var="${awkstr}"'$NF ~ var {print $NF}'
cela fonctionne dans les poissons! mais pour moi, échoue dans bash, en raison de l' -ioption (-> ignorer l'environnement) envdans la ligne où vous vérifiez lsofsa disponibilité. il échoue avec: env -i PATH="${PATH}" type lsof->env: ‘type’: No such file or directory
hoijui
2
Si vous voulez simplement vérifier que vous exécutez (une version particulière de) Bash, la meilleure façon de le faire est d'utiliser la $BASH_VERSINFOvariable de tableau. En tant que variable de tableau (en lecture seule), elle ne peut pas être définie dans l'environnement, vous pouvez donc être sûr qu'elle provient (le cas échéant) du shell actuel.
Cependant, puisque Bash a un comportement différent lorsqu'il est appelé as sh, vous devez également vérifier la $BASHfin de la variable d'environnement avec /bash.
Dans un script que j'ai écrit qui utilise des noms de fonction avec -(pas de soulignement), et dépend des tableaux associatifs (ajoutés dans Bash 4), j'ai le contrôle de cohérence suivant (avec un message d'erreur utilisateur utile):
case`eval 'echo $BASH@${BASH_VERSINFO[0]}' 2>/dev/null`in*/bash@[456789])# Claims bash version 4+, check for func-names and associative arraysif!eval"declare -A _ARRAY && func-name() { :; }"2>/dev/null;then
echo >&2"bash $BASH_VERSION is not supported (not really bash?)"exit1fi;;*/bash@[123])
echo >&2"bash $BASH_VERSION is not supported (version 4+ required)"exit1;;*)
echo >&2"This script requires BASH (version 4+) - not regular sh"
echo >&2"Re-run as \"bash $CMD\" for proper operation"exit1;;esac
Vous pouvez omettre la vérification fonctionnelle quelque peu paranoïaque des fonctionnalités dans le premier cas, et supposer simplement que les futures versions de Bash seront compatibles.
Aucune des réponses n'a fonctionné avec le fishshell (il n'a pas les 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 comme bash. Ici , je suis seulement en utilisant ps, tailet sed(sans extesions GNU, essayez d'ajouter --posixà vérifier). Ce sont toutes des commandes POSIX standard. Je suis sûr qu'il tailpeut être retiré, mais mon sedfu n'est pas assez fort pour le faire.
Il me semble que cette solution n'est pas très portable car elle ne fonctionne pas sous OS X. :(
Cela devrait être portable sur différentes plates-formes et coquilles. Il utilise pscomme les autres solutions, mais il ne s'appuie pas sur sedou awket filtre les fichiers indésirables de la tuyauterie et de pslui - même, de sorte que le shell doit toujours être la dernière entrée. De cette façon, nous n'avons pas besoin de compter sur des variables PID non portables ou de choisir les bonnes lignes et colonnes.
J'ai testé sur Debian et macOS avec Bash, Z shell ( zsh) et fish (ce qui ne fonctionne pas avec la plupart de ces solutions sans changer l'expression spécifiquement pour fish, car il utilise une variable PID différente).
J'ai essayé cela en utilisant zsh, et ça m'a donné -bash.
user137369
Sur mon système (maintenant), testé avec bash et dash, ce retour mutt...: -b
F. Hauri
1
Grepping PID de la sortie de "ps" n'est pas nécessaire, car vous pouvez lire la ligne de commande respective pour n'importe quel PID à partir de la structure du répertoire / proc:
echo $(cat /proc/$$/cmdline)
Cependant, cela pourrait ne pas être mieux que simplement:
echo $0
À propos de l'exécution d'un shell réellement différent de celui indiqué par le nom, une idée est de demander la version du shell en utilisant le nom que vous avez obtenu précédemment:
<some_shell> --version
sh semble échouer avec le code de sortie 2 tandis que d'autres donnent quelque chose d'utile (mais je ne suis pas en mesure de tout vérifier car je ne les ai pas):
Ce n'est pas une solution très propre, mais elle fait ce que vous voulez.
# MUST BE SOURCED..
getshell(){local shell="`ps -p $$ | tail -1 | awk '{print $4}'`"
shells_array=(# It is important that the shells are listed in descending order of their name length.
pdksh
bash dash mksh
zsh ksh
sh
)local suited=falsefor i in ${shells_array[*]};doif![-z `printf $shell | grep $i`]&&! $suited;then
shell=$i
suited=truefidone
echo $shell
}
getshell
"Cela ne fonctionne, cependant, que sur des shells de type ksh." Voulez-vous dire que je dois vérifier le shell avant d' exécuter cela? Hmm ...
jpaugh
@jpaugh, les listes doivent être pris en charge par le shell de sourcing ce code, ce qui est le cas dash, yashetc. En règle générale, si vous utilisez bash, zsh, ksh, quel que soit - vous ne devriez pas se soucier de ces choses.
theoden8
Donc, vous comptez bash comme "ksh-like"? Je l'ai. Cela a plus de sens
jpaugh
@jpaugh, eh bien, c'est ce que je voulais dire parce que kshl'ensemble de fonctionnalités est principalement un sous-ensemble de bashfonctionnalités (mais je n'ai pas vérifié cela soigneusement cependant).
theoden8
1
Procédez comme suit pour savoir si votre shell utilise Dash / Bash.
ls –la /bin/sh:
si le résultat est /bin/sh -> /bin/bash==> alors votre shell utilise Bash.
si le résultat est /bin/sh ->/bin/dash==> alors votre shell utilise Dash.
Si vous souhaitez passer de Bash à Dash ou vice-versa, utilisez le code ci-dessous:
ln -s /bin/bash /bin/sh (changer le shell en Bash)
Remarque : Si la commande ci-dessus entraîne une erreur indiquant que / bin / sh existe déjà, supprimez / bin / sh et réessayez.
Le premier est un non-sens, echo $SHELLfait ce que vous essayez de faire et le fait bien. Le second n'est pas bon non plus, car $SHELLla variable d'environnement contient un shell par défaut pour un utilisateur actuel, pas un shell en cours d'exécution. Si j'ai par exemple bashdéfini comme shell par défaut, exécutez zshet echo $SHELL, il s'imprimera bash.
David Ferenczy Rogožan
Vous avez raison Dawid Ferenczy, nous pouvons utiliser la commande ps pour déterminer le shell actuel. [# ps -p $$ | queue -1 | awk '{print $ 4}'].
Ranjithkumar T
echo $SHELLpeut être des ordures: ~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$
SaltwaterC
-2
Celui-ci fonctionne bien sur Red Hat Linux (RHEL), macOS, BSD et certains AIX :
ps -T $$ | awk 'NR==2{print $NF}'
alternativement, le suivant devrait également fonctionner si pstree est disponible,
!
substitution?) Est probablement plus portable que de trouver le nom du shell. La coutume locale pourrait vous faire exécuter quelque chose nommé/bin/sh
qui pourrait en fait être ash, dash, bash, etc.Réponses:
Il existe trois approches pour trouver le nom de l'exécutable du shell actuel:
Veuillez noter que les trois approches peuvent être dupées si l'exécutable du shell l'est
/bin/sh
, mais c'est vraiment un renommébash
, par exemple (ce qui arrive fréquemment).Ainsi, votre deuxième question de savoir si la
ps
sortie fera l'affaire est répondue par " pas toujours ".echo $0
- affichera le nom du programme ... qui dans le cas du shell est le shell réel.ps -ef | grep $$ | grep -v grep
- cela recherchera l'ID de processus actuel dans la liste des processus en cours d'exécution. Puisque le processus actuel est le shell, il sera inclus.Ce n'est pas fiable à 100%, car vous pourriez avoir d' autres processus dont la
ps
liste comprend le même numéro que l'ID de processus du shell, en particulier si cet ID est un petit nombre (par exemple, si le PID du shell est "5", vous pouvez trouver des processus appelés "java5" ou "perl5" dans la mêmegrep
sortie!). C'est le deuxième problème avec l'approche "ps", en plus de ne pas pouvoir s'appuyer sur le nom du shell.echo $SHELL
- Le chemin vers le shell courant est stocké commeSHELL
variable pour n'importe quel 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 à la place. Si c'est une possibilité, utilisez l' approcheps
ou$0
.Si, cependant, l'exécutable ne correspond pas à votre shell réel (par exemple,
/bin/sh
est en fait bash ou ksh), vous avez besoin d'une heuristique. Voici quelques variables environnementales spécifiques à différents coques:$version
est défini sur tcsh$BASH
est réglé sur bash$shell
(en minuscules) est défini sur le nom réel du shell dans csh ou tcsh$ZSH_NAME
est défini sur zshksh a
$PS3
et$PS4
mis, tandis que le shell Bourne normal (sh
) n'a que$PS1
et$PS2
mis. Cela semble généralement comme les plus difficiles à distinguer - la seule différence dans l'ensemble des variables d'environnement entresh
etksh
nous avons installé sur Solaris Boxen est$ERRNO
,$FCEDIT
,$LINENO
,$PPID
,$PS3
,$PS4
,$RANDOM
,$SECONDS
et$TMOUT
.la source
ps -p $$
comme le souligne Matthew Slattery . Pourksh
:echo $KSH_VERSION
ouecho ${.sh.version}
.echo ${.sh.version}
renvoie "Bad Substitution". Voir ma solution cips -ef | grep …
... Ce n'est pas fiable à 100% que ... » En utilisant une expression régulière simple viaegrep
ougrep -e
peut apporter facilement la fiabilité jusqu'à pour-tout-et-intentions fins 100%:ps -ef | egrep "^\s*\d+\s+$$\s+"
. Les^
marques que nous commençons dès le début de la ligne, les\d+
Eats l'UID, le$$
correspond au PID, et\s*
et\s+
compte et assurer des espaces entre les autres parties.ps -ef | awk '$2==pid' pid=$$
ps -p $$
devrait fonctionner partout où les solutions impliquent
ps -ef
etgrep
font (sur toute variante Unix qui prend en charge les options POSIXps
) et ne souffrira pas des faux positifs introduits par la recherche d'une séquence de chiffres qui peut apparaître ailleurs.la source
ps
qui peut ne pas comprendre-p
, vous devrez donc peut-être l'utiliser/bin/ps -p $$
.$$
sauf ceuxfish
avec lesquels vous auriez à utiliserps -p %self
./bin/ps
.ps
pourrait facilement (en fait c'est tout à fait normal de nos jours) être installé dans/usr/bin
.$(which ps) -p $$
est une meilleure façon. Bien sûr, cela ne fonctionnera pas dans les poissons, et éventuellement dans d'autres coquilles. Je pense que c'est(which ps) -p %self
dans le poisson.readlink /proc/$$/exe
sh
est émulé parbash
, ps -p vous donne/usr/bin/bash
même si vous l'exécutez commesh
Essayer
ou
la source
ps -o fname --no-headers $$
.test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash
. (La ligne suivante de mon script a l'équivalent de csh.)-q
place de-p
:SHELL=$(ps -ocomm= -q $$)
Si vous voulez simplement vous assurer que l'utilisateur invoque un script avec Bash:
la source
#!/bin/bash
:if [ ! -n "$BASH" ] ;then exec bash $0; fi
. Avec cette ligne, le script est exécuté à l'aide de bash même s'il a commencé à utiliser ksh ou sh. Mon cas d'utilisation n'a pas besoin d'arguments de ligne de commande, mais ils pourraient être ajoutés après$0
si nécessaire.Tu peux essayer:
Ou:
la source
/pattern/ { action }
va faire?$SHELL
La variable d'environnement contient un shell, qui est configuré par défaut pour un utilisateur actuel. Il ne reflète pas un shell en cours d'exécution. Il est également préférable d'utiliserps -p $$
que de saluer $$ en raison de faux positifs.awk
,ps | awk '$1=='$$' { n=split($4,a,"/"); print a[n] }'
$SHELL
n'a pas toujours besoin d'afficher le shell actuel. Il ne reflète que le shell par défaut à invoquer.Pour tester ce qui précède, disons
bash
est le shell par défaut, essayezecho $SHELL
, puis dans le même terminal, entrez dans un autre shell ( KornShell (ksh) par exemple) et essayez$SHELL
. Vous verrez le résultat comme bash dans les deux cas.Pour obtenir le nom du shell actuel, utilisez
cat /proc/$$/cmdline
. Et le chemin vers le shell exécutable parreadlink /proc/$$/exe
.la source
/proc
.ps est la méthode la plus fiable. La variable d'environnement SHELL n'est pas garantie d'être définie et même si elle l'est, elle peut être facilement usurpée.
la source
J'ai une astuce simple pour trouver le shell actuel. Tapez simplement une chaîne aléatoire (qui n'est pas une commande). Il échouera et renverra une erreur "introuvable", mais au début de la ligne, il dira de quel shell il s'agit:
la source
echo 'aaaa' > script; chmod +x script; ./script
donne./script.sh: 1: aaaa: not found
Ce qui suit donnera toujours le shell réel utilisé - il obtient le nom de l'exécutable réel et non le nom du shell (c'est-
ksh93
à- dire au lieu deksh
, etc.). Pour/bin/sh
, il montrera le shell réellement utilisé, iedash
.Je sais qu'il y en a beaucoup qui disent que la
ls
sortie ne devrait jamais être traitée, mais quelle est la probabilité que vous ayez un shell que vous utilisez qui est 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, il existe de nombreux autres exemples pour le faire différemment.Comme l'a souligné Toby Speight , ce serait une façon plus appropriée et plus propre d'y parvenir:
la source
/proc
. Tout le monde n'est pas une boîte Linux.basename $(readlink /proc/$$/exe)
àls
+sed
+echo
.ash -> /bin/busybox
, cela donnera / bin / busybox.J'ai essayé de nombreuses approches différentes et la meilleure pour moi est:
Il fonctionne également sous Cygwin et ne peut pas produire de faux positifs comme greffe PID. Avec un peu de nettoyage, il sort juste un nom exécutable (sous Cygwin avec chemin):
Vous pouvez créer une fonction pour ne pas avoir à la mémoriser:
... puis exécutez
shell
.Il a été testé sous Debian et Cygwin.
la source
ps
,tail
etgawk
, cmd ne se définit pas$$
comme étant un PID, il ne peut donc certainement pas fonctionner sous la cmd standard.ps -p$$ -o comm=
? POSIX indique que la spécification de tous les en-têtes vides supprime complètement l'en-tête. Nous échouons toujours (comme toutes lesps
réponses) lorsque nous sommes sourcés par un script exécuté directement (par exemple#!/bin/sh
).Ma variante sur l'impression du processus parent:
N'exécutez pas d'applications inutiles quand AWK peut le faire pour vous.
la source
awk
, quandps -p "$$" -o 'comm='
peut-il le faire pour vous?Il existe de nombreuses façons de découvrir le shell et sa version correspondante. Voici quelques-uns qui ont fonctionné pour moi.
Simple
Approche hackish
$> ******* (Tapez un ensemble de caractères aléatoires et dans la sortie, vous obtiendrez le nom du shell. Dans mon cas -bash: chapter2-a-sample-isomorphic-app: command not found )
la source
À condition que votre
/bin/sh
supporte la norme POSIX et que votre système ait lalsof
commande installée - une alternative possible àlsof
pourrait dans ce cas êtrepid2path
- vous pouvez également utiliser (ou adapter) le script suivant qui imprime les chemins complets:la source
-i
option (-> ignorer l'environnement)env
dans la ligne où vous vérifiezlsof
sa disponibilité. il échoue avec:env -i PATH="${PATH}" type lsof
->env: ‘type’: No such file or directory
Si vous voulez simplement vérifier que vous exécutez (une version particulière de) Bash, la meilleure façon de le faire est d'utiliser la
$BASH_VERSINFO
variable de tableau. En tant que variable de tableau (en lecture seule), elle ne peut pas être définie dans l'environnement, vous pouvez donc être sûr qu'elle provient (le cas échéant) du shell actuel.Cependant, puisque Bash a un comportement différent lorsqu'il est appelé as
sh
, vous devez également vérifier la$BASH
fin de la variable d'environnement avec/bash
.Dans un script que j'ai écrit qui utilise des noms de fonction avec
-
(pas de soulignement), et dépend des tableaux associatifs (ajoutés dans Bash 4), j'ai le contrôle de cohérence suivant (avec un message d'erreur utilisateur utile):Vous pouvez omettre la vérification fonctionnelle quelque peu paranoïaque des fonctionnalités dans le premier cas, et supposer simplement que les futures versions de Bash seront compatibles.
la source
Aucune des réponses n'a fonctionné avec le
fish
shell (il n'a pas les variables$$
ou$0
).Cela fonctionne pour moi (testé sur
sh
,bash
,fish
,ksh
,csh
,true
,tcsh
, etzsh
, openSUSE 13.2):Cette commande génère une chaîne comme
bash
. Ici , je suis seulement en utilisantps
,tail
etsed
(sans extesions GNU, essayez d'ajouter--posix
à vérifier). Ce sont toutes des commandes POSIX standard. Je suis sûr qu'iltail
peut être retiré, mais monsed
fu n'est pas assez fort pour le faire.Il me semble que cette solution n'est pas très portable car elle ne fonctionne pas sous OS X. :(
la source
sed: invalid option -- 'E'
sur bash 3.2.51 et tcsh 6.15.00Ma solution:
Cela devrait être portable sur différentes plates-formes et coquilles. Il utilise
ps
comme les autres solutions, mais il ne s'appuie pas sursed
ouawk
et filtre les fichiers indésirables de la tuyauterie et deps
lui - même, de sorte que le shell doit toujours être la dernière entrée. De cette façon, nous n'avons pas besoin de compter sur des variables PID non portables ou de choisir les bonnes lignes et colonnes.J'ai testé sur Debian et macOS avec Bash, Z shell (
zsh
) et fish (ce qui ne fonctionne pas avec la plupart de ces solutions sans changer l'expression spécifiquement pour fish, car il utilise une variable PID différente).la source
De Comment savez-vous quel est votre shell actuel? .
la source
grep $$
n'est pas fiable.ps -ef | awk -v pid=$$ '$2==pid { print $8 }'
c'est mieux, mais pourquoi ne pas simplement l'utiliserps -p $$
?Sous Mac OS X (et FreeBSD):
la source
zsh
, et ça m'a donné-bash
.mutt
...: -bGrepping PID de la sortie de "ps" n'est pas nécessaire, car vous pouvez lire la ligne de commande respective pour n'importe quel PID à partir de la structure du répertoire / proc:
Cependant, cela pourrait ne pas être mieux que simplement:
À propos de l'exécution d'un shell réellement différent de celui indiqué par le nom, une idée est de demander la version du shell en utilisant le nom que vous avez obtenu précédemment:
sh
semble échouer avec le code de sortie 2 tandis que d'autres donnent quelque chose d'utile (mais je ne suis pas en mesure de tout vérifier car je ne les ai pas):la source
Ce n'est pas une solution très propre, mais elle fait ce que vous voulez.
Vous pouvez maintenant utiliser
$(getshell) --version
.Cela ne fonctionne cependant que sur les shells de type KornShell (ksh).
la source
dash
,yash
etc. En règle générale, si vous utilisezbash
,zsh
,ksh
, quel que soit - vous ne devriez pas se soucier de ces choses.ksh
l'ensemble de fonctionnalités est principalement un sous-ensemble debash
fonctionnalités (mais je n'ai pas vérifié cela soigneusement cependant).Procédez comme suit pour savoir si votre shell utilise Dash / Bash.
ls –la /bin/sh
:si le résultat est
/bin/sh -> /bin/bash
==> alors votre shell utilise Bash.si le résultat est
/bin/sh ->/bin/dash
==> alors votre shell utilise Dash.Si vous souhaitez passer de Bash à Dash ou vice-versa, utilisez le code ci-dessous:
ln -s /bin/bash /bin/sh
(changer le shell en Bash)Remarque : Si la commande ci-dessus entraîne une erreur indiquant que / bin / sh existe déjà, supprimez / bin / sh et réessayez.
la source
Et j'ai trouvé ça
la source
Veuillez utiliser la commande ci-dessous:
la source
echo $SHELL
fait ce que vous essayez de faire et le fait bien. Le second n'est pas bon non plus, car$SHELL
la variable d'environnement contient un shell par défaut pour un utilisateur actuel, pas un shell en cours d'exécution. Si j'ai par exemplebash
défini comme shell par défaut, exécutezzsh
etecho $SHELL
, il s'imprimerabash
.echo $SHELL
peut être des ordures:~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$
Celui-ci fonctionne bien sur Red Hat Linux (RHEL), macOS, BSD et certains AIX :
alternativement, le suivant devrait également fonctionner si pstree est disponible,
la source