определите оболочку в сценарии во время времени выполнения

Согласно моему знанию, для определения текущей оболочки мы используем echo $0 в оболочке. Скорее я хочу, чтобы мой сценарий зарегистрировался, какую оболочку он выполняет. Так, я пытался распечатать $0 в сценарии и это возвращает название сценария, как это должно. Так, мой вопрос состоит в том, как я могу найти, в какой оболочке мой сценарий работает во время времени выполнения?

23
03.01.2020, 17:13
7 ответов

На Linux можно использовать /proc/PID/exe.

Пример:

# readlink /proc/$$/exe
/bin/zsh
28
27.01.2020, 19:41
  • 1
    Это немного слишком специфично для меня (например, на Debian это печатает zsh4 или ksh93). /bin/sed -r -e 's/\x0.*//' /proc/$$/cmdline дает zsh или ksh вместо этого. (Это составило бы 0$, если бы оболочки волшебно не зафиксировали это для предоставления названия сценариев вместо этого). –  frostschutz 13.04.2013, 02:17
  • 2
    @frostschutz Ваш - лучший ответ, выполненный для +500! –  Teresa e Junior 14.04.2013, 19:05
  • 3
    Это переносит от страшного Все в мире болезнь поля Linux. /proc является столь ужасным и непортативным, как это добирается. –  Jens 15.04.2013, 15:58
  • 4
    @Jens вот почему, я указал это, относится к Linux только. /proc не 'ужасно'. /proc часто очень изящное решение. Непортативный да, но потому что что-то непортативно, не делает это ужасным. –  Patrick 16.04.2013, 15:17
  • 5
    @Patrick я рассматриваю /proc ужасный, потому что файлы в нем могут прийти и уйти в прихоти разработчиков и содержании файлов, является склонным для изменения без уведомления, причиняя бесконечную боль из-за bitrot и перемещая форматы конечного файла. –  Jens 18.04.2013, 14:12

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

  1. Оболочка Thompson (osh),
  2. Оболочка Bourne,
  3. Оболочка границы снова (bash),
  4. Оболочка Korn (ksh88, ksh93, pdksh, mksh),
  5. zsh,
  6. Совместимая политикой Обычная оболочка (posh),
  7. Еще одна оболочка (yash),
  8. rc оболочка,
  9. akanga оболочка,
  10. оболочка es,
  11. wish Интерпретатор TCL,
  12. tclsh Интерпретатор TCL,
  13. expect Интерпретатор TCL,
  14. Perl,
  15. Python,
  16. Ruby,
  17. PHP,
  18. JavaScript (nodejs, оболочка SpiderMonkey и JSPL, по крайней мере)
  19. MS/Вино cmd.exe, command.com (MS-DOS, FreeDOS...).
    'echo' +"'[{<?php echo chr(13)?>php <?php echo PHP_VERSION.chr(10);exit;?>}\
    @GOTO DOS [exit[set 1 [[set 2 package] names];set 3 Tcl\ [info patchlevel];\
    if {[lsearch -exact $1 Expect]>=0} {puts expect\ [$2 require Expect]\ ($3)} \
    elseif {[lsearch -exact $1 Tk]>=0} {puts wish\ ($3,\ Tk\ [$2 require Tk])} \
    else {puts $3}]]]' >/dev/null ' {\">/dev/null \
    ">"/dev/null" +"\'";q="#{",1//2,"}";a=+1;q='''=.q,';q=%{\"
    'echo' /*>/dev/null
    echo ">/dev/null;status=0;@ {status=1};*=(" '$' ");~ $status 1&&{e='"\
    "';eval catch $2 ^'&version {eval ''echo <='^ $2 ^'&version''}';exit};e='"\
    "';if (eval '{let ''a^~a''} >[2] /dev/null'){e='"\
    "';exec echo akanga};eval exec echo rc $2 ^ version;\" > /dev/null
    : #;echo possibly pre-Bourne UNIX V1-6 shell;exit
    if (! $?version) set version=csh;exec echo $version
    :DOS
    @CLS
    @IF NOT "%DOSEMU_VERSION%"=="" ECHO DOSEMU %DOSEMU_VERSION%
    @ECHO %OS% %COMSPEC%
    @VER
    @GOTO FIN
    ", unless eval 'printf "perl %vd\n",$^V;exit;'> "/dev/null";eval ': "\'';
    =S"';f=false e=exec\ echo n=/dev/null v=SH_VERSION;`(eval "f() { echo :
    };f")2>$n` $f||$e Bourne-like shell without function
    case `(: ${_z_?1}) 2>&1` in 1) $e ash/BSD sh;;esac;t(){
    eval "\${$1$v+:} $f &&exec echo ${2}sh \$$1$v";};t BA ba;t Z z;t PO po;t YA ya
    case `(typeset -Z2 b=0;$e $b)2>$n` in 00) (eval ':${.}')2>$n&&eval '
    $e ksh93 ${.sh.version}';t K pdk;$e ksh88;;esac;case `(eval '$e ${f#*s}$($e 1
    )$((1+1))')2>$n` in e12)$e POSIX shell;;esac;$e Bourne-like shell;: }
    print "ruby ",RUBY_VERSION,"\n";exit;' ''';import sys
    print("python "+sys.version);z='''*/;
    s="";j="JavaScript";if(typeof process=="object"){p=console.log;p(process.title
    ,process.version)}else{p=print;p((f="function")==(t=typeof version)?"string"==
    typeof(v=version())?v:(typeof build!=f?"":s= "SpiderMonkey ")+j+" "+v:(t==
    "undefined"?j+"?":version)+"\n");if(s)build()}/*
    :FIN } *///'''

Я отправил начальную версию того which_interpreter сценария приблизительно 2004 в Usenet. Sven Mascheck имеет (вероятно, более полезный для Вас) сценарий, названный whatshell, который фокусируется на идентификации подобных Границе оболочек. Можно также найти объединенную версию наших двух сценариев там.

48
27.01.2020, 19:41
  • 1
    Это не может определить Python 3, только Python 2. Зафиксировать это, изменение print быть функцией. –  Chris Down 04.04.2013, 12:19
  • 2
    Это - самый большой момент WTF года до сих пор. +1 для взятия мобильности прошлая исправность. –  l0b0 04.04.2013, 14:35
  • 3
    Было бы хорошо, если это распознает оболочку рыбы. –  Konrad Borowski 23.03.2014, 18:39
  • 4
    @xfix, я не забываю пробовать даже прежде, чем добавить php и JavaScript, но не мог найти решение затем. Сложность растет экспоненциально с количеством языков для поддержки (как все, что Вы добавляете, должно быть допустимым (или по крайней мере иметь незначимые побочные эффекты) на всех поддерживаемых языках), таким образом, это было бы еще более трудно теперь. Я не говорю, что это невозможно, но это, вероятно, означало бы отбрасывать поддержку некоторых других языков. –  Stéphane Chazelas 23.03.2014, 22:45
  • 5
    @iconoclast, таким образом, это правильно определяет bash 3.2.53(1)-release как интерпретатор, интерпретирующий его. –  Stéphane Chazelas 10.08.2015, 11:53

Вы могли попробовать

ps -o args= -p "$$"

который даст Вам название команды, связанной с pid сценария.

6
27.01.2020, 19:41
  • 1
    Не работает при использовании хижины насколько я могу сказать. Sprunge.us/QeHD –  Chris Down 04.04.2013, 12:20
  • 2
    Извините, @ChrisDown, Flup. Мое плохое, я неправильно перевел cmd кому: comm когда POSIXifying ответ. –  Stéphane Chazelas 04.04.2013, 14:04

Это - то, что я использую в своем .profile для проверки на различные оболочки в системах, я продолжаю работать. Это не делает тонкие различия между ksh88 и ksh93, но это никогда не приводило меня к сбою.

Обратите внимание, что это не требует единственного ветвления или канала.

# Determine what (Bourne compatible) shell we are running under. Put the result
# in $PROFILE_SHELL (not $SHELL) so further code can depend on the shell type.

if test -n "$ZSH_VERSION"; then
  PROFILE_SHELL=zsh
elif test -n "$BASH_VERSION"; then
  PROFILE_SHELL=bash
elif test -n "$KSH_VERSION"; then
  PROFILE_SHELL=ksh
elif test -n "$FCEDIT"; then
  PROFILE_SHELL=ksh
elif test -n "$PS3"; then
  PROFILE_SHELL=unknown
else
  PROFILE_SHELL=sh
fi
13
27.01.2020, 19:41
  • 1
    Отметьте это только очень последние версии ksh93 иметь $KSH_VERSION. Та переменная прибывает из pdksh и никогда AT&T ksh88, до которого добираются. –  Stéphane Chazelas 16.04.2013, 00:28
  • 2
    Право, которое является, почему у меня есть второй тест для FCEDIT. –  Jens 16.04.2013, 09:12
  • 3
    Право. Отметьте это posh (pdksh с большинством функций неPOSIX, удаленных, таким образом, Вы, вероятно, хотели бы назвать это "sh"), не имеет никакого FCEDIT, ни KSH_VERSION, но имеет PS3 (возможно, не долгое время), хотя это маловероятно для одного иметь его как оболочку входа в систему. Также обратите внимание, что код выше не отразился бы ли bash или zsh находятся в sh режим эмуляции, который может быть проблемой, если Вы используете $PROFILE_SHELL решить, разрешить ли это или ту функцию. См. также whatshell Sven Mascheck для больше, Вы можете (или не может) хотеть проверить. –  Stéphane Chazelas 16.04.2013, 09:25

Если существует lsof команда, доступная в Вашей системе, можно получить полный путь родительского исполняемого файла оболочки путем получения родительского PID через ps и парсинг ouput lsof -p $ppid (см., Как определить текущую оболочку, я продолжаю работать?).

#!/bin/sh
ppid="`ps -p "$$" -o ppid=`"
lsof -nP -p "$ppid" | awk 'NR==3 {print $NF; exit}'
1
27.01.2020, 19:41
  • 1
    В моей системе это возвращается /, если я использую NR==4 Я получаю путь к родителю оболочек. –  Thor 15.04.2013, 10:10
  • 2
    Отметьте тот POSIX shs имеют $PPID переменная. На Linux, можно использовать readlink -f "/proc/$PPID/exe". –  Stéphane Chazelas 09.09.2014, 15:48

За пределами земли Linux или недостающий доступ к/proc файловой системе или equivelent, можно использовать pstree:

Принятие Вас имеет pid

На Mac:

./test.sh 
16012
-+= 00001 root /sbin/launchd
 \-+= 00245 wingwong /sbin/launchd
   \-+= 04670 wingwong /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal -psn_0_2052597
     \-+= 11816 root login -pf wingwong
       \-+= 11817 wingwong -bash
         \-+= 16012 wingwong ksh ./test.sh
           \-+- 16013 wingwong pstree -p 16012

На поле Linux:

./test.sh 
14981
bash(14981)---pstree(14982)

Формат и стиль вывода от pstree отличаются, в зависимости от Вашей среды, но можно осуществить вывод ASCII, и затем sed/tr/awk/etc. фильтруют вывод для получения оболочки, которая запускает скрипт.

Так очищенная версия вывода (работает на Mac или Linux выполнения ОС):

#!/usr/bin/env sh
pstree  -p $$  | tr ' ()' '\012\012\012' | grep -i "sh$" | grep -v "$0" | tail -1

На выполненных урожаях:

./test.sh 
sh

И, когда выполнено с другой оболочкой:

#!/usr/bin/env ksh
pstree  -p $$  | tr ' ()' '\012\012\012' | grep -i "sh$" | grep -v "$0" | tail -1

Урожаи:

./test.sh 
ksh

Никакая корневая или специальная файловая система не требуется. Отметьте, моя фильтрация предполагает, что двоичный файл оболочки называет концы с sh и что нет никаких промежуточных записей, которые заканчиваются sh. Также предполагает, что Вы не назвали свой сценарий "sh" или некоторый неудачный grep шаблон, который сотрет информацию.:) Потребует, чтобы некоторая настройка для Вашей собственной среды гарантировала более высокую степень защиты от неумелого обращения.

1
27.01.2020, 19:41

Можно использовать команду:

$ echo $SHELL

узнать оболочку из сценария.

-2
27.01.2020, 19:41
  • 1
    Нет. $SHELL оболочка выбора пользователя. Инициализированный от оболочки входа в систему пользователя. Ничто, чтобы сделать с в настоящее время рабочей оболочкой. –  Stéphane Chazelas 04.04.2013, 09:55

Теги

Похожие вопросы