Как определить текущую оболочку, над которой я работаю? - PullRequest
562 голосов
/ 25 июля 2010

Как определить текущую оболочку, над которой я работаю?

Достаточно ли будет вывода только команды ps?

Как это можно сделать в разных вариантах UNIX?

Ответы [ 23 ]

712 голосов
/ 25 июля 2010
  • Существует 3 подхода к нахождению имени исполняемого файла текущей оболочки:

    Обратите внимание, что все 3 подхода могут быть обмануты, если исполняемый файл оболочкинапример, /bin/sh, но это действительно переименованное bash (что часто случается).

    Таким образом, на ваш второй вопрос о том, подойдет ли вывод ps, дан ответ " не всегда ".

    1. echo $0 - напечатает имя программы ... которое в случае оболочки является фактической оболочкой

    2. ps -ef | grep $$ | grep -v grep - это будет искать текущий идентификатор процесса в спискезапущенные процессы.Поскольку текущий процесс является оболочкой, он будет включен.

      Это не на 100% надежно, поскольку у вас могут быть ДРУГИЕ процессы, чей список ps включает в себя то же число, что и идентификатор процесса оболочки, особенно если этот идентификатор мал # (например, если PID оболочки равен "5", вы можете найти процессы с именем "java5" или "perl5" в одном и том же выводе grep!). Это вторая проблема с подходом "ps", из-за невозможности полагаться на имя оболочки.

    3. echo $SHELL - Путь ктекущая оболочка хранится как переменная SHELL для любой оболочки.Предостережение для этого заключается в том, что если вы явно запустите оболочку как подпроцесс (например, это не ваша оболочка входа в систему), вы получите вместо этого значение вашей оболочки входа в систему.Если это возможно, используйте подход ps или $0.


  • Если, однако, исполняемый файл не соответствует вашей фактической оболочке(например, /bin/sh на самом деле bash или ksh), вам нужна эвристика.Вот некоторые переменные среды, специфичные для различных оболочек:

    • $version установлен на tcsh

    • $BASH установлен на bash

    • $shell (в нижнем регистре) устанавливается фактическое имя оболочки в csh или tcsh

    • $ZSH_NAME устанавливается в zsh

    • ksh имеет $PS3 и $PS4, в то время как обычная оболочка Bourne (sh) имеет только $PS1 и $PS2.Это, как правило, кажется самым трудным для различения - ЕДИНСТВЕННАЯ разница во всем наборе переменных окружения между sh и ksh, которые мы установили на Solaris boxen, составляет $ERRNO, $FCEDIT, $LINENO, $PPID, $PS3, $PS4, $RANDOM, $SECONDS, $TMOUT.

86 голосов
/ 25 июля 2010

ps -p $$

должен работать везде, где работают решения, включающие ps -ef и grep (в любом варианте Unix, который поддерживает опции POSIX для ps), и не будет страдать от ложных срабатываний, вызванных grepping для последовательность цифр, которая может появиться в другом месте.

36 голосов
/ 19 июня 2012

Попробуйте

ps -p $$ -oargs=

или

ps -p $$ -ocomm=
24 голосов
/ 31 марта 2013

Если вы просто хотите убедиться, что пользователь вызывает скрипт с bash:

if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi
19 голосов
/ 25 июля 2010

Вы можете попробовать:

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

Или:

echo $SHELL
11 голосов
/ 15 октября 2012

$SHELL не всегда нужно показывать текущую оболочку. Он отражает только оболочку по умолчанию, которая будет вызвана.

Чтобы проверить выше, Say bash является оболочкой по умолчанию, попробуйте echo $SHELL, затем в том же терминале перейдите в другую оболочку (например, ksh) и попробуйте $SHELL, вы увидите результат bash в обоих случаях.

Чтобы получить имя текущей оболочки, используйте cat /proc/$$/cmdline И путь к исполняемому файлу оболочки readlink /proc/$$/exe

9 голосов
/ 25 июля 2010

пс - самый надежный метод.Конвертер SHELL не гарантируется, и даже если он установлен, его можно легко подделать

8 голосов
/ 09 декабря 2015

У меня есть простой трюк, чтобы найти текущую оболочку. Просто введите случайную строку (которая не является командой). Он потерпит неудачу и вернет ошибку «not found», но в начале строки скажет, какая это оболочка:

ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found
7 голосов
/ 17 июня 2014

Это всегда даст фактическую используемую оболочку - получает имя фактического исполняемого файла, а не имя оболочки (т.е. ksh93 вместо ksh и т. Д.). Для /bin/sh будет отображаться фактическая используемая оболочка: т.е. dash

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

Я знаю, что многие говорят, что ls вывод должен обрабатываться по-новому, но какова вероятность того, что у вас будет оболочка, которую вы используете по имени со специальными символами или поместите в каталог с именемсо спецсимволами?Если это все еще так, вот множество других примеров, делающих это по-другому.

4 голосов
/ 14 октября 2014

Я испробовал много разных подходов, и лучший для меня:

ps -p $$

Он также работает под Cygwin и не может выдавать ложные срабатывания в качестве PIDоглавлению.С некоторой очисткой он выводит только имя исполняемого файла (в Cygwin с путем):

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

Вы можете создать функцию, чтобы вам не пришлось ее запоминать:

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

... и затем просто выполните shell.

Протестировано в Debian и Cygwin.

...