Як показати поточне значення змінної середовища?


24

Коли я перевіряю навколишнє середовище моєї системи, з’явиться багато змінних умов навколишнього середовища. Як я можу просто шукати певну змінну?

Книга, яку я читаю, говорить:

Іноді кількість змінних у вашому оточенні зростає досить великою, настільки, що вам не хочеться бачити всі значення, що відображаються, коли вас цікавить лише одна. У такому випадку ви можете використовувати echoкоманду, щоб показати поточне значення змінної середовища.

Як це зробити в терміналі Linux?

Відповіді:


25

Просто:

echo "$VARIABLENAME"

Наприклад, для змінної середовища $HOMEвикористовуйте:

echo "$HOME"

Потім друкується щось подібне до:

/home/username

Редагувати : згідно з коментарем Стефана Шазеласа , можливо, буде краще, якщо ви використовуєте printenvзамість echo:

printenv HOME

4
Ви забули лапки (якщо тільки ви не маєте на увазі синтаксис zsh чи rc / es). echo- це поганий вибір команди, оскільки він міг би перетворити вміст змінної. Він виведе вміст параметра оболонки тим самим іменем. Це не обов'язково те ж саме при використанні Bourne оболонки або окр вари , як 1, *наприклад. І ви не можете використовувати такий підхід для env vars, ім'я яких недійсне як ім'я змінної оболонки.
Стефан Хазелас

5
Також зауважте, що якщо є декілька записів оточення з однаковою назвою (ОК, патологічний випадок), який ви отримаєте, залежить від оболонки (як правило, першої або останньої). printenv VARвідобразить їх усі (принаймні, для реалізації GNU).
Стефан Шазелас

9

Виконуючи:

printenv

Ви побачите всі змінні середовища. Для отримання додаткової інформації ви можете подивитися:

https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-linux-vps


2
Щоб наблизитись до фактично відповіді на питання, printenv variablenameвідобразиться лише названа змінна; наприклад, printenv  HOMEзробить приблизно те саме, що і echo  "$HOME".
G-Man каже: "Відновіть Моніку"

5

Важливо розуміти, що кожен процес має свій набір змінних середовища.

Коли процес викликає fork()системний виклик, створюється другий процес ( дочірня ), ідентичний першому ( батьківський ) (ця копія включає оточення, яке знаходиться трохи вище стека (або трохи нижче, залежно від того, як ви думаєте про стеки :-)- але в Unix / Linux стек росте вниз від високих адрес).

Зазвичай дочірній процес потім викличе execve()системний виклик, який викине все у свою (віртуальну) пам’ять та реконструює його з розділів коду та даних у вказаному бінарному файлі.

Однак, коли він реконструює стек, він копіює обстановку та аргументи, передані execve()на стек спочатку (у цьому порядку), перш ніж викликати main()функцію (велика робота виконується в crt0коді завантажувальної програми після execve()повернення (до запису точка, вказана у двійковій)).

У execve()бібліотеці C є обгортки для системного виклику, які передаватимуть поточне середовище (тобто копію батьківського середовища), а не абонент, який надає це (таким чином дитина наслідує батьківське оточення) - див environ(7).

Спробуйте виконати команду (як root) ps axeww | less... це покаже вам середовище для всіх процесів! Цікавим є процес id 1 (тобто initпроцес - перший процес, створений ядром під час завантаження).

Якщо ви хочете подивитися на середовище для певного процесу (а ви знаєте, що це ідентифікатор процесу), спробуйте виконати команду cat /proc/<PID>/environ(замінивши <PID>ідентифікатором процесу).

Зауважте, що якщо у процесу достатньо привілеїв, він може переписати власний стек, що може ускладнити пізнання того, що його середовище - ви побачите деякі демонові процеси на зразок цього у виводі ps.

Зрештою, вся ця вафля зводиться до того, що @chaos сказав вище, якщо ви хочете переглянути поточне значення певної змінної середовища у вашому процесі оболонки, просто скористайтеся командою (вбудована) echo "$<NAME>"(замінивши <NAME>на ім'я змінна середовище, яка вас цікавить) ... просто пам’ятайте, що одна і та ж змінна може мати інше значення або взагалі не існувати в іншому процесі.


1
(1) Зауважте, що eопція psта /proc/…/environспеціальний файл може існувати не у всіх системах. (2) AFAIK, кожен процес Unix має право переписати свій стек і змінити змінні середовища. (3) Для більшого обговорення див. До кого належать змінні середовища? (на Супер Користувача ).
G-Man каже: "Відновіть Моніку"

У мене в голові було те, що деякі системи мали спосіб запобігти непривілейованому процесу "приховувати" свої аргументи командного рядка та оточення, наприклад, від запуску root ps... але тепер, коли ви виділили цю точку, я не можу згадати, чому я думав, що.
Мюррей Дженсен

@MurrayJensen, згідно з деякими дискусіями щодо високоголосного питання, яке я запитав про "curl", приховуючи свої аргументи в ps - це не визначено в POSIX, чи PS повертає аргументи, як спочатку передано в процес, або копію, яку процес може змінити після нього почався. Якась система (я думаю, Solaris ??) показує оригінальні аргументи, незважаючи ні на що. (Ось посилання.) Це, можливо, було те, про що ти думав. :)
Wildcard

Бінго! Так, звичайно, Соларіс робить це "правильно" :-) Дякую за оновлення ...
Мюррей Дженсен


1

якщо вам доведеться встановити багато варіантів:

  ( set -o posix ; set ) | sort >~/vars.before

після їх встановлення:

  ( set -o posix ; set ) | sort >~/vars.after

ніж відобразити встановлене:

  comm -3 ~/vars.before ~/vars.after | perl -ne 's#\s+##g;print "\n $_ "'

Таким чином, ви незабаром опинитесь, працюючи з декількома наборами варіантів оболонок, попередньо визначеними у файлах cnf, що в поєднанні з tmux зробить вас майстром управління конфігурацією в середовищі оболонки:

  # ---------------------------------------------------------
  # cat cnf/qto.dev.host-name.cnf
  # [MainSection]
  # postgres_db_name     = dev_qto
  # postgres_db_host     = host-name
  #
  # call by: doParseCnfEnvVars cnf/qto.dev.host-name.cnf
  # ---------------------------------------------------------
  doParseCnfEnvVars(){

     cnf_file=$1;shift 1;
     test -z "$cnf_file" && echo " you should set the cnf_file !!!"

     INI_SECTION=MainSection

     ( set -o posix ; set ) | sort >~/vars.before

     eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
        -e 's/#.*$//' \
        -e 's/[[:space:]]*$//' \
        -e 's/^[[:space:]]*//' \
        -e "s/^\(.*\)=\([^\"']*\)$/export \1=\"\2\"/" \
        < $cnf_file \
        | sed -n -e "/^\[$INI_SECTION\]/,/^\s*\[/{/^[^#].*\=.*/p;}"`

     # and post-register for nice logging
     ( set -o posix ; set ) | sort >~/vars.after

     echo "INFO added the following vars from section: [$INI_SECTION]"
     comm -3 ~/vars.before ~/vars.after | perl -ne 's#\s+##g;print "\n $_ "'
  }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.