узнайте, какая оболочка tcsh / bash / etc. выполняется при использовании eval в скрипте

#bash #shell #eval #csh #tcsh

#bash #оболочка #eval #csh #tcsh

Вопрос:

У меня есть сценарий оболочки, который экспортирует переменные для использования в настройке инструмента для многопользовательской среды. Поскольку разные проекты (история более 100 проектов) используют разные настройки, мой скрипт устанавливает переменные для разных типов оболочек.

Пример:

 #!/bin/sh

#some XY_VAR setting happening here

case "$1" in

'-c')
    echo "setenv XY $XY_VAR;"
    ;;

'-b')
    echo "export XY=$XY_VAR;"
    ;;

esac
 

при использовании в скрипте проекта он оценивается следующим образом

 eval `set_my_vars -c` #when using (t)c-shell
eval `set_my_vars -b` #when using bash
 

Мой вопрос в том, могу ли я заставить скрипт определять оболочку, из которой он вычисляется, и вводить ее в оператор case?

ps -hp $$

не работает при оценке скрипта, это была моя первая идея (с awk, конечно). Я нашел несколько способов, с помощью которых люди хотели определить, в какой оболочке они работают, но все, что я нашел, терпит неудачу при использовании eval.

Кто-нибудь может помочь? Может быть, я просто глуп, чтобы найти решение самостоятельно.

Спасибо и с наилучшими пожеланиями rws

Комментарии:

1. теоретически правильно, но вы все равно можете устанавливать переменные и находиться в других оболочках. Если BASH установлен в tcsh, мой скрипт примет неправильный оператор case

Ответ №1:

$$ относится к текущему процессу; который в вашем случае является оболочкой, которая порождается обратными метками. Итак, что вам нужно сделать, это получить pid процесса, который породил подоболочку: родительский процесс. Примером может быть:

 comm=$(ps -ho comm $(ps -ho ppid $))
echo "echo "$comm""
 

Сначала выполняется ps -ho ppid $$ , чтобы получить родительский pid, а затем запускает другой ps -ho comm , чтобы получить имя команды из родительского pid.

А затем с помощью:

 eval `./sourceme`
 

Выведет ожидаемое значение:

 [~]% eval `./sourceme`
zsh

$ sh
$ eval `./sourceme`
sh

$ csh
% eval `./sourceme`
csh

% bash
[~]$ eval `./sourceme`
bash

[~]$ osh
osh$ eval `./sourceme`
osh
 

Однако для оболочки fish требуется немного другой синтаксис:

 osh$ fish
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish
martin@e585 ~> eval `./sourceme`
fish: Unknown command: `./sourceme`
martin@e585 ~> eval (./sourceme)
fish
 

Я тестировал это только в Linux; поскольку ваш ps пример выдает ошибку в моей системе («неподдерживаемая опция SysV»), Похоже, что вы, вероятно, не используете Linux (или Linux с другим ps ?), Поэтому вам может потребоваться немного поработать с командами, но, надеюсь, это должно указать вам направильное направление.

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


Если вы используете Linux, другим вариантом будет использование файловой системы /proc:

 ppid=$(cat "/proc/$/status" | grep ^PPid: | awk '{print $2}')
comm=$(cat "/proc/$ppid/status" | grep ^Name: | awk '{print $2}')
echo "echo "$comm""
 

Но это будет работать только в Linux. ps немного запутана и сложна в переносимости, но она, безусловно, более переносима, чем procfs в Linux.

Комментарии:

1. Спасибо Мартин за ваш ответ и ваше решение! Я запускаю CentOS6 / 7 / 8 на своей машине, и с помощью case '$comm' нее я теперь могу идеально адаптировать свои переменные env по своему вкусу. Большое спасибо, спасибо! rws