Если я исследую, /proc/1/environ
я вижу строку с разделенными нулем байтами 1
переменных среды процесса . Я хотел бы перенести эти переменные в мою текущую среду. Есть простой способ сделать это?
Страница proc
man дает мне фрагмент, который помогает распечатывать каждую переменную среды построчно (cat /proc/1/environ; echo) | tr '\000' '\n'
. Это помогает мне проверить правильность содержимого, но что мне действительно нужно, это добавить эти переменные в мою текущую сессию bash.
Как я могу это сделать?
источник
. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/nnn/environ)
, который будет правильно обрабатывать переменные с кавычками."$@"
вместо'{}'
. Для тех, кто интересуется--
аргументом в его улучшенном ответе: позиционные аргументыbash -c command_string
присваиваются начиная с$0
, а"$@"
расширяются и включают аргументы, начинающиеся с$1
. Аргумент--
присваивается$0
.В
bash
вы можете сделать следующее. Это будет работать для всего возможного содержимого переменных и избегатьeval
:Это объявит переменные чтения как переменные оболочки в запущенной оболочке. Чтобы вместо этого экспортировать переменные в работающую оболочку:
источник
В этом ответе я предполагаю систему, в которой
/proc/$pid/environ
возвращается среда процесса с указанным PID с нулевыми байтами между определениями переменных. ( Так что Linux, Cygwin или Solaris (?) ).Zsh
(Довольно просто, как в zsh: перенаправление ввода без команды
<FILE
эквивалентноcat FILE
. Вывод подстановки команды подвергается расширению параметра с флагами,ps:\000:
означающими «разделить на нулевые байты» и@
означающими «если все это в двойных кавычках, тогда обрабатывать каждый элемент массива как отдельное поле »(обобщение"$@"
).Баш, мкш
(В этих оболочках пустой разделитель, передаваемый в
read
результате, приводит к тому, что нулевые байты являются разделителями. Я используюPWD
в качестве временного имени переменной, чтобы избежать засорения другой переменной, которая может быть в конечном итоге импортирована. Хотя вы также можете технически импортироватьPWD
, он будет оставаться на месте только до следующийcd
.)POSIX
Переносимость POSIX не столь интересна для этого вопроса, потому что она применима только к системам, которые имеют
/proc/PID/environ
. Так что вопрос в том, что поддерживает Solaris sed - или, если есть/proc/PID/environ
, то Solaris не использовал, но я сильно отстаю от кривой возможностей Solaris, так что в настоящее время это возможно. В Linux утилиты GNU и BusyBox являются нулевыми, но с оговорками.Если мы настаиваем на переносимости POSIX, ни одна из текстовых утилит POSIX не требуется для обработки нулевых байтов, так что это сложно. Вот решение, которое предполагает, что awk поддерживает нулевой байт в качестве разделителя записей (nawk и gawk делают, как это делает BusyBox awk, но mawk нет).
BusyBox awk (версия, обычно встречающаяся в встраиваемых системах Linux) поддерживает нулевые байты, но не устанавливает
RS
значение"\0"
вBEGIN
блоке, а не синтаксис командной строки выше; Однако это поддерживает-v 'RS="\0"'
. Я не исследовал почему, это похоже на ошибку в моей версии (Debian wheezy).(Оберните все
строкиразделенными нулями записями в одинарные кавычки"\047"
, после экранирования одинарных кавычек внутри значений.)Предостережения
Помните, что любой из них может попытаться установить переменные только для чтения (если ваша оболочка имеет переменные только для чтения).
источник
Я ходил по кругу с этим. Я был разочарован переносимостью нулевых байтов. Мне не понравилось, что не было надежного способа справиться с ними в скорлупе. Так что я продолжал искать. Правда в том, что я нашел несколько способов сделать это, только несколько из которых отмечены в моем другом ответе. Но результатом были как минимум две функции оболочки, которые работают так:
Сначала я расскажу о
\0
разграничении. Это на самом деле довольно легко сделать. Вот функция:Обычно
od
принимаетstdin
и записываетstdout
каждый байт, который получает в шестнадцатеричном формате на строку.Могу поспорить, вы можете догадаться, что
\0null
, верно? Написано так, что с любым легко справитьсяsed
.sed
просто сохраняет последние два символа в каждой строке, пока не встретит ноль, и в этот момент он заменяет промежуточные символы новой строкиprintf
дружественным кодом формата и печатает строку. Результатом является\0null
разделенный массив шестнадцатеричных байтов. Посмотрите:Я передал вышеупомянутое,
tee
чтобы вы могли видеть как вывод команды susbstitution, так и результатprintf
обработки. Надеюсь, вы заметите, что подоболочка на самом деле тоже не указана, аprintf
разделена только по\0null
разделителю. Посмотрите:Никаких кавычек на это расширение тоже - не важно, цитируете ли вы это или нет. Это связано с тем, что значения прикуса проходят неразделенными, за исключением того, что одна электронная
\n
линия создается для каждого раза, когдаsed
печатается строка. Разделение слов не применяется. И вот что делает это возможным:Вышеприведенная функция использует
_zedlmt
либо${pcat}
подготовленный поток байтового кода для получения ресурсов среды любого процесса, который может быть найден в текущей оболочке, либо/proc
непосредственно.dot
${psrc}
в текущей оболочке, либо без параметра, для отображения обработанного вывода того же самого на терминале, напримерset
илиprintenv
будет. Все , что вам нужно , это$pid
- любой читаемый/proc/$pid/environ
файл будет делать.Вы используете это так:
Но в чем разница между человеком дружелюбным и доступным ? Ну, разница в том, что делает этот ответ отличным от всех остальных, включая мой другой. Любой другой ответ так или иначе зависит от цитирования оболочки для обработки всех крайних случаев. Это просто не работает так хорошо. Пожалуйста, поверьте мне - я пытался. Посмотрите:
Никакое количество символов в стиле фанк или содержащихся в кавычках не может сломать это, потому что байты для каждого значения не оцениваются до самого момента получения контента. И мы уже знаем, что оно работало как значение хотя бы один раз - здесь нет необходимости в синтаксическом анализе или защите кавычек, потому что это побайтная копия исходного значения.
Функция сначала оценивает
$var
имена и ожидает завершения проверок, прежде чем.dot
источник here-doc загрузит его в файл-дескриптор 3. Прежде чем получить его, он выглядит так. Это глупо. И POSIX портативный. Ну, по крайней мере, обработка \ 0null является переносимой POSIX - файловая система / process, очевидно, специфична для Linux. И вот почему есть две функции.источник
Использование
source
и процесс подстановки :Коротко:
Использование
eval
и подстановка команд :sed
Вызов может быть заменен наawk
вызов:Но не забывайте, что он не очищает переменные окружения, которых нет в pid 1.
источник
Стоит отметить, что процессы могут иметь переменные среды, которые не являются допустимыми переменными Bash / Sh / * sh - POSIX рекомендует, но не требует, чтобы переменные среды имели совпадающие имена
^[a-zA-Z0-9_][a-zA-Z0-9_]*$
.Чтобы создать список переменных, совместимых с оболочкой из среды другого процесса, в Bash:
Точно так же, чтобы загрузить их:
Эта проблема возникает только изредка, но когда это происходит ...
источник
Я думаю, что это портативный POSIX:
Но @Gilles делает хорошее замечание -
sed
вероятно, будет обрабатывать нули, но, возможно, нет. Так что есть (я действительно так думаю на этот раз) на самом деле переносимый метод POSIX:Тем не менее, если у вас есть GNU,
sed
вам нужно только сделать:Ну, POSIX portable, за исключением того,
/dev/...
который не указан, но вы можете ожидать, что этот синтаксис будет вести себя одинаково в большинстве Unices.Теперь, если это как-то связано с вашим другим вопросом , вы можете использовать его следующим образом:
Документ
.dot
Here-Doc чрезвычайно полезен тем, что не позволяет оболочке обойтись без какой-либо цитаты, которую мы так усердно обрабатываем в подоболочке, а также обеспечивает нам надежный путь к исходному файлу, а не, опять же, подоболочке или оболочке. переменная. Другие здесь используют<(process substitution)
bashism, который работает во многом таким же образом - только он определенно является анонимным,|pipe
тогда как POSIX определяет толькоiohere
для here-docs, и поэтому это может быть файл любого типа, хотя на практике это обычноtemp
файл. (dash,
с другой стороны,|pipes
для анонимных документов здесь используется анонимность ) . К сожалению, при замене процесса он также зависит от оболочки, что может быть особенно неприятно, если вы работаете с нимinit
.Это также работает,
|pipes
конечно, но затем вы снова теряете среду, когда|pipe's
состояние испаряется с его подоболочкой. Опять же, это работает:Сам
sed
оператор работает, удерживая каждую строку в памяти до тех пор, пока не достигнет последней, и тогда он выполняет глобальную обработку замены, заключая в кавычки и вставляя новые строки, где это уместно, путем привязки к нулям. Довольно просто на самом деле.На
dash
картинке вы увидите, что я решил отказаться от \ mess и добавилGNU
конкретную-r
опцию вsed
. Но это только потому, что это было меньше, чтобы печатать. Это работает в любом случае, как вы можете видеть наzsh
картинке.Вот
zsh
:И здесь мы
dash
делаем то же самое:Даже терминальные выходы проходят невредимыми:
источник
/proc/PID/environ
. Таким образом, вопрос в том, что поддерживает Solaris sed - или, если есть/proc/PID/environ
, Solaris , он не использовал, но я способ за кривой на особенностях Solaris, чтобы это могло быть в настоящее время.)sed
требуется для обработки шестнадцатеричной ASCII, из которых нулевой байт является одним. Кроме того, я на самом деле просто подумал, что гораздо проще сделать это до сих пор.\xNN
синтаксис не требуется в POSIX, даже в\OOO
восьмеричном синтаксисе (в строках C и в awk, да, но не в регулярных выражениях sed)./proc/PID/environ
конце концов Solaris не имеет (в нем есть несколько других записей, подобных Linux/proc/PID
, но нетenviron
). Таким образом, портативное решение не обязательно должно выходить за рамки инструментов Linux, то есть GNU sed или BusyBox sed. Оба поддерживают\x00
регулярные выражения, поэтому ваш код настолько переносим, насколько это необходимо (но не POSIX). Это слишком сложно, хотя.источник