Я плохо знаком с Ubuntu.
Я записал сценарий для добавления dir к среде ПУТИ. Когда я запускаю скрипт, он хорошо работает, и dir добавляется к ПУТИ. Но кажется, что изменение только длится до выходов сценария вместо того, чтобы длиться в течение продолжительности сессии. То, когда я смотрю на ПУТЬ после того, как сценарий, работало, dir больше не там. Какие-либо предложения?
Существует две вещи помнить:
Команды, включая сценарии, сохраняют свою среду на время выполнения команды
Команды наследовали среду от родительского процесса. Для команд, запущенных через оболочку, они наследуются оболочке.
Таким образом, если Вы делаете PATH=$PATH:/my/dir
это только продолжится в период сценариев. Для создания этого постоянным родительская оболочка должна знать об изменении. Надлежащий способ сделать, который должен был бы записать в ~/.bashrc
если Вы используете удар или соответствующий емкостно-резистивный файл для Вашей оболочки. Таким образом мы можем использовать>> для добавления в файл
echo PATH=$PATH:/my/dir >> ~/.bashrc
И когда сценарий выходит, выполненный
source ~/.bashrc
так, чтобы оболочка перечитала конфигурацию и знала об изменениях. Теперь каждая команда, которую Вы выполняете в оболочке и каждой новой интерактивной запущенной оболочке, наследует новую переменную ПУТИ
Два шага могут быть соединены в функцию с тех пор (по крайней мере, для удара) функции, выполненные в текущей среде оболочки, таким образом, в отличие от сценария, когда Вы делаете source
часть, звоня source
от функции будет влиять на текущую оболочку.
Ответ Sergiy Kolodyazhnyy определяет проблему здесь: сценарии выполняются в отдельной дочерней оболочке оболочки, которая называет их и управляет, чтобы влияли на саму оболочку, такую как присвоение переменным или изменение рабочего каталога, не влияйте на оболочку вызова вообще, только дочерняя оболочка и (если они export
переменные к среде) ее дети.
Можно играть с этим использованием скромные переменные оболочки...
$ foo=bar
$ echo $foo
bar
$ echo -e "foo=baz \n"'echo $foo' > script
$ cat script
foo=baz
echo $foo
$ bash script
baz
$ echo $foo
bar
Хотя, поскольку Eliah Kagan показывает в этом ответе, легче сделать так с подоболочками.
Я пишу этот ответ в случае, если Вы не хотите постоянно добавлять каталог к своему ПУТИ, но только к текущей сессии оболочки.
Чтобы сделать это, просто необходимо запустить скрипт в текущей оболочке. Это, покончили source
команда, которая сокращена до .
(точка).
Учитывая эту немного упрощенную версию Вашего сценария...
read -rp "What did you want to add to PATH? "
[ -d "$REPLY" ] &&
PATH="$PATH:$(readlink -m $REPLY)" &&
echo "OK, adding $REPLY to PATH" &&
echo "$PATH" ||
echo "seems like $REPLY is not a directory"
Заметьте, что я получаю тот же результат как Вы, когда я запускаю скрипт обычным способом:
$ ./add-to-path
What did you want to add to PATH? /home/zanna/playground
OK, adding /home/zanna/playground to PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/zanna/playground
$ echo $PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Но когда я source
сценарий это работает как ожидалось:
$ . add-to-path
What did you want to add to PATH? /home/zanna/playground
OK, adding /home/zanna/playground to PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/zanna/playground
$ echo $PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/zanna/playground
Я добавлю три азида:
~/.profile
вместо ~/.bashrc
потому что ~/.bashrc
получен каждой интерактивной оболочкой Bash, включая оболочки, запущенные с текущей оболочки - это означает, что дочерние оболочки могли закончиться с действительно длинными трактами, поскольку они наследовали ПУТЬ, а также добавляющий к ней, когда они получают ~/.bashrc
. Напротив, ~/.profile
обычно только получается при входе в систему (или оболочками входа в систему).export
когда Вы присваиваете ПУТИ, потому что это уже - переменная среды: в некотором смысле это уже экспортировано и останется так: присвоение на ПУТЬ будет всегда наследовано дочерними процессами (хотя не родительских процессов, поскольку Вы обнаружили!), не будучи явно export
редактор.Я заключил переменные в кавычки REPLY
и PATH
повсюду. Это - хорошая идея, потому что или может иметь пробелы или другие символы та триггерная оболочка расширения. Однако побочный эффект этого - это ~
не расширен, таким образом, сценарий склонен возвратить вещи как
looks like ~/some-existing-dir is not a directory
который верен (взятие ~
буквально), но не очень полезный. Возможно, сценарий должен предупредить пользователя об этом...