Переменные, Переменные среды

              ....... Мир без переменных статичен, движение есть отображение жизни, ее след , если мы хотим моделировать мир нам нужны переменные, как отображения движения и что есть "движение"?  — переход из "возможности" в "действительность" (Аристотель, что спорно, но "красиво")

 Переменная - Variable (computer science)

Переменные интерпретатора (shell) и переменные среды

Чтобы продуктивно работать с интерпретатором shell, нужно гибко манипулировать переменными этого интерпретатора. Переменные интерпретатора shell это наименования (имена), которым присваиваются значения. В качестве значений может выступать имя пути, имя файла, число, и пр., по сути переменная - это контейнер для определенного типа данных, Имя переменной - это ссылка на сохраненное значение, помимо ссылки на саму переменную (в зависимости от контекста, variable - $variable), разделение имени и содержания позволяет использовать имя независимо от  информации, которую оно представляет. В любом случае интерпретатор shell воспринимает присвоенное значение как текстовую строку

Существуют переменные двух типов: переменные интерпретатора shell - локальные переменные и переменные среды (environment variable) - "глобальные". На самом деле имеется четыре типа переменных, но оставшиеся предназначены только для чтения. Эти переменные считаются специальными и применяются при передаче параметров в shell-сценарии. Для наложения ограничений на переменные следует объявлять их с указанием типа: инструкции declare и typeset , однако что работает в sh, в bash работает не так и типы переменных это отдельная тема.

В чем состоят отличия различных интерпретаторов команд (оболочек) ?  <<----примерно ТУТ  и там ---->  bash  csh  ksh  zsh

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

/etc/environment, /etc/profile и ~/.bash_profile или ~/.profile или ~/.bashrc , и другие, в зависимости от установленной системы, все то, что будет относиться к созданию окружения при инициализации системы, см. системные файлы запуска здесь.

Полезно вспомнить про то, что называют; профили пользователей которые следует разделить на       

Глобальный профиль:              (/etc/profile)   

Пользовательский профиль:    (~/.profile;~/.bash_profile; ~/.bash_login; ~/.bash_logout). 

В файлах профиля устанавливаются переменные окружения:

PATH - путь поиска исполняемых файлов, 

USER - имя пользователя, 

HOME - путь к домашнему каталогу. 

............................................................

   /etc/profile  глобальный файл профиля

~/.profile профиль пользователя включает настройки пользователя: файл сценария оболочки, который выполняется автоматически при входе в систему, а также в файлах профиля при желании, можно устанавливать права на доступ к файлам и каталогам по умолчанию, маска режима - umask (user file creation mode mask) ...и многое другое.

~/.bashrc файл ресурсов оболочки (интерпретатора команд), где удобно задать псевдонимы для команд, выполняется только при запуске оболочки из командной строки , то есть в данном случае, Bash (в отличии от глобальных файлов профиля, загружаемых при запуске системы) и содержит дополнительные настройки оболочки.

/etc/bashrc общесистемный,  глобальный файл ресурсов оболочки Bash.

Возможно это хорошая идея, как в Linux заиметь /etc/environment; /etc/profile;, но  не всякая OS это пердусматривает, но всякая *nix система имеет  ~/.profile и что нибудь типа ~/.bashrc и это самый верный способ персонализации окружения, и вообще создание среды окружения задача специфичная как для отдельных "программ", так и для различных ОS.  

Есть не совсем очевидная (для некоторых пользователей ....) разница между профильными файлами .profile и .bashrc по моему определить ее можно так:

UNIX. Профессиональное программирование ----->ст.266

    Среда или окружение (environment) имеет большое значение в UNIX-системах, так как хранит множество настроек как системы в целом, так и отдельных программ. Важной особенностью является то, что при создании дочерний процесс получает локальную копию среды родительского процесса, а, значит, не может изменить напрямую глобальные установки (fork --> exec).

    Среда , окружение представляет собой набор пар: «имя переменной» и «значение переменной», реализация управления которыми возложена обычно на командный интерпретатор. Иными словами, окружение - это набор переменных окружения. Так как существует достаточно большое количество интерпретаторов, синтаксис отличается в зависимости от используемого пользователем. Как «имя», так и «значение» чувствительны к регистру символов, «Имя» обычно указывается в верхнем регистре, использование пробелов недопустимо. Для того, чтобы посмотреть переменные среды,  достаточно выпонить команду env без аргументов, которая выведет переменные окружения и их значения т.е. те, которые будут переданы всем дочерним процессам, начальном наборе запускаемом при регистрации пользователя в системе, для того чтобы посмотреть переменные текущей оболочки  надо воспользоваться командой set.  Возможно удобнее пользоваться понятиями локальной и глобальной среды: переменные текущего интерпретатора  - локальные переменные, environment variable - глобальные переменные, что будет более конкретнее понятия "переменные среды", ниже к сожалению это не везде соблюдается.

Понятие о переменных интерпретатора shell и окружении

Переменные позволяют выполнить настройку среды. Они содержат информацию, которая применяется определенным пользователем. Благодаря этому система получает более подробные сведения о пользователях. Кроме того, переменные используются для хранения констант. Рассмотрим, например, переменную под именем EDITOR. Существует довольно много текстовых редакторов, но как выбрать наиболее подходящий ?, путем присваивания значения  нужного редактора переменной EDITOR, и тогда именно этот редактор будет применяться, когда используется программа cron или другие приложения. Система обращается к значению переменной editor и применяет указанный редактор как заданный по умолчанию (помня разницу между переменными оболочки и переменными окружения).

А вот так объясняется понятие "окружения"  в масштабном эпосе про Гуревича и Мефодия (полная версия которого Здесь ):  "Необходимость в "окружении" обусловлена вот какой задачей. Акт передачи данных от родительского процесса дочернему, и, что еще важнее, системе, должен обладать свойством "атомарности". Если использовать для этой цели файл (например, конфигурационный файл запускаемой программы), всегда сохраняется вероятность, что за время между изменением файла и последующим чтением запущенной программой кто-то - например, другой процесс того же пользователя - снова изменит этот файл). Хорошо бы, чтобы изменение данных и их передача выполнялись одной операцией. Например, завести для каждого процесса такой "файл", содержимое которого, во-первых, мог бы изменить только этот процесс, и, во-вторых, оно автоматически копировалось бы в аналогичный "файл" дочернего процесса при его порождении. Эти свойства и реализованы в понятии "окружение". Каждый запускаемый процесс система снабжает неким информационным пространством, которое этот процесс вправе изменять как ему заблагорассудится. Правила пользования этим пространством просты: в нем можно задавать именованные хранилища данных ( переменные окружения), в которые записывать какую угодно информацию (присваивать значение переменной окружения), а впоследствии эту информацию считывать (подставлять значение переменной), дочерний процесс - точная копия родительского, поэтому его окружение - также точная копия родительского. Если про дочерний процесс известно, что он использует значения некоторых переменных из числа передаваемых ему с окружением, родительский может заранее указать, каким из копируемых в окружении переменных нужно изменить значение. При этом, с одной стороны, никто (кроме системы, конечно) не сможет вмешаться в процесс передачи данных, а с другой стороны, одна и та же утилита может быть использована одним и тем же способом, но в измененном окружении - выдавать различные результаты". 

И похоже все это очень доходчиво, можно добавить, что понимая UNIX как логически стройную систему и опираясь на две фундаментальные абстракции ее слагающие, это понятие файла и процесса (а кто то добавит еще и pipe), пытливый пользователь всегда будет иметь представление о происходящем.

Локальные переменные

Переменные интерпретатора shell (переменные текущей оболочки, что важно) могут использоваться сценариями в период функционирования интерпретатора shell, то есть носят локальный характер для данного процесса. После завершения выполнения интерпретатора (процесса, поскольку оболочка ни что иное как процесс) действие этих переменных прекращается и это то что определяет понятие "локальные переменные" если запускается на выполнение другой процесс или происходит выход из среды интерпретатора команд, текущее значение локальной переменной не сохраняется.. 

Например, локальная переменная <имя_файла> может иметь значение< loops.doc>. Это значение важно для пользователя только во время выполнения текущего интерпретатора команд. Переменные этого типа недоступны для других интерпретаторов shell или процессов, что имеет свои преимущества, придает необходимую гибкость "вычислительному процессу" как таковому. Чтобы просмотреть значения всех переменных интерпретатора, достаточно воспользоваться командой set имея понятие или помня про команду env которая отобразит значения переменнных среды, переменных проще говоря взятых из профильных файлов заданных стартовыми сценариями при загрузке системы и регистрации пользователя.

Присваивание значений переменных

https://ru.wikipedia.org/

http://citforum.ru/programming/shell/

http://www.bash-scripting.ru/abs/

http://vds-admin.ru/shell-scripting/peremennye-i-parametry --->> здесь

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

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

variable   это символическое имя переменной (интерфейс переменной) в то время как 

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

**** Имена переменных, без префикса $, могут использоваться в процессе объявления переменной, то есть когда переменной присваивается определенное значение, при удалении значения переменной, при экспорте и в случаях  когда переменная является названием сигнала. Надо запомнить, что с обеих сторон знака "=" либо есть, либо нет пробелов в зависимости от оболочки. Если значение содержит пробел, заключите все в двойные кавычки. Для переменных интерпретатора shell можно использовать как строчные, так и прописные буквы. 

Различные способы присваивания значений переменным

Чтобы отобразить значение отдельной переменной, достаточно применить команду echo и предварить имя переменной знаком $.

$ name1=111

$ echo $name1

111

$ Name2="111 222 333"

$ echo $Name2

111 222 333

$

Одинарные и обратные кавычки

Одинарные кавычки все заключенное в них интерпретируется "буквально".

Обратные кавычки интересней, обратные кавычки позволяют присваивать переменным данные вывода системных команд. Символы, заключенные в обратные кавычки, воспринимаются интерпретатором shell как системная команда, которую следует выполнить, что очень удобно:

$ xxx=`date`

$ xxxx=date

$ echo $xxxx

date

$ echo $xxx

Tue Jan 11 09:08:01 PM MSK 2022

Переменные можно также комбинировать. Ниже переменной ERROR_MSG присваивается сообщение об ошибке, в котором используется значение переменной cреды LOGNAME, в примере интерпретатор shell сначала выводит текст, затем рассматривает переменную $LOGNAME и отображает ее значение.

$ ERROR_MSG="Sorry this file does not exist user $LOGNAME"

$ echo $ERROR_MSG

Sorry this file does not exist user imint

$

Проверка командой set:

$ set

..........................................

DIRSTACK=()

EDITOR=vim

ERROR_MSG='Sorry this file does not exist user imint'

EUID=1000

GROUPS=()

..........................................

Удаление значения переменной

Если  команда set без аргументов выводит список значений всех переменных, установленных в локальной среде, то чтобы удалить значение переменной, достаточно применить команду unset: unset  имя_переменной

$ echo $ERROR_MSG

Sorry this file does not exist user imint

$ unset ERROR_MSG

$ echo $ERROR_MSG

$

Объединение значений переменных

Чтобы объединить значения переменных, достаточно последовательно расположить переменные:

$ echo $ имя_переменной $ имя_переменной

$ zzz1="1 +"

$ zzz2=2

$ echo $zzz1 $zzz2

1 + 2

$

Проверка на наличие значения переменной (подстановка)

Допустим, что нужно проверить, была ли установлена либо инициализирована переменная. Если это не так, можно туг же воспользоваться другим значением. Формат используемой в этом случае команды будет следующий: {переменная:-значение}

Если переменная установлена, она применяется. Если переменная не установлена, вместо нее используется значение ${переменная:-значение}, например:

$ COLOR=blue

$ echo "Sky is ${COLOR:-gray} today"

Sky is blue today

$

Переменная COLOR имеет значение blue. Когда команда echo выводит на экран значение переменной COLOUR, выполняется проверка, была ли установлена переменная ранее. Если переменная установлена, используется установленное значение, если нет {переменная:-значение}. Выполним сброс значения переменной и рассмотрим результат:

$ COLOR=blue

$ unset COLOR

$ echo "Sky is ${COLOR:-gray} today"

Sky is gray today

$

В приведенном примере переменной не присваивается действительное значение; для присваивания значения следует применить формат: {переменная:=значение}

Рассмотрим более полезный пример, в котором содержится запрос о времени создания платежной ведомости (payroll), и регулярности. Если в обоих случаях при указании времени и типа нажать клавишу [Enter], то значения этих переменных не будут установлены пользователем. В этом случае применяются новые значения, заданные по умолчанию (03:00 и Weekly). Затем значения передаются команде at, что свидетельствует о переносе выполнения задания на более ранний срок.:

$ echo ${RUN_TYPE:=Weekly}

Weekly

echo ${TIME:=03:00}

03:00


$ pg vartest

#!/bin/sh

# vartest

echo "what time do you wish to start the payroll [03:00]:"

read TIME

echo "process to start at ${TIME:=03:00} OK"

echo "is it a monthly or weekly run [Weekly]:"

read RUN_TYPE

echo "Run type is ${RUN_TYPE:=Weekly}"

at -f $RUN_TYPE $TIME # -f Читать задание из файла, а не из стандартного ввода

$

Так будет выглядеть результат, если вы запускаете его, нажимая Enter в обоих полях

$ sh vartest

what time do you wish to start the payroll [03:00]:

##########ENTER#############

process to start at 03:00 OK

is it a monthly or weekly run [Weekly]:

##########ENTER#############

Run type is Weekly

warning: commands will be executed using /bin/sh

job 13 at Sun Aug 2 03:00:00 2015

PS: следует учесть, что используемая в скрипте утилита  at - позволяющая планировать выполнение команд в определенное время (задания, созданные с помощью at, выполняются только один раз), может быть установлена, а может и нет (в зависимости от дистрибютива):

$ which at

$ type at

bash: type: at: not found

При желании можно установить но по скольку из современных дистрибютивов, по соображениям безопасность(видимо) она повсюду вырезана, то будут не большие проблемы в ее совместимости с crontab и systemd: (https://stackoverflow.com/at-command-is-not-executed)

$ sudo apt install at

$ type at

at is /usr/bin/at

$  

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

$ echo "The file is ${FILES:?}"

bash: FILES: параметр null или не установлен

$

Для инициализации переменной значением пустой строки, запись будет такой: переменная=""

$ RUN_TYPE=""

$ echo $RUN_TYPE


Чтобы проверить, содержит ли переменная значение, (а если нет вывести пустую строку) примените следующую команду: {переменная:+значение} {переменная:+""}

$ echo ${ZZZ:+""}


Применение переменных, содержащих аргументы системных команд

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

В примере переменные сохраняют информацию об имени файла необходимую для его копирования.

SOURCE     - путь к файлу passwd

DEST       - получатель файла

В примере обе переменные применяются в команде cp

$ SOURCE="/etc/passwd"

$ DEST="/temp/[имя файла]"

$ cp ${SOURCE} ${DEST}       # =  cp  /etc/passwd   /temp/[имя файла]

Как получить первые n символов переменной в Bash?

https://coderoad.ru/

https://www.linux.org.ru/forum

$ FOO="qwertzuiopasdfghjklyxcvbnm"

$ echo ${FOO:0:10}(man bash,раздел parameter expansion)

qwertzuiop

$ echo $FOO | head -n 1 | cut -c -10

qwertzuiop

$ echo $FOO | head -c 10

qwertzuiop $ 

Переменные ¨только для чтения¨

Если переменной присваивается значение, то может потребоваться, чтобы это значение не изменялось. Для этого достаточно сделать переменную доступной только для чтения. Если пользователь попытается изменить значение, появится сообщение об ошибке, в котором указывается, что данная переменная предназначена только для чтения. В этом случае применяется следующий формат: readonly имя_переменной

$ Start="~/.bin/start.sh"

$ echo $Start

~/.bin/start.sh

$ readonly Start

$ Start="~"

bash: Start: доступная только на чтение переменная

$

Чтобы просмотреть все переменные, которые доступны только для чтения, примените команду readonly.

$ readonly

declare -r 

declare -ir BASHPID

declare -r BASH_COMPLETION_COMPAT_DIR="/etc/bash_completion.d"

declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="11" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")'

declare -r Start="~/.bin/start.sh"

declare -ir UID="1000"

Переменные среды

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

Этими процессами могут быть редакторы, сценарии, приложения. Переменные среды можно устанавливать в командной строке. Однако эти значения не сохраняются после выхода из системы. Поэтому переменные среды инициализируют в пользовательском файле .profile; .bashrc (в зависимости от системы, интерпретатора и тд.)

Если вы внесли изменения в ".profile", то для переноса этих изменений в среду необходимо выполнить этот файл. Для этого можно выйти и заново войти в систему, а можно воспользоваться  командой "." source без выхода из системы, т.е.  $ . .profile - что обычно все и делают.

Администратор системы может установить некоторые переменные среды в системных файлах запуска: /etc/profile, etc/environment .... Поскольку переменные размещаются в профильных файлах, они инициализируются при регистрации в системе. Обычно при обозначении переменных среды используются прописные буквы. В Unix, переменные, созданные в среде родительского процесса не передаются автоматически дочернему. Чтобы переменная, созданная процессом A, была доступна запущенному им процессу B, необходимо перед запуском дочернего процесса B выполнить экспорт данной переменной с помощью команды export. Присваивание значений переменным среды проходит так же, как и в случае с переменными интерпретатора shell.

Пытаясь связать выше сказанное....:

Переменные среды (окружения) затрагивают командную оболочку в целом и влияют на порядок взаимодействия с пользователем.

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

При запуске командного интерпретатора, для него создаются переменные, соответствующие переменным среды (окружения) из ~/.profile и etc/environment либо из etc/profile, ~/bash_profile или ~/.bashrc  в зависимости от установленной системы. см. Системные файлы запуска. Любое изменение переменных окружения заставляет оболочку обновить свои переменные, и все дочерние процессы ( команды, запускаемые из системной оболочки) наследуют это окружение.

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

Экспорт переменных оболочки (команда export)

Переменная оболочки называется локальной, если она известна только той оболочке, которая ее создала. Если вы запустите новую оболочку, то переменные старой оболочки будут ей неизвестны. Если вы хотите, чтобы переменные старой оболочки были известны во вновь открываемых (дочерних) оболочках, экспортируйте переменные, сделав их "глобальными". Сделать локальные переменные глобальными можно с помощью команды export, или экспортируйте(пропишите) их в свой файл .profile или ~/.bashrc  в зависимости от установленной системы, и они будут считаны при запуске. Переменные можно экспортировать в дочерние, но не в родительские оболочки.

Что касается сценариев:

Переменная сценария – это величина, хранящая свое значение на всем протяжении выполнения сценария, поскольку сценарий "асоциирован" с процессом или группой.

Если сценарий меняет переменные окружения, они должны быть экспортированы, т.е передаться окружению, локальному по отношению к сценарию, с помощью команды export.

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

Присваивание значений переменным среды

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

export VARIABLE_NAME=значение 

или:

$ VARIABLE_NAME=значение; export VARIABLE_NAME

Точка с запятой между двумя командами выступает в роли разделителя команд.

Очевидно, что отличие между присваиванием значений переменным локальным и средам в том, что бы пометить их в bash таким образом, что они будут устанавливаться во всех порождаемых процессах, командных оболочках. Это означает, что они обозначены как внешние, экспортированные (export).

К аналогичному результату можно прийти следующим образом:

$ VARIABLE_NAME=значение

$ export VARIABLE_NAME

Удаление значений переменных среды

Чтобы удалить значение переменной, следует применить команду unset.

$ unset MYBIN

$ unset CONSOLE

$ echo $MYBIN $CONSOLE

$

Отображение значений переменных среды

Отображение значений переменных среды выполняется так же, как и в случае с переменными интерпретатора shell:

$ CONSOLE=tty1; export CONSOLE

$ echo $CONSOLE

tty1

$ MYBIN=~/.bin; export MYBIN

$ echo $MYBIN

/home/imint/.bin

Чтобы просмотреть  определенные переменные среды, достаточно воспользоваться командой env.

$ env

........................

SSH_AGENT_PID=2367

......................

CONSOLE=tty1

.....................

USERNAME=imint

........................

MYBIN=/home/imint/.bin

SHLVL=1

$

Встроенные переменные интерпретатора shell

Интерпретатор Bourne shell располагает именами, которые зарезервированы для переменных среды. Эти названия переменных нельзя использовать иначе. Обычно они содержатся в файле /etc/profile. Однако так бывает не всегда, поэтому пользователь может самостоятельно устанавливать значения этих переменных. Ниже приводится перечень переменных, встроенных в интерпретатор shell.

Переменная CDPATH

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

Переменная CDPATH позволит использовать простое имя файла в качестве аргумента  команде cd (change directory), для смены рабочего каталога на каталог указанный в качестве аргумента. При необходимости иметь несколько часто используемых каталогов, редактирование переменной CDPATH ускорит работу, при использовании команды cd с длинными именами для переключения между каталогами на которые она указывает.

$ CDPATH=~:/usr/local:/etc; export CDPATH

$ echo $CDPATH

/home/imint:/usr/local:/etc

$

Попробуем в качестве аргумента команде cd поставит любой каталог находящийся по путям указанным в переменной (не забывая в качестве разделителей путей при их назначении ставит двоеточие)

$ cd .bin

~/.bin $

$ cd conky

/etc/conky $

$ cd apps

/usr/local/apps $ 

Команда cd будет выполнять поиск среди каталогов, заданных с помощью переменной CDPATH. Если нужный каталог найден, именно он становится текущим рабочим каталогом. Примененная без аргументов команда cd возьмет значение из переменной $HOME..??, а может и из /etc/passwd...., но итогом будет переход в домашний каталог. Чтобы изменения остались в окружении после перезагрузки системы отредактируйте файл:

etc/environment

Если использовать пути, как в выше указанном примере, то запись будет примерно такой:

CDPATH="~:/usr/local:/etc"

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

m=/system/zones;export m

[07:25@solaris]~$ m=/system/zones;export m

[07:26@solaris]~$ cd $m

[07:26@solaris]/system/zones$

Если в системе нет etc/environment, добавьте в .profile (выполнить  . .profile):

m=/system/zones;export m

Переменная PS1

Переменные PS1, PS2(Promt String) пример переменных предназначенных специально для bash, они задают его свойства и особенности поведения, переменные хранящие "строку подсказку" выводимую в разных состояниях, PS1 - подсказка которую показывает shell при выводе командной строки, а PS2 - при нажатии Enter.

Основная командная строка включает символ приглашения интерпретатора shell. По умолчанию для основной командной строки используется символ #, а для любой другой командной строки применяется символ $ (если "\$" в bash). В командной строке можно использовать любые символы. Например:

$ PS1="--->>"; export PS1

--->>

--->>

--->>PS1='\@'

03:59

03:40

Символ    Отображение в приглашении

\$              # - если пользователь работает с root-правами, в остальных случаях - $

\w              Путевое имя рабочего каталога

\W             Базовое имя рабочего каталога

\!               Номер текущего события (истории)

\d              Дата в формате неделя, месяц, дата

\h              Имя хоста машины без указания домена

\H             Полное имя хоста машины, включая домен

\u              Пользовательское имя текущего пользователя

\@            Текущее время дня в 12-часовом формате AM/PM

\T             Текущее время дня в 12-часовом формате ЧЧ:ММ:СС

\A             Текущее время дня в 24-часовом формате ЧЧ:ММ

\t              Текущее время дня в 24-часовом формате ЧЧ:ММ:СС

***Date --> https://pubs.opengroup.org/utilities/date.html 

Переменная SHELL

Переменная shell включает сведения об интерпретаторе shell, заданном по умолчанию. Интерпретатор команд обычно указан в файле /etc/passwd. Это значение нельзя отменить, даже если приходится использовать другой интерпретатор команд.

$ echo $SHELL

/bin/bash

$

На ряду с злободневными командами типа: chmod, chown, chgrp в тени остается команда  chsh, позволяющая без лишних движений сменить оболочку используемую для входа в систему, (reboot все равно потребуется) пример:

$ chsh -s /bin/bash (sh, zsh, ksh) $USER 

Переменная TZ

Эта переменная позволяет определить часовой пояс. Значение переменной TZ устанавливает администратор системы.

Переменная EDITOR

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

$ EDITOR=vim; export EDITOR

$ echo $EDITOR

vim

$

Переменная MANPATH

Представляет каталоги, которые включают страницы справочной программы man. Имя каждого каталога отделяется двоеточием.

Переменная REPLY

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

$ type read

read is a shell builtin 

$ read

VARIABLE_read

$ echo $REPLY

VARIABLE_read

$ read aaa

bbb

$ echo $aaa

bbb

$  


Что бы как то подитожить все эти измышления про переменные, можно сказать что вопрос: зачем нужны переменные?, вопрос чисто риторический, куда мы ни посмотри они везде и как же без них, те же "позиционные параметры командной строки" по сути те же переменные, узнать и разбираться в их многообразии похоже можно только практически 

Переменная HOME

Каталог HOME обычно указывается в файле passwd, во втором поле от конца файла. Если переменная установлена, для перехода в каталог НОМЕ можно воспользоваться командой cd.

Переменная IFS - Internal Field Separator

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

IFS=":"

foo="12:34::78"

$ echo $foo

12 34  78

foo=12:34::78

$ echo $foo

12:34::78

Переменная LOGNAME

Переменная содержит регистрационное имя пользователя. Значение этой переменной устанавливается по умолчанию.

Переменная MAIL

Переменная MAIL хранит имя пути доступа и имя файла для вашего почтового ящика. По умолчанию ее значение /vаг/sрооl/mail/<user name>. Интерпретатор shell периодически проверяет почтовый ящик на предмет наличия новых сообщений. Если пользователь получает электронное сообщение, он узнает об этом из командной строки. Если к почтовому ящику имеется другой путь, установите его с помощью переменной mail.

Переменная MAILCHEK

Значение переменной MAILCHEK задается по умолчанию таким образом, чтобы наличие новой электронной почты проверялось каждые 60 секунд. Если электронную почту следует запрашивать реже, установите свое значение 120,180,240..итд.

Переменная MAILPATH

Применяйте переменную MAILPATH, если вы располагаете более чем одним почтовым ящиком. При установке значения этой переменный перекрывается значение переменной MAIL.


Переменная PATH

Переменная PATH хранит сведения о каталогах, где находятся выполняемые команды или сценарии, по этой причине исполняемые файлы невозможно запускать просто по имени, если они лежат в текущем каталоге, и текущий каталог не входит в PATH. Важно, чтобы  последовательность перечисления каталогов указывалась правильно, поскольку при обращении к этой переменной существенно сокращается время выполнения команды или сценария. Например, если в каком-либо каталоге нет заданной команды, то не следует его просматривать. Перечень включает каталоги, отсортированные по частоте применения. Сначала указываются наиболее часто применяемые каталоги, а затем те из них, которые применяются реже всего. Если нужно найти текущий рабочий каталог, то независимо от места его нахождения используйте точку, рекомендуется не включать точку в переменную PATH, чтобы избежать случайного исполнения скриптов их текущей директории, поскольку точка есть синоним команды source.

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

Не обязательно, но вероятно будет удобно если вы занимаетесь написанием и отладкой скриптов завести отдельную директорию например: ~/scripts или где удобнее и безопаснее, и прописать ее в PATH , отредактировав etc/environment, не забывая разделители путей (:) 

Например глобально (etc/environment): PATH="~/scripts:/usr/local/sbin:................."  

(нужен root) изменить переменную среды

Изменить до перезагрузки: $ export PATH ="~/scripts:/usr/local/sbin:................." 

Или так: $ export PATH=$PATH:~ - добавить к существующему пути поиска исполняемых файлов, переменной PATH домашний каталог

$ echo $PATH

/usr/local/sbin:........:/home/user


[19:02@solaris]~ # echo ${PATH:?}  # = echo $PATH

/usr/sbin:/usr/bin:/hd/bin:/opt/sfw/bin:/opt/csw/bin:/home/user

[19:03@solaris]~ #

*** В Linux …

Чтобы сообщить Linux, что в строках предполагается применение управляющих символов, команду echo следует вводить как "echo -e .....".

PS1=`[\A@\h]\w \$ `   <<--- в профильные файлы

PS1="[\A]\u\$ "

Переменная PS2

Значение этой переменной задает вид вторичной командной строки. По умолчанию этот тип командной строки определяется символом >,так же используют:@, 1:(в зависимости от дистрибютива в случае Linux). Подобная командная строка используется при выполнении многострочной команды или в случае, когда размер команды превышает длину строки.

$ for loop in *             # цикл FOR

 1:

 1:

 1:do

 1:echo $loop

 1:

Переменная TERMINFO

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

Переменная TERM

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

$ echo $TERM

xterm-256color

$

Переменная PWD

Эта переменная представляет имя пути доступа для текущего каталога. Обычно значение переменной изменяется всякий раз при выполнении команды cd.

Переменная PAGER

Данная переменная хранит сведения о командах программы постраничной разбивки. К подобным командам можно отнести, например: pg, more. Система проверяет значение этой переменной, когда пользователь выполняет просмотр страниц man, по умолчанию не задан (наприер в Arch), но ни кто не мешает задать, например less.

Переменная LPDEST или переменная PRINTER

Эта переменная представляет имя принтера, заданного по умолчанию. При выводе на печать сохраняется имя принтера, заданное пользователем. 

Выше приведенные переменные, это не полный список встроенных переменных UNIX/LINIX систем, как и назначение других часто употребляемых, например переменная LANG, все они достойны описания, но не здесь.

$ echo $DIRSTACK

/home/user - содержимое вершины стека каталогов

$ echo $EUID

1000 - Эффективный UID

$ echo $UID

1000 - реальный идентификатор

$ echo $FUNCNAME

 - имя текущей функции в скрипте

$ echo $GROUPS

1000 - групы к которым принадлежит текущий пользователь

$ echo $HOSTTYPE

x86_64 - архитектура машины

$ echo $OLDPWD

 - прежний рабочий каталог

$ echo $OSTYPE

linux-gnu - тип ОС

$ echo $PPID

10655 - идентификатор родительского процесса

$ echo $SECONDS

11926 - время работы скрипта

$ echo $#

 - общее количество параметров переданных скрипту

$ echo $*

 - все аргументы переданыне скрипту(выводятся в строку)

$ echo $@

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

$ echo $!

 - PID последнего запущенного в фоне процесса

$ echo $$

13081 - PID  скрипта

$

....и тд.!

Применение команды set

При установке переменных команда в bash: set FOO=foo делает то же самое, что и FOO=foo.

Eсть несколько опций которые не могут быть экспортированы при помощи export , и поэтому они должны быть заданы в ~/.bashrc и в вашем профиле последовательно. Эти опции настраиваются при помощи встроенной команды set:

Экспорт переменных среды можно задать при установке этих переменных в файле $HOME .profile.: команда set с параметром ¨¨ в виде ¨set -а¨. Эго означает, что выполняется экспорт всех переменных. Не применяйте этот метод при работе с файлом /etc/profile. Данный метод применим только при работе с файлом $HOME .profile.

Команда set без аргументов показывает переменные текущей оболочки и их значения как и команда declare.

env -- покажет переменные окружения, глобальные переменные.

Экспорт переменных в дочерние процессы

Рассмотрим пример, сценария, который вызывает другой сценарий. Вызываемый сценарий фактически и является дочерним процессом.

Рассматриваемый листинг включает два небольших сценария под именами father и child. Сценарий father задает переменную с именем FILM, значение которой "A Few Fool Men". Эта переменная отображается на экране, затем вызывается другой сценарий под названием child.

Данный сценарий отображает переменную film из первого сценария. Перед отображением на экране значением переменной FILM во второй раз в сценарии child FILM становится "Too Boob".

#!/bin/sh

#father 

#сценарий родитель 

echo "===== Я father ====="

FILM="A Few Fool Men"

echo "очень нравится фильм :$FILM"

echo "===== END fathrt ====="

# вызов сценария child

sh child

#!/bin/sh

#child 

#сценарий потомок

echo "===== вызывается из родителя...я child ==="

echo "хороший фильм :$FILM"

FILM="Too Boob"

echo "еще нравится :$FILM"

echo "===== END child ====="

Результат сценария:

$ sh father

Я father 

очень нравится фильм :A Few Fool Men

END fathrt 

вызывается из родителя...я child 

хороший фильм :

еще нравится :Too Boob

END child 


Сценарий child не может возвратить переменную FILM, поскольку эта переменная не экспортирована в сценарий father.Теперь, если команду export добавить в сценарий father, сценарий child получит всю информацию о переменной FILM.

#!/bin/sh

#father1 

#сценарий родитель 

echo "===== Я father1 ====="

FILM="A Few Fool Men"

echo "очень нравится :$FILM"

echo "===== END ====="

# вызов сценария child

# сначала экспортируйте переменную

export FILM

sh child

Результат сценария:

$ sh father1

Я father1 

очень нравится :A Few Fool Men

END 

вызывается из родителя...я child 

хороший фильм :A Few Fool Men

еще нравится :Too Boob

END child 

После того как команда export включена в состав сценария, можно выполнить произвольное число процессов. И всем этим процессам известно о наличии переменной FILM. Нельзя выполнять экспорт переменных из дочерних процессов в родительский процесс, однако с помощью изменения направления этого можно добиться.

PS: Подстановка переменных в строку адреса

Например:

$  /$$

$  /home/$USER

И на первый взгляд все это .....не имеет смысла, но только на первый

$ echo /home/$USER

/home/user

$ printf /home/$USER

/home/user$ 

$ echo ls -lah /proc/$$/fd/ 

ls -lah /proc/19410/fd/

.....тоже самое с подстановкой в массивы

В общем и целом так:

При анализе команды оболочка разделяет строку ввода и выполняет подстановку псевдонимов. Затем, перед запуском команды, выполняется подстановка переменных. Подстановка выполняется при обнаружении в строке символа $. Однако если за этим символом следует пробел, знак табуляции или символ новой строки, то подстановка не выполняется. Если перед знаком $ стоит символ \, то подстановка также отменяется, за исключением следующих двух случаев:


  Команда заключена в двойные кавычки (" "). В этом случае оболочка всегда выполняет подстановку.

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


https://www.ibm.com/docs/ru/shell-variable-substitution- 


Конкотенация строки

При конкатенации то есть объединении строки сдержащей переменные следует использовать фигурные скобки например:

$ echo ${USER}-on-${HOSTNAME}

user-on-cranchbang

$ con=${USER}-on-${HOSTNAME}

$ echo $con

user-on-cranchbang

$ echo "My PWD:${PWD}--My Shell: ${SHELL}---My Terminal:${TERM}"

My PWD:/home/user--My Shell: /bin/bash---My Terminal:xterm-256color

....это не единственный способ конкатенации, как и не единственный пример.ВВ


PS: В переменные можно запросто записывать команды, вопрос лишь зачем?

$ ccc="ls -l"

$ echo $ccc

ls -l

$ $ccc

total 21472

-rw-r--r-- 1  21846836 Dec 28  2019 4kvideodownloader_4.4.11-1_amd64.deb

-rw-r--r-- 1         0 Apr 21 13:30 ask

-rw-r--r-- 1 l      241 Dec 11 15:52 awk

drwxr-xr-x 2      4096 Sep 26  2023 backup

drwxr-xr-x 2      4096 Sep 26  2023 bin

..............................................................