Вы на самом деле натолкнулись на правильный термин ¹. Существует переменная среды SHLVL
который все главные интерактивные оболочки (удар, tcsh, zsh) увеличивают 1, когда они запускают. Таким образом, если Вы запускаете оболочку в оболочке, SHLVL
увеличения 1.
Это непосредственно не отвечает на Ваше беспокойство, однако, потому что SHLVL
переносит вещи как эмуляторы терминала. Например, в моей типичной конфигурации, $SHLVL
2 в xterm, потому что уровень 1 соответствует оболочке, которая выполняет мои X сессий (~/.xinitrc
или ~/.xsession
).
То, что я делаю, должно отобразиться $SHLVL
в моей подсказке, но только если родительский процесс оболочки является другой оболочкой (с эвристикой как, “если ее имя заканчивается в sh
плюс дополнительная пунктуация и цифры, это - оболочка”). Тем путем у меня есть очевидный визуальный признак в редком случае оболочки, работающей под другой оболочкой.
Возможно, Вы предпочли бы обнаруживать оболочки, которые работают непосредственно под эмулятором терминала. Можно сделать это справедливо точно: это оболочки, родительский процесс которых имеет другой терминал управления, так, чтобы ps -o tty= -p$$
и ps -o tty= -p$PPID
произведите другой вывод. Вы могли бы вручную сбросить SHLVL
к 1 в этих оболочках или наборе Ваше собственное TERMSHLVL
к 1 в этих оболочках (и увеличенный иначе).
¹, Хотя нельзя было бы думать это смотрящий на страницы руководства: ни одна из трех оболочек, которые поддерживают его, не включает слово “уровень” в их документацию SHLVL
.
Вы просто не можете сделать этого. Нет никакого пути ¹, сделать процесс может изменить среду своего родителя (или его текущий каталог, о котором Вы могли бы думать затем).
На самом деле еще меньше - happending, чем Вы думаете.
make
реализации отражают присвоение на делание PATH
переменная в среде; GNU делает (найденный на Linux, и другие системы) делает, но BSD делают, не делает.export PATH
строка работает на оболочке, которая завершается сразу впоследствии. Не то, чтобы эта строка сделала бы что-либо во-первых — если PATH
определяется в той точке, это - потому что это уже находится в среде оболочки.Сделайте для создания вещей автоматически. Если Вы хотите установить переменные для своей интерактивной среды, это не инструмент, на который необходимо смотреть. Вместо этого запишите отрывок оболочки и получите его в текущей оболочке:
. ./define-my-variables.sh
В Вашем make-файле получите сценарий в каждой подоболочке. Можно использовать обратную косую черту для создания долгой команды; помните это
set -e
.install:
set -e; \
. ./define-my-variables.sh; \
mkdir -p bin; \
…
¹ Обязательное примечание: никакой нормальный путь. Даже удаленно вызов chdir
через ptrace
от отладчика не будет работать, как с большинством оболочек, потому что им не нравится изменять их текущий каталог под их ногами.
Вы не можете. Это не возможно для подпроцесса (как make
) изменить среду его родительского процесса.
Вы могли сделать что-то как
$ eval `make pathupdate`
Где pathupdate
цель похожа:
pathupdate:
@echo PATH=\"$(PATH)\"
Вы можете заставить Make рекурсивно вызывать себя с измененным окружением, как таковое:
dummy: build_all
all:
PATH=/new/directory:$(PATH) $(MAKE) build_all
build_all:
your make rules
Если вы хотите использовать фрагмент оболочки:
dummy: build_all
all:
. ./define-my-variables.sh ; $(MAKE) build_all
build_all:
your make rules
Ваш ответ можно найти здесь: https://stackoverflow.com/a/8942216/367461
По сути, вам следует сделать следующее:
export PATH := $(shell pwd)/bin:$(PATH)
test:
mkdir -p ./bin
@echo $(PATH)
Я тестировал это на Fedora 23 с GNU Make 4.0, и у меня он отлично работает.
Я собираюсь задать тот же вопрос, потому что мне не удалось заставить другой пример ответа работать.
Однако мне удалось найти рабочее решение с помощью команды eval
. Я не совсем уверен, почему это не было опубликовано раньше.
do_something:
$(eval export PATH=$(shell pwd)/bin:$(PATH))
@echo $(PATH)
Примечание: изменения
ПУТЬ
являются временными в самой программе make. После выхода из make PATH сбрасывается до более раннего значения.