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





Ответы - Как определить текущую оболочку, над которой я работаю / How to determine the current shell I'm working on

25.07.2010 01:37:34
Существует три подхода к поиску имени исполняемого файла текущей оболочки:
Обратите внимание , что все три подхода можно обмануть , если исполняемый файл оболочки
/bin/sh
, но на самом деле это переименованныйbash
, например (что часто случается).Таким образом, на ваш второй вопрос о том, будет ли
ps
-выведет имя программы... что в случае с оболочкой и есть настоящая оболочка.echo $0
- это будет выглядеть для текущего идентификатора процесса в списке запущенных процессов. Поскольку текущий процесс является оболочкой, он будет включен.Это не 100% Надежный, как вы могли бы других , чьи процессы
ps -ef | grep $$ | grep -v grep
список включает в себя такое же количество, как оболочки идентификатор процесса, особенно если это небольшое количество (например, если оболочки ПИД "5", можно обнаружить процессов под названием "с java5" или "perl5" в тот жеps
выход!). Это вторая проблема с подходом "ps", Помимо невозможности полагаться на имя оболочки.grep
-путь к текущей оболочке сохраняется как переменнаяecho $SHELL
для любой оболочки. Предостережение для этого состоит в том, что если вы запускаете оболочку явно как подпроцесс (например, это не ваша оболочка входа), вы получите значение вашей оболочки входа. Если это возможно, используйтеSHELL
илиps
.Если, однако, исполняемый файл не соответствует вашей фактической оболочке (например
$0
на самом деле bash или ksh), вам нужна эвристика. Вот некоторые переменные среды, характерные для различных оболочек::/bin/sh
находится в tcsh$version
на баш$BASH
(нижний регистр) имеет значение фактического имени оболочки в csh или tcsh$shell
устанавливается на zshksh имеет
$ZSH_NAME
и$PPID
, в то время как обычный Bourne shell ($PS3
) имеет толькоsh
и$PS1
. Это обычно кажется самым трудным для различения - единственное различие во всем наборе переменных окружения между$PS3
иsh
, которые мы установили на Solaris boxen, - этоksh
,$ERRNO
,$FCEDIT
,$LINENO
,$PPID
,$PPID
,$PS4
,$RANDOM
и$SECONDS
.



echo ${.sh.version}
возвращает "плохую замену". Смотрите мое решение выше

sh
и ksh
-это $ERRNO
, $FCEDIT
, $LINENO
, $PPID
, $PS3
, $PS4
, $RANDOM
, $SECONDS
, $TMOUT
.



$ ps | grep sh
25736 pts/1 00:00:00 sh
25740 pts/1 00:00:00 bash
... где /bin/bash
-исполняемый файл, а /bin/sh
указывает на dash


echo $0
выводит имя скрипта,а не имя оболочки.

ps -ef | grep …
... это не 100% Надежный, как ...” с помощью простого регулярного выражения через egrep
или grep -e
можно легко довести надежность До для всех намерений и целей 100%: ps -ef | egrep "^\s*\d+\s+$$\s+"
. ^
Гарантирует, что мы начинаем с начала строки, \d+
съедает UID, $$
соответствует PID, а \s*
и \s+
учитывают & обеспечивают пробелы между другими частями.


ps -ef | awk '$2==pid' pid=$$

pgrep
лучше подходит для грэппинга через процессы

25.07.2010 01:38:44
Вы можете попробовать:
ps | grep `echo $$` | awk '{ print $4 }'
Или:
echo $SHELL

/pattern/ { action }
будет делать?


$SHELL
, чем греппинг $$ из-за ложных срабатываний.



25.07.2010 01:39:39
ПС-самый надежный метод. Переменная окружения оболочки не гарантируется, и даже если это так, ее можно легко подделать.


25.07.2010 01:41:25
echo $$ # Gives the Parent Process ID
ps -ef | grep $$ | awk '{print $8}' # Use the PID to see what the process is.


grep $$
ненадежно. ps -ef | awk -v pid=$$ '$2==pid { print $8 }'
лучше, но почему бы просто не использовать ps -p $$
?

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

ps
, которая может не понимать -p
, поэтому вам может потребоваться использовать /bin/ps -p $$
.

$$
, за исключением fish
, с которой вам придется использовать ps -p %self
.

/bin/ps
. ps
может легко (на самом деле это вполне нормально в наши дни) быть установлен в /usr/bin
. $(which ps) -p $$
- это лучший способ. Конечно, это не сработает у рыб, а возможно и у некоторых других раковин. Я думаю, что это (which ps) -p %self
в рыбе.

readlink /proc/$$/exe

sh
эмулируется bash
, ps-p дает вам /usr/bin/bash
, даже если вы запускаете его как sh



mutt
... :- b


ps -o fname --no-headers $$
.

test `ps -p $$ -ocomm=` == "bash" && do_something_that_only_works_in_bash
. (Следующая строка в моем сценарии имеет эквивалент csh.)

-q
вместо -p
: SHELL=$(ps -ocomm= -q $$)

15.10.2012 03:45:43
$SHELL
не обязательно всегда показывать текущую оболочку. Он отражает только оболочку по умолчанию, которая будет вызвана.
Чтобы проверить вышесказанное, скажемbash
является оболочкой по умолчанию, попробуйте echo $SHELL
, а затем в том же терминале войдите в другую оболочку ( например, KornShell (ksh)) и попробуйте $SHELL
. Вы увидите результат как баш в обоих случаях.
Чтобы получить имя текущей оболочки, используйте cat /proc/$$/cmdline
. И путь к исполняемому файлу оболочки с помощью readlink /proc/$$/exe
.

/proc
.

20.03.2013 09:30:04
При условии, что ваш /bin/sh
поддерживает стандарт POSIX и в вашей системе установлена lsof
lsof-возможной альтернативой lsof
в этом случае может быть pid2path
- вы также можете использовать (или адаптировать) следующий скрипт, который печатает полные пути:
#!/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}'

-i
(- >игнорировать окружение) опции > env
в строке, где вы проверяете наличие lsof
. это не удается с: env -i PATH="${PATH}" type lsof
- > > env: ‘type’: No such file or directory

31.03.2013 08:54:15
Если вы просто хотите убедиться, что пользователь вызывает скрипт с помощью Bash:
if [ ! -n "$BASH" ] ;then echo Please run this script $0 with bash; exit 1; fi





#!/bin/bash
: if [ ! -n "$BASH" ] ;then exec bash $0; fi
. С этой строкой скрипт запускается с использованием bash, даже если он запущен с использованием ksh или sh. Мой вариант использования не требует аргументов командной строки, но при необходимости их можно добавить после $0
.

22.10.2013 02:26:08
Пожалуйста, используйте следующую команду:
ps -p $$ | tail -1 | awk '{print $4}'

zsh
делает то, что вы пытаетесь сделать, и делает это хорошо. Второй вариант также не подходит, поскольку $SHELL
установлен в качестве оболочки по умолчанию, выполните bash
и zsh
, он напечатает echo $SHELL
.


echo $SHELL
может быть дрянь: ~ $ echo $SHELL /bin/zsh ~ $ bash bash-4.3$ echo $SHELL /bin/zsh bash-4.3$

17.06.2014 02:44:25
Ниже всегда приводится фактическая используемая оболочка-она получает имя фактического исполняемого файла, а не имя оболочки (напримерksh93
вместо ksh
и т. д.). Для /bin/sh
он покажет фактическую используемую оболочку, т. е. dash
.
ls -l /proc/$$/exe | sed 's%.*/%%'
Я знаю, что многие говорятls

/proc
. Не весь мир-это линукс-бокс.

basename $(readlink /proc/$$/exe)
ls
+ sed
+ echo
.

ash -> /bin/busybox
, это даст как /bin/busybox версии.

11.08.2014 09:38:09
Если вы просто хотите проверить, что вы используете (определенную версию) Bash, лучший способ сделать это-использовать $BASH_VERSINFO
, вам также нужно проверитьsh
.
В скрипте, который я написал, использует имена функций с $BASH
(не подчеркивание) и зависит от ассоциативных массивов (добавлено в Bash 4), у меня есть следующая проверка здравомыслия (с полезным сообщением об ошибке пользователя):
/bash
Вы можете опустить несколько параноидальную функциональную проверку функций в первом случае и просто предположить, что будущие версии Bash будут совместимы.

13.09.2014 01:07:50
Ни один из ответов не работал с bash
или $$
).
Это работает для меня (проверено на $0
, sh
, bash
, fish
, ksh
, csh
, true
и tcsh
; openSUSE 13.2):
zsh
Эта команда выводит строку типа ps | tail -n 4 | sed -E '2,$d;s/.* (.*)/\1/'
. Здесь я использую только bash
, ps
и tail
(без расширений GNU; попробуйте добавить sed
, чтобы проверить это). Все они являются стандартными командами POSIX. Я уверен--posix
можно удалить, но мой tail
фу недостаточно силен, чтобы сделать это.
Мне кажется, что это решение не очень портативно, так как оно не работает на OS X. :(

sed: invalid option -- 'E'
на bash 3.2.51 и tcsh 6.15.00

14.10.2014 03:57:50
Я перепробовал много разных подходов, и самый лучший для меня-это:
ps -p $$
Он также работает под Cygwin и не может давать ложных срабатываний, как PID grepping. С некоторой очисткой он выводит только имя исполняемого файла (под Cygwin с path):
ps -p $$ | tail -1 | awk '{print $NF}'
Вы можете создать функцию, так что вам не придется запоминать ее:
# Print currently active shell
shell () {
ps -p $$ | tail -1 | awk '{print $NF}'
}
...а потом просто выполнить shell
.
Он был протестирован под Debian и Cygwin.


ps
, tail
и gawk
, cmd не определяет $$
, поскольку это PID, поэтому он определенно не может работать под обычным cmd.

ps -p$$ -o comm=
? POSIX говорит, что указание всех заголовков пустыми полностью подавляет заголовок. Мы все еще терпим неудачу (как и все ответы ps
), когда мы исходим из непосредственно выполняемого сценария (например#!/bin/sh
).

30.10.2014 09:16:40
Греппинг PID из выходных данных " ps " не требуется, так как вы можете прочитать соответствующую командную строку для любого PID из структуры каталогов /proc:
echo $(cat /proc/$$/cmdline)
Тем не менее, это может быть не лучше, чем просто:
echo $0
Что касается запуска фактически другой оболочки, чем указано в названии, одна идея заключается в том, чтобы запросить версию из оболочки, используя имя, которое вы получили ранее:
<some_shell> --version
sh
, кажется, терпит неудачу с кодом выхода 2, в то время как другие дают что-то полезное (но я не могу проверить все, так как у меня их нет):
$ sh --version
sh: 0: Illegal option --
echo $?
2

09.07.2015 09:42:56
Это не очень чистое решение, но оно делает то, что вы хотите.
# 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=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
.
Это работает, однако, только на kornshell-подобных оболочках (ksh).


dash
, yash
и т. д. Обычно, если вы используете bash
, zsh
, ksh
, что угодно-вы не должны беспокоиться о таких вещах.


ksh
(хотя я не проверял это тщательно).

25.08.2015 04:37:28
Мой вариант печати родительского процесса:
ps -p $$ | awk '$1 == PP {print $4}' PP=$$
Не запускайте ненужные приложения, когда AWK может сделать это за вас.

09.12.2015 06:34:54
У меня есть простой трюк, чтобы найти текущую оболочку. Просто введите случайную строку (которая не является командой). Он завершится неудачей и вернет ошибку" не найдено", но в начале строки он скажет, какая это оболочка:
ksh: aaaaa: not found [No such file or directory]
bash: aaaaa: command not found

echo 'aaaa' > script; chmod +x script; ./script
дает./script.sh: 1: aaaa: not found

18.05.2017 02:13:09
Мое решение:
ps -o command | grep -v -e "\<ps\>" -e grep -e tail | tail -1
Это должно быть переносимо на различные платформы и оболочки. Он использует ps
, как и другие решения, но он не полагается на sed
или awk
и отфильтровывает мусор из трубопроводов и ps
) и fish (который не работает с большинством этих решений без изменения выражения специально для fish, потому что он использует другую переменную PID).

19.09.2017 10:30:27
Существует много способов узнать оболочку и ее соответствующую версию. Вот несколько из них, которые работали на меня.
Простой
- $ > > echo $0 (дает вам имя программы. В моем случае выход был-Баш .)
- $> > $SHELL (это приведет вас в оболочку и в приглашении вы получите имя оболочки и версию. В моем случае баш3, 2$ .)
- $ > > echo $SHELL (Это даст вам исполняемый путь. В моем случае / bin / bash .)
- $> > $SHELL -- version (это даст полную информацию о программном обеспечении shell с типом лицензии)
Хакерский подход
$> ******* (Введите набор случайных символов,и на выходе вы получите имя оболочки. В моем случае-bash: chapter2-a-sample-isomorphic-app: команда не найдена)

11.12.2017 07:38:00
Этот хорошо работает на Red Hat Linux (RHEL), macOS, BSD и некоторых AIXes:
ps -T $$ | awk 'NR==2{print $NF}'
в качестве альтернативы, следующий должен также работать, если pstree доступен,
pstree | egrep $$ | awk 'NR==2{print $NF}'

14.12.2017 11:12:15
Выполните следующие действия, чтобы узнать, использует ли ваша оболочка Dash/Bash.
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 и повторите попытку.

