Может ли сценарий оболочки устанавливать переменные среды вызывающей оболочки?

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

setenv FOO foo

в csh / tcsh или

export FOO=foo

в sh / bash устанавливайте его только во время выполнения скрипта.

я уже знаю, что

source myscript

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

Но вот загвоздка:

Я хочу, чтобы этот скрипт можно было вызывать из bash или csh. Другими словами, я хочу, чтобы пользователи любой оболочки могли запускать мой скрипт и изменять среду своей оболочки. Таким образом, «источник» не будет работать для меня, поскольку пользователь, работающий с csh, не может создать сценарий bash, а пользователь, выполняющий bash, не может создать сценарий csh.

Есть ли какое-нибудь разумное решение, которое не требует написания и поддержки ДВУХ версий сценария?


person Larry Gritz    schedule 30.01.2009    source источник
comment
@eusoubrasileiro не работает (по крайней мере, на osx), поскольку «экспорт» интерпретируется bash как имя файла.   -  person drevicko    schedule 12.01.2016
comment
см. ответ @Humberto Romero stackoverflow.com/a/28489593/881375 в этой теме   -  person tomasb    schedule 14.07.2016
comment
Заголовок этого Q должен быть изменен - ​​основное различие заключается в использовании двух разных оболочек, заголовок этого не отражает.   -  person yzorg    schedule 18.01.2019
comment
Здесь для Linux и Windows ответили: unix.stackexchange.com/questions/38205/   -  person Andry    schedule 22.02.2019


Ответы (21)


У вашего процесса оболочки есть копия родительской среды и нет доступа к среде родительского процесса вообще. Когда ваш процесс оболочки завершает работу, любые изменения, внесенные вами в его среду, теряются. Получение файла сценария - наиболее часто используемый метод для настройки среды оболочки, вы можете просто укусить пулю и сохранить по одному для каждого из двух вариантов оболочки.

person converter42    schedule 30.01.2009
comment
@KrisRandall На самом деле ответ правильный !! исходный script.sh ==. script.sh - person MYZ; 02.06.2019

Используйте синтаксис вызова "скрипта с точкой". Например, вот как это сделать, используя полный путь к скрипту:

. /path/to/set_env_vars.sh

А вот как это сделать, если вы находитесь в том же каталоге, что и скрипт:

. set_env_vars.sh

Они выполняют сценарий под текущей оболочкой вместо загрузки другой (что произошло бы, если бы вы сделали ./set_env_vars.sh). Поскольку он работает в той же оболочке, установленные вами переменные среды будут доступны при выходе.

Это то же самое, что и вызов source set_env_vars.sh, но он короче для набора и может работать в некоторых местах, где source не работает.

person Humberto Romero    schedule 12.02.2015
comment
Другими словами, точка - это замена source в bash в других оболочках. - person stevesliva; 13.02.2015
comment
Я заметил, что это не сработает, если, например, вывод будет выводиться по конвейеру. ./script.sh | тройник out.log - person ozma; 07.04.2015
comment
Я понятия не имею, как и почему это работает, но работает отлично. - person ArtOfWarfare; 11.09.2015
comment
Этот ответ должен быть наверху - person tomasb; 14.07.2016
comment
Джип Должен быть наверху. Просто констатирую очевидное ... если сценарий находится в вашем PWD, то он имеет форму точки, например, пробела. ./localscript.sh - person Max Robbertze; 27.07.2016
comment
точка - это просто source - person DMaster; 21.10.2016
comment
@ozma Хороший улов, сегодня днем ​​я потратил несколько часов впустую! - person Phil Brubaker; 12.05.2017
comment
Это не работает ... если set_env_vars.sh делает export MY_VAR=123, $MY_VAR все еще пусто в вызывающем скрипте ... Я не понимаю этот ответ - person kris; 01.06.2017
comment
. ./set_env_vars.sh верно? - person 030; 16.06.2017
comment
В вопросе говорится, что он уже знает, что это за источник, и, очевидно, это не то, что он ищет. Это неправильный ответ на заданный вопрос. - person Roman Rabinovich; 02.10.2018
comment
Проголосовали за, так как это отвечает на вопрос в заголовке (для bash), хотя и не отвечает на полный вопрос. Это также ясно объясняет, почему source работает. - person mgarey; 10.01.2019

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

Вы можете написать сценарий, который будет выдавать правильные команды для tcsh или sh в зависимости от того, как он вызывается. Если ваш сценарий "setit", выполните:

ln -s setit setit-sh

а также

ln -s setit setit-csh

Теперь либо напрямую, либо через псевдоним, вы делаете это из sh

eval `setit-sh`

или это из csh

eval `setit-csh`

setit использует $ 0 для определения своего стиля вывода.

Это напоминает то, как люди используют для получения набора переменных среды TERM.

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

#!/bin/bash
arg0=$0
arg0=${arg0##*/}
for nv in \
   NAME1=VALUE1 \
   NAME2=VALUE2
do
   if [ x$arg0 = xsetit-sh ]; then
      echo 'export '$nv' ;'
   elif [ x$arg0 = xsetit-csh ]; then
      echo 'setenv '${nv%%=*}' '${nv##*=}' ;'
   fi
done

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

Чтобы упростить вызов csh, tcsh или аналогичных оболочек:

alias dosetit 'eval `setit-csh`'

или для sh, bash и т. д .:

alias dosetit='eval `setit-sh`'

Приятно то, что вам нужно хранить список только в одном месте. Теоретически вы можете даже вставить список в файл и поместить cat nvpairfilename между «in» и «do».

Это в значительной степени то же самое, что и раньше выполнялись настройки терминала оболочки входа в систему: сценарий выводил статусы, которые должны быть выполнены в оболочке входа в систему. Псевдоним обычно используется для упрощения вызова, как в "tset vt100". Как упоминалось в другом ответе, на сервере новостей INN UseNet также есть аналогичные функции.

person Thomas Kammeyer    schedule 30.01.2009
comment
Я думаю, это может быть на правильном пути. Но я не совсем знаю, что должно быть в setit, что позволит ему правильно работать из любой оболочки. Можете ли вы рассказать немного подробнее о том, что вы имели в виду? - person Larry Gritz; 30.01.2009
comment
По сути, он проверяет $ 0 и перемещается в соответствующую часть скрипта в зависимости от того, с каким именем он был вызван. - person phresus; 30.01.2009
comment
Я думаю, что Томас говорит, что вы пишете setit сценарий на одном языке, но затем он выводит набор инструкций для конкретного языка, которые должны быть eval'd вызывающим процессом. - person matpie; 31.01.2009
comment
Ага, я вижу, что ты сейчас делаешь. Ух, это умно, но неудобно. Спасибо за разъяснение. - person Larry Gritz; 31.01.2009
comment
Это круто. Моя проблема намного проще: изменение переменных env без использования. или источник. Простой alias gg='. gg $1' исправляет это. - person mcv; 02.03.2011
comment
Вам не нужна вся сложная система ссылок. Просто используйте переменную $ SHELL. - person Mad Physicist; 15.04.2015
comment
Переменная SHELL не совсем надежна. Пример: в моей системе ArchLinux я запускаю tcsh, а SHELL установлен в / bin / tcsh. Запуск bash и повторение SHELL по-прежнему дает / bin / tcsh и то же самое при вызове bash как sh. SHELL работает только в оболочках, которые пытаются ее установить, или в системах с rc-файлами, которые ее устанавливают, и не все. - person Thomas Kammeyer; 16.04.2015

В моем .bash_profile у меня есть:

# No Proxy
function noproxy
{
    /usr/local/sbin/noproxy  #turn off proxy server
    unset http_proxy HTTP_PROXY https_proxy HTTPs_PROXY
}


# Proxy
function setproxy
{
    sh /usr/local/sbin/proxyon  #turn on proxy server 
    http_proxy=http://127.0.0.1:8118/
    HTTP_PROXY=$http_proxy
    https_proxy=$http_proxy
    HTTPS_PROXY=$https_proxy
    export http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
}

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

person chris    schedule 19.11.2011
comment
Это как раз то, что мне было нужно (ну, пришлось менять номер порта;). - person Agos; 01.12.2011

Это «отчасти» возможно при использовании gdb и setenv (3), хотя мне трудно рекомендовать на самом деле это. (Кроме того, то есть самая последняя версия ubuntu фактически не позволит вам сделать это, не указав ядру быть более снисходительным к ptrace, и то же самое может произойти и для других дистрибутивов).

$ cat setfoo
#! /bin/bash

gdb /proc/${PPID}/exe ${PPID} <<END >/dev/null
call setenv("foo", "bar", 0)
END
$ echo $foo

$ ./setfoo
$ echo $foo
bar
person Kjetil Joergensen    schedule 08.07.2011
comment
Кьетил, чувак, это фантастика. Мне сейчас очень нравится твой сценарий. - person Heath Hunnicutt; 26.07.2015
comment
Это круто! Но как это сделать на Mac? - person Li Dong; 05.10.2015
comment
спасибо, как однострочный: gdb -nx -p $$ --batch -ex 'call setenv("foo", "bar")' > & /dev/null - person Yinon Ehrlich; 03.04.2016
comment
Интересный подход. Когда у меня будет время, я посмотрю, как это сделать в OS X и обновлюсь. - person Robert Brisita; 04.05.2016

Это работает, это не то, что я бы использовал, но это «работает». Создадим скрипт teredo для установки переменной окружения TEREDO_WORMS:

#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL -i

Он будет интерпретирован оболочкой Korn, экспортирует переменную среды, а затем заменит себя новой интерактивной оболочкой.

Перед запуском этого сценария мы установили SHELL в среде оболочки C, а переменная среды TEREDO_WORMS не установлена:

% env | grep SHELL
SHELL=/bin/csh
% env | grep TEREDO
%

Когда скрипт запускается, вы находитесь в новой оболочке, другой интерактивной оболочке C, но установлена ​​переменная среды:

% teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%

Когда вы выходите из этой оболочки, исходная оболочка берет на себя:

% exit
% env | grep TEREDO
%

Переменная среды не установлена ​​в исходной среде оболочки. Если вы используете exec teredo для запуска команды, то исходная интерактивная оболочка заменяется оболочкой Korn, которая задает среду, а затем она, в свою очередь, заменяется новой интерактивной оболочкой C:

% exec teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%

Если вы наберете exit (или Control-D), ваша оболочка завершится, вероятно, выйдете из этого окна или вернетесь на предыдущий уровень оболочки, с которого начались эксперименты.

Тот же механизм работает для оболочки Bash или Korn. Вы можете обнаружить, что приглашение после команд выхода появляется в забавных местах.


Обратите внимание на обсуждение в комментариях. Я бы не рекомендовал это решение, но оно позволяет достичь заявленной цели с помощью одного скрипта для установки среды, которая работает со всеми оболочками (которые принимают параметр -i для создания интерактивной оболочки). Вы также можете добавить "$@" после параметра для передачи любых других аргументов, которые затем могут сделать оболочку пригодной для использования в качестве общего инструмента «установить среду и выполнить команду». Вы можете опустить -i, если есть другие аргументы, ведущие к:

#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL "${@-'-i'}"

Бит "${@-'-i'}" означает, что «если список аргументов содержит хотя бы один аргумент, использовать исходный список аргументов; в противном случае замените несуществующие аргументы -i '.

person Jonathan Leffler    schedule 30.01.2009
comment
Гм, это довольно радикально: вы заменяете оболочку входа в систему. Если вы собираетесь это сделать ... вы должны проверить, как это влияет на сеанс, группу процессов и другие вещи. Например: как вы думаете, что происходит с управляемыми дочерними процессами? - person Thomas Kammeyer; 31.01.2009
comment
Несомненно - поэтому я сказал, что не буду им пользоваться. Если вы выполните команду дважды, вы не потеряете информацию о сеансе или группе процессов; который основан на PID, и PID не меняется. В профиле или файле входа в систему вы можете воспользоваться сценарием настройки общеязыковой среды. Но, как я уже сказал, я бы не стал его использовать. - person Jonathan Leffler; 31.01.2009
comment
Именно это я и пытался сделать в моем конкретном случае! Этот метод, кажется, используется clearcase при выполнении setview cleartool, что я пытаюсь подражать. Большое спасибо ! - person Offirmo; 06.06.2012
comment
Вы можете просто вызвать новую оболочку, а не заменять существующую. - person Jonathon Hill; 08.04.2013
comment
@JonathonHill: Вы могли бы (запустить новую оболочку как обычную команду вместо выполнения exec). Основная причина, по которой этого не следует делать, заключается в том, что у вас случайный уровень оболочки, поэтому вам придется сделать дополнительный Control-D, чтобы выйти из этого окна. - person Jonathan Leffler; 08.04.2013
comment
Верно, что было вполне приемлемо в моем конкретном случае использования. Спасибо! - person Jonathon Hill; 10.04.2013

Вам следует использовать модули, см. http://modules.sourceforge.net/

РЕДАКТИРОВАТЬ: пакет модулей не обновлялся с 2012 года, но все еще работает нормально. Все новые функции, навороты появляются в lmod сегодня (что мне нравится больше): https://www.tacc.utexas.edu/research-development/tacc-projects/lmod

person Davide    schedule 04.02.2009
comment
Здесь мы широко используем файлы модулей, и одной из причин является поддержка csh / bourne-ish. У нас есть устаревшие сценарии csh, сценарии bash и сценарии python, и все они получают настройки переменных среды из одних и тех же файлов модулей, вместо того, чтобы иметь набор сценариев env.csh, env.sh, env.py с дополнительным обслуживанием, которое влечет за собой. Кроме того, файлы модулей позволяют вашей среде отражать зависимости версий: если вам нужно перейти на версию 3 с версии 4 инструмента, вместо того, чтобы сбрасывать все ваши переменные env вручную, вы можете просто поменять модуль, и все изменится. - person Andrej Panjkov; 15.05.2009
comment
Я не мог найти примеров того, как его использовать, все попытки, которые я предпринял, были неудачными, какие-либо советы? - person Aquarius Power; 08.06.2014
comment
@AquariusPower, спустя столько лет, я больше не рекомендую модули, но его моральный преемник, это lmod, см. tacc.utexas.edu/tacc-projects/lmod - я думаю, что его документация также лучше, чем у старых модулей, посмотрим, лучше ли это для вас - person Davide; 10.06.2014
comment
@LiDong - да, он не обновлялся с 2012 года, но все еще работает нормально. Все новые функции, навороты появляются в lmod сегодня (что мне нравится больше): tacc.utexas.edu/research-development/tacc-projects/lmod - person Davide; 06.10.2015

Другой обходной путь, о котором я не упоминал, - это запись значения переменной в файл.

Я столкнулся с очень похожей проблемой, когда я хотел иметь возможность запустить последний набор тестов (вместо всех моих тестов). Мой первый план состоял в том, чтобы написать одну команду для установки переменной env TESTCASE, а затем создать другую команду, которая будет использовать ее для запуска теста. Излишне говорить, что у меня была такая же проблема, как и у вас.

Но потом я придумал такой простой прием:

Первая команда (testset):

#!/bin/bash

if [ $# -eq 1 ]
then
  echo $1 > ~/.TESTCASE
  echo "TESTCASE has been set to: $1"
else
  echo "Come again?"
fi

Вторая команда (testrun):

#!/bin/bash

TESTCASE=$(cat ~/.TESTCASE)
drush test-run $TESTCASE
person dkinzer    schedule 26.07.2013

Добавьте флаг -l в начало вашего сценария bash, т.е.

#!/usr/bin/env bash -l

...

export NAME1="VALUE1"
export NAME2="VALUE2"

Значения с NAME1 и NAME2 теперь будут экспортированы в вашу текущую среду, однако эти изменения не являются постоянными. Если вы хотите, чтобы они были постоянными, вам нужно добавить их в ваш .bashrc файл или другой файл инициализации.

На страницах руководства:

-l Make bash act as if it had been invoked as a login shell (see INVOCATION below).
person cristobal    schedule 16.06.2014
comment
Нет, на самом деле не работает. Все, что происходит, - это ваш сценарий думает, что он работает в оболочке входа в систему. По-прежнему не предоставляет переменные вызывающей оболочке. - person Endareth; 13.02.2018

Вы можете указать дочернему процессу распечатать свои переменные среды (вызывая «env»), затем перебрать напечатанные переменные среды в родительском процессе и вызвать «экспорт» для этих переменных.

Следующий код основан на захвате результатов поиска. -print0 в массив bash

Если родительская оболочка - это bash, вы можете использовать

while IFS= read -r -d $'\0' line; do
    export "$line"
done < <(bash -s <<< 'export VARNAME=something; env -0')
echo $VARNAME

Если родительской оболочкой является тире, то read не предоставляет флаг -d, и код становится более сложным.

TMPDIR=$(mktemp -d)
mkfifo $TMPDIR/fifo
(bash -s << "EOF"
    export VARNAME=something
    while IFS= read -r -d $'\0' line; do
        echo $(printf '%q' "$line")
    done < <(env -0)
EOF
) > $TMPDIR/fifo &
while read -r line; do export "$(eval echo $line)"; done < $TMPDIR/fifo
rm -r $TMPDIR
echo $VARNAME
person klaus se    schedule 25.09.2014

Вы можете вызвать еще один Bash с другим профилем bash_profile. Также вы можете создать специальный bash_profile для использования в среде multi-bashprofile.

Помните, что вы можете использовать функции внутри bashprofile, и эти функции будут доступны глобально. например, "пользователь функции {export USER_NAME $ 1}" может устанавливать переменную во время выполнения, например: пользователь olegchir && env | grep olegchir

person Oleg Chirukhin    schedule 29.10.2010
comment
Ничто из этого не повлияет на вызывающую оболочку. - person Ignacio Vazquez-Abrams; 29.10.2010
comment
@Ignacio, в этом случае вам не нужно вызывать скрипты для установки переменных окружения. Вызывающая оболочка сама установит переменную. Но если нам все же нужно отделить сеттеры от основного кода bashrc, мы можем разделить все эти функции в отдельный файл и включить его как библиотеку (например, исходный код ru.olegchir.myproject.environment.setters.sh в .bashrc) . - person Oleg Chirukhin; 03.11.2010

Другой вариант - использовать «Модули среды» (http://modules.sourceforge.net/). К сожалению, это вводит в игру третий язык. Вы определяете среду с помощью языка Tcl, но есть несколько удобных команд для типичных модификаций (добавить или добавить или установить). Вам также потребуется установить модули среды. Затем вы можете использовать module load *XXX*, чтобы назвать нужную среду. Команда модуля - это, по сути, причудливый псевдоним для механизма eval, описанного выше Томасом Каммейером. Основным преимуществом здесь является то, что вы можете поддерживать среду на одном языке и полагаться на «Модули среды» для перевода ее в sh, ksh, bash, csh, tcsh, zsh, python (?!? !!) и т. Д.

person Howard Hobbes    schedule 23.10.2014

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

#!/bin/bash
unset http_proxy

Сделайте файл исполняемым

sudo chmod 744 unsetvar

Создать псевдоним

alias unsetvar='source /your/path/to/the/script/unsetvar'

Он должен быть готов к использованию до тех пор, пока у вас есть папка, содержащая файл сценария, добавленный к пути.

person Marton Tatai    schedule 19.01.2017
comment
По какой причине вы просто не используете alias unsetvar='unset http_proxy'? Или еще лучше создать функцию unsetvar () { unset http_proxy; } - person tripleee; 23.11.2017
comment
Это не только для OS X. Это может работать и для Linux. Этот ответ также будет лучше, если вы написали, с какими файлами вы работаете. - person Andreas Storvik Strauman; 02.04.2018

Я не вижу ответа, в котором описывалось бы, как обойти эту проблему с взаимодействующими процессами. Обычный шаблон с такими вещами, как ssh-agent, - это когда дочерний процесс печатает выражение, которое родительский процесс может eval.

bash$ eval $(shh-agent)

Например, ssh-agent имеет параметры для выбора синтаксиса вывода, совместимого с Csh или Bourne.

bash$ ssh-agent
SSH2_AUTH_SOCK=/tmp/ssh-era/ssh2-10690-agent; export SSH2_AUTH_SOCK;
SSH2_AGENT_PID=10691; export SSH2_AGENT_PID;
echo Agent pid 10691;

(Это приводит к запуску агента, но не позволяет вам его использовать, если вы сейчас не скопируете и вставите этот вывод в приглашение оболочки.) Сравните:

bash$ ssh-agent -c
setenv SSH2_AUTH_SOCK /tmp/ssh-era/ssh2-10751-agent;
setenv SSH2_AGENT_PID 10752;
echo Agent pid 10752;

(Как видите, csh и tcsh используют setenv для установки переменных.)

Ваша собственная программа тоже может это сделать.

bash$ foo=$(makefoo)

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

person tripleee    schedule 23.11.2017

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

1.) Создайте сценарий с условием выхода либо 0 (успешно), либо 1 (неуспешно).

if [[ $foo == "True" ]]; then
    exit 0
else
    exit 1

2.) Создайте псевдоним, зависящий от кода выхода.

alias='myscript.sh && export MyVariable'

Вы вызываете псевдоним, который вызывает сценарий, который оценивает условие, которое требуется для выхода из нуля через '&&', чтобы установить переменную среды в родительской оболочке.

Это мусор, но в крайнем случае может пригодиться.

person user1802263    schedule 31.08.2018

Технически это правильно - только eval не является ответвлением другой оболочки. Однако с точки зрения приложения, которое вы пытаетесь запустить в измененной среде, разница равна нулю: дочерний элемент наследует среду своего родителя, поэтому (измененная) среда передается всем нисходящим процессам.

Фактически, измененная переменная окружения «прилипает» - пока вы работаете в родительской программе / оболочке.

Если абсолютно необходимо, чтобы переменная среды оставалась после выхода из родительской оболочки (Perl или оболочки), родительская оболочка должна выполнить тяжелую работу. Один из методов, который я видел в документации, заключается в том, что текущий скрипт порождает исполняемый файл с необходимым языком экспорта, а затем обманом заставляет родительскую оболочку выполнить его, всегда осознавая тот факт, что вам нужно предварять команду с 'источником', если вы пытаетесь оставить энергонезависимую версию измененной среды. В лучшем случае Клюге.

Второй метод - изменить сценарий, который запускает среду оболочки (.bashrc или что-то еще), чтобы он содержал измененный параметр. Это может быть опасно - если вы перегружаете скрипт инициализации, это может сделать вашу оболочку недоступной при следующей попытке запуска. Есть множество инструментов для изменения текущей оболочки; Добавляя необходимые настройки к «пусковой установке», вы также эффективно продвигаете эти изменения. Вообще не очень хорошая идея; если вам нужны изменения среды только для определенного набора приложений, вам придется потом вернуться и вернуть сценарий запуска оболочки в исходное состояние (используя vi или что-то еще).

Короче, хороших (и простых) методов не бывает. Предположительно, это было затруднено, чтобы гарантировать, что безопасность системы не будет безвозвратно скомпрометирована.

person David Lovering    schedule 18.05.2011

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

Так почему бы просто не что-то вроде

#!/usr/bin/env bash
FOO=foo $SHELL

Затем, когда вы закончите с окружением, просто exit.

person Andrew    schedule 28.02.2013

Вы всегда можете использовать псевдонимы

alias your_env='source ~/scripts/your_env.sh'
person user1667208    schedule 10.04.2014

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

Затем сценарий, который вы создадите в любой из двух оболочек, имеет команду с этой последней формой, которая подходит для каждой оболочки с псевдонимом.

Если я найду конкретные псевдонимы, я их выложу.

person sancho.s ReinstateMonicaCellio    schedule 30.10.2015

Я создал решение, используя трубы, eval и signal.

parent() {
    if [ -z "$G_EVAL_FD" ]; then
            die 1 "Rode primeiro parent_setup no processo pai"
    fi
    if [ $(ppid) = "$$" ]; then
            "$@"
    else
            kill -SIGUSR1 $$
            echo "$@">&$G_EVAL_FD
    fi
}
parent_setup() {
    G_EVAL_FD=99
    tempfile=$(mktemp -u)
    mkfifo "$tempfile"
    eval "exec $G_EVAL_FD<>'$tempfile'"
    rm -f "$tempfile"
    trap "read CMD <&$G_EVAL_FD; eval \"\$CMD\"" USR1
}
parent_setup #on parent shell context
( A=1 ); echo $A # prints nothing
( parent A=1 ); echo $A # prints 1

Он может работать с любой командой.

person Luiz Angelo Daros de Luca    schedule 21.09.2016

Кроме условий записи в зависимости от того, что установлено в $ SHELL / $ TERM, нет. Что плохого в использовании Perl? Он довольно распространен (я не могу придумать ни одного варианта UNIX, в котором его не было бы), и это избавит вас от неприятностей.

person phresus    schedule 30.01.2009
comment
Как Perl решает проблему? Программа Perl все еще не может установить переменные среды вызывающей оболочки, не так ли? - person Larry Gritz; 30.01.2009
comment
Нет. Однако он может установить его через Local :: Env, а затем вызвать сценарий оболочки с помощью system () или обратных кавычек. - person phresus; 02.02.2009
comment
Я почти уверен, что system () или обратные кавычки создадут новую дочернюю оболочку, а не вызовут оболочку, запустившую сценарий Perl. - person Larry Gritz; 05.02.2009