Hoe kan ik de huidige shell bepalen waaraan ik werk?
Zou de uitvoer van de opdracht ps
alleen 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/sh
is, maar het in werkelijkheid bijvoorbeeld een hernoemdebash
is (wat vaak gebeurt).Dus uw tweede vraag of de uitvoer van
ps
voldoende is, wordt beantwoord met “niet altijd“.-
echo $0
– drukt de programmanaam af… die in het geval van de shell de eigenlijke shell is. -
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 dezelfdegrep
-uitvoer!). Dit is het tweede probleem met de “ps”-benadering, naast het niet kunnen vertrouwen op de shell-naam. -
echo $SHELL
– Het pad naar de huidige shell wordt opgeslagen als deSHELL
variabele 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 deps
of$0
benadering.
-
-
Als het uitvoerbare bestand echter niet overeenkomt met uw werkelijke shell (bijv.
/bin/sh
is eigenlijk bash of ksh), hebt u heuristieken nodig. Hier zijn enkele omgevingsvariabelen die specifiek zijn voor verschillende schelpen:-
$version
is ingesteld op tcsh -
$BASH
is ingesteld op bash -
$SHELL
(kleine letters) is ingesteld op de werkelijke shellnaam in csh of tcsh -
$ZSH_NAME
is ingesteld op zsh -
ksh heeft
$PS3
en$PS4
ingesteld, terwijl de normale Bourne-shell (sh
) alleen$PS1
en$PS2
ingesteld. Dit lijkt over het algemeen het moeilijkst te onderscheiden – het enigeverschil in de hele set omgevingsvariabelen tussensh
enksh
die we op Solaris boxen hebben geïnstalleerd is$ERRNO
,$FCEDIT
,$LINENO
,$PPID
,$PS3
,$PS4
,$RANDOM
,$SECONDS
en$TMOUT
.
-
Antwoord 2, autoriteit 13%
ps -p $$
zou overal moeten werken waar de oplossingen met ps -ef
en grep
doen (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 $SHELL
var, 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 args
of -o comm
zoals gesuggereerd in een ander antwoord (deze kunnen bijvoorbeeld een symbolische link gebruiken, zoals wanneer /bin/sh
verwijst 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/bash
en/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}'