Hoe de huidige shell te bepalen waaraan ik werk

Hoe kan ik de huidige shell bepalen waaraan ik werk?

Zou de uitvoer van de opdracht psalleen voldoende zijn?

Hoe kan dit in verschillende smaken van Unix?


Antwoord 1, autoriteit 100%

  • Er zijn drie manieren om de naamvan het huidige uitvoerbare bestand van de shell te vinden:

    Houd er rekening mee dat alle drie de benaderingen voor de gek kunnen worden gehouden als het uitvoerbare bestand van de shell /bin/shis, maar het in werkelijkheid bijvoorbeeld een hernoemde bashis (wat vaak gebeurt).

    Dus uw tweede vraag of de uitvoer van psvoldoende is, wordt beantwoord met “niet altijd“.

    1. echo $0– drukt de programmanaam af… die in het geval van de shell de eigenlijke shell is.

    2. ps -ef | grep $$ | grep -v grep– dit zoekt naar de huidige proces-ID in de lijst met lopende processen. Aangezien het huidige proces de shell is, zal het worden opgenomen.

      Dit is niet 100% betrouwbaar, omdat je misschien andereprocessen hebt waarvan de ps-lijst hetzelfde nummer bevat als de proces-ID van shell, vooral als die ID een klein aantal is (als de PID van de shell bijvoorbeeld “5” is, vindt u mogelijk processen met de naam “java5” of “perl5” in dezelfde grep-uitvoer!). Dit is het tweede probleem met de “ps”-benadering, naast het niet kunnen vertrouwen op de shell-naam.

    3. echo $SHELL– Het pad naar de huidige shell wordt opgeslagen als de SHELLvariabele voor elke shell. Het voorbehoud hierbij is dat als je een shell expliciet start als een subproces (het is bijvoorbeeld niet je login-shell), je in plaats daarvan de waarde van je login-shell krijgt. Als dat een mogelijkheid is, gebruik dan de psof $0benadering.


  • Als het uitvoerbare bestand echter niet overeenkomt met uw werkelijke shell (bijv. /bin/shis eigenlijk bash of ksh), hebt u heuristieken nodig. Hier zijn enkele omgevingsvariabelen die specifiek zijn voor verschillende schelpen:

    • $versionis ingesteld op tcsh

    • $BASHis ingesteld op bash

    • $SHELL(kleine letters) is ingesteld op de werkelijke shellnaam in csh of tcsh

    • $ZSH_NAMEis ingesteld op zsh

    • ksh heeft $PS3en $PS4ingesteld, terwijl de normale Bourne-shell (sh) alleen $PS1en $PS2ingesteld. Dit lijkt over het algemeen het moeilijkst te onderscheiden – het enigeverschil in de hele set omgevingsvariabelen tussen shen kshdie we op Solaris boxen hebben geïnstalleerd is $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDSen $TMOUT.


Antwoord 2, autoriteit 13%

ps -p $$

zou overal moeten werken waar de oplossingen met ps -efen grepdoen (op elke Unix-variant die POSIX-opties voor ps) en zullen geen last hebben van de valse positieven die worden geïntroduceerd door te grijpen naar een reeks cijfers die elders kan verschijnen.


Antwoord 3, autoriteit 6%

Probeer

ps -p $$ -oargs=

of

ps -p $$ -ocomm=

Antwoord 4, autoriteit 4%

Als je er zeker van wilt zijn dat de gebruiker een script aanroept met Bash:

if [ -z "$BASH" ] ;then echo "Please run this script $0 with bash"; exit 1; fi

Antwoord 5, autoriteit 3%

Je kunt het proberen:

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

Of:

echo $SHELL

6

PS is de meest betrouwbare methode. De schelpomgeving variabele is niet gegarandeerd ingesteld en zelfs als het is, kan het gemakkelijk worden vervalst.


Antwoord 7

Waarom haal je het niet met de $SHELLvar, een simpele sed zou het pad kunnen verwijderen:

$ echo $SHELL | sed -E 's/^.*\/([aA-zZ]+$)/\1/g'
bash

Getest op MacOS, Ubuntu, CentOS


Antwoord 8

Een manier is:

ps -p $$ -o exe=

wat IMO beter is dan het gebruik van -o argsof -o commzoals gesuggereerd in een ander antwoord (deze kunnen bijvoorbeeld een symbolische link gebruiken, zoals wanneer /bin/shverwijst naar een specifieke shell als streepje of bash).

Het bovenstaande retourneert het pad van het uitvoerbare bestand, maar pas op dat als gevolg van /usr-merge, men mogelijk moet controleren op meerdere paden (bijv. /bin/bashen/usr/bin/bash)

Houd er rekening mee dat het bovenstaande niet volledig POSIX-compatibel is (POSIX ps heeft geen exe).


Antwoord 9

Gelieve het onderstaande commando te gebruiken:

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

Antwoord 10

En ik heb dit bedacht

sed 's/.*SHELL=//; s/[[:upper:]].*//' /proc/$$/environ

Antwoord 11

U kunt echo $SHELL|sed "s/\/bin\///g"

gebruiken


Antwoord 12

Deze werkt goed op Red Hat Linux(RHEL), macOS, BSD en sommige AIX-en:

ps -T $$ | awk 'NR==2{print $NF}' 

als alternatief zou de volgende ook moeten werken als pstreebeschikbaar is,

pstree | egrep $$ | awk 'NR==2{print $NF}'

Other episodes