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

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

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

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

Ответы [ 23 ]

4 голосов
/ 25 августа 2015

Мой вариант печати родительского процесса.

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

Зачем запускать ненужные приложения, когда awk может сделать это за вас?

3 голосов
/ 20 марта 2013

При условии, что ваш /bin/sh поддерживает стандарт POSIX и в вашей системе установлена ​​команда lsof - возможной альтернативой lsof может быть в этом случае <a href="http://glowworm.us/pid2path.html" rel="nofollow">pid2path</a> - вы также можете использовать (или адаптировать) следующеескрипт, который печатает полные пути:

#!/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}'
2 голосов
/ 25 июля 2010
echo $$ # Gives the Parent Process ID 
ps -ef | grep $$ | awk '{print $8}' #use the PID to see what the process is.

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

2 голосов
/ 13 сентября 2014

Ни один из ответов не работал с оболочкой fish (в ней нет переменных $$ или $0).

Это работает для меня (проверено на sh, bash, fish, ksh, csh, true, tcsh и zsh; openSUSE 13.2):

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

Эта команда выводит строку наподобие bash.Я использую здесь только ps, tail и sed (без расширений GNU; попробуйте добавить --posix, чтобы проверить это).Все они являются стандартными командами POSIX.Я уверен, что tail можно удалить, но мой sed fu недостаточно силен для этого.

Мне кажется, что это решение не очень переносимо, так как оно не работает наOS X.: (

1 голос
/ 14 декабря 2017

Чтобы узнать, использует ли ваша Shell DASH / BASH, выполните следующие действия.

1) ls –la / bin / sh , если результат равен / bin /sh -> / bin / bash ==> Тогда ваша оболочка использует BASH.

, если результат / bin / sh -> / bin / dash ==> Тогдаваша оболочка использует DASH.

Если вы хотите перейти с BASH на DASH или наоборот, используйте следующий код ln -s / bin / bash / bin / sh (изменить оболочкув BASH)

ПРИМЕЧАНИЕ. Если приведенная выше команда выдает сообщение об ошибке: / bin / sh уже существует, удалите / bin / sh и попробуйте снова.

1 голос
/ 19 сентября 2017

Есть много способов узнать оболочку и соответствующую ей версию. Вот несколько, которые работали для меня.

Прямо вперед

  1. $> echo $ 0 (Дает вам имя программы. В моем случае вывод был -bash )
  2. $> $ SHELL (Это приведет вас в оболочку, и в командной строке вы получите имя и версию оболочки. В моем случае bash3.2 $ )
  3. $> echo $ SHELL (Это даст вам исполняемый путь. В моем случае / bin / bash )
  4. $> $ SHELL --version (Это даст полную информацию о программном обеспечении оболочки с типом лицензии)

Хакерский подход

$> ******* (Введите набор случайных символов и в выходных данных вы получите имя оболочки. В моем случае -bash: chapter2-a-sample-isomorphic-app: command не найдено )

1 голос
/ 18 мая 2017

Мое решение:

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

Это должно переноситься на разные платформы и оболочки. Он использует ps, как и другие решения, но он не полагается на sed или awk и отфильтровывает нежелательные сообщения из трубопровода и сам ps, так что оболочка всегда должна быть последней записью. Таким образом, нам не нужно полагаться на непереносимые переменные PID или выбирать правильные строки и столбцы.

Я тестировал на Debian и MacOS с bash, zsh и fish (что не работает с большинством этих решений без изменения выражения специально для fish, потому что он использует другую переменную PID).

1 голос
/ 09 июля 2015

Это не очень чистое решение, но оно делает то, что вы хотите.

Я понимаю, что ответ немного запоздал в этом старом добром 2015 году, но ...

#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

Теперь вы можете использовать $(getshell) --version.

Это работает, однако, только на ksh-подобных оболочках.

1 голос
/ 30 октября 2014

Пропуск PID из вывода «ps» не требуется, потому что вы можете прочитать соответствующую командную строку для любого PID из структуры каталогов / proc:

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

Однако это может быть не лучше, чем просто:

echo $0

По поводу запуска оболочки, отличной от указанной в названии, одна идея состоит в том, чтобы запросить версию из оболочки, используя имя, которое вы получили ранее:

<some_shell> --version

sh, похоже, завершается с ошибкой при выходекод 2, в то время как другие дают что-то полезное (но я не могу проверить все, поскольку у меня их нет):

$ sh --version
sh: 0: Illegal option --
echo $?
2
1 голос
/ 11 августа 2014

Если вы просто хотите проверить, что вы используете (определенную версию) Bash, лучший способ сделать это - использовать переменную массива $BASH_VERSINFO. Как переменная массива (только для чтения) она не может быть установлена ​​в среде, так что вы можете быть уверены, что он идет (если вообще) из текущей оболочки. Однако, поскольку Bash имеет другое поведение при вызове как sh, вам также нужно проверить, что переменная окружения $BASH оканчивается на /bash.

В написанном мной сценарии, использующем имена функций с - (не подчеркивание) и зависит от ассоциативных массивов (добавлено в Bash 4), У меня есть следующая проверка работоспособности (с полезным сообщением об ошибке пользователя):

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

Вы могли бы опустить несколько параноидальную функциональную проверку для функций в первом случае, и просто предположим, что будущие версии bash будут совместимы.

...