Переменные, Переменные среды
....... Мир без переменных статичен, движение есть отображение жизни, ее след , если мы хотим моделировать мир нам нужны переменные, как отображения движения и что есть "движение"? — переход из "возможности" в "действительность" (Аристотель, что спорно, но "красиво")
Переменная - 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 по моему определить ее можно так:
.profile — после регистрации в системе и выполнения /etc/profile пользователь "локализуется" и переходит в начальный каталог $HOME, выполнение ~/.profile это следующий этап локализации, локальный ~/.profile предназначен для вещей, которые не посредственно не связаны с Bash(как и любой другой оболочкой), например переменные окружения PATH,EDITOR, свои аббревиатуры ..и тд, это дополнительный сервис для пользователя, дополнительная возможность обозначить свои предпочтения, кроме того файл .profile читается многими оболочками при отсутствии их собственных конфигурационных файлов(cshrc, kshrc ...), в общем и целом это можно назвать "персонализация окружения", кроме того считывается системой прежде .bashrc. Если имеется файл .profile, система использует его в качестве исходного файла и обращается к существующему(выбранному) интерпретатору shell. "Теоритически" если раздражает, то его можно и удалить....
.bashrc — это как раз конфигурационный файл Bash (что более чем очевидно из названия), предназначен для настройки использования интерактивного Bash, например псевдонимов Bash, PS1,...и тд.
UNIX. Профессиональное программирование ----->ст.266
Среда или окружение (environment) имеет большое значение в UNIX-системах, так как хранит множество настроек как системы в целом, так и отдельных программ. Важной особенностью является то, что при создании дочерний процесс получает локальную копию среды родительского процесса, а, значит, не может изменить напрямую глобальные установки (fork --> exec).
Среда , окружение представляет собой набор пар: «имя переменной» и «значение переменной», реализация управления которыми возложена обычно на командный интерпретатор. Иными словами, окружение - это набор переменных окружения. Так как существует достаточно большое количество интерпретаторов, синтаксис отличается в зависимости от используемого пользователем. Как «имя», так и «значение» чувствительны к регистру символов, «Имя» обычно указывается в верхнем регистре, использование пробелов недопустимо. Для того, чтобы посмотреть переменные среды, достаточно выпонить команду env без аргументов, которая выведет переменные окружения и их значения т.е. те, которые будут переданы всем дочерним процессам, начальном наборе запускаемом при регистрации пользователя в системе, для того чтобы посмотреть переменные текущей оболочки надо воспользоваться командой set. Возможно удобнее пользоваться понятиями локальной и глобальной среды: переменные текущего интерпретатора - локальные переменные, environment variable - глобальные переменные, что будет более конкретнее понятия "переменные среды", ниже к сожалению это не везде соблюдается.
Понятие о переменных интерпретатора shell и окружении
Переменные позволяют выполнить настройку среды. Они содержат информацию, которая применяется определенным пользователем. Благодаря этому система получает более подробные сведения о пользователях. Кроме того, переменные используются для хранения констант. Рассмотрим, например, переменную под именем EDITOR. Существует довольно много текстовых редакторов, но как выбрать наиболее подходящий ?, путем присваивания значения нужного редактора переменной EDITOR, и тогда именно этот редактор будет применяться, когда используется программа cron или другие приложения. Система обращается к значению переменной editor и применяет указанный редактор как заданный по умолчанию (помня разницу между переменными оболочки и переменными окружения).
А вот так объясняется понятие "окружения" в масштабном эпосе про Гуревича и Мефодия (полная версия которого Здесь ): "Необходимость в "окружении" обусловлена вот какой задачей. Акт передачи данных от родительского процесса дочернему, и, что еще важнее, системе, должен обладать свойством "атомарности". Если использовать для этой цели файл (например, конфигурационный файл запускаемой программы), всегда сохраняется вероятность, что за время между изменением файла и последующим чтением запущенной программой кто-то - например, другой процесс того же пользователя - снова изменит этот файл). Хорошо бы, чтобы изменение данных и их передача выполнялись одной операцией. Например, завести для каждого процесса такой "файл", содержимое которого, во-первых, мог бы изменить только этот процесс, и, во-вторых, оно автоматически копировалось бы в аналогичный "файл" дочернего процесса при его порождении. Эти свойства и реализованы в понятии "окружение". Каждый запускаемый процесс система снабжает неким информационным пространством, которое этот процесс вправе изменять как ему заблагорассудится. Правила пользования этим пространством просты: в нем можно задавать именованные хранилища данных ( переменные окружения), в которые записывать какую угодно информацию (присваивать значение переменной окружения), а впоследствии эту информацию считывать (подставлять значение переменной), дочерний процесс - точная копия родительского, поэтому его окружение - также точная копия родительского. Если про дочерний процесс известно, что он использует значения некоторых переменных из числа передаваемых ему с окружением, родительский может заранее указать, каким из копируемых в окружении переменных нужно изменить значение. При этом, с одной стороны, никто (кроме системы, конечно) не сможет вмешаться в процесс передачи данных, а с другой стороны, одна и та же утилита может быть использована одним и тем же способом, но в измененном окружении - выдавать различные результаты".
И похоже все это очень доходчиво, можно добавить, что понимая UNIX как логически стройную систему и опираясь на две фундаментальные абстракции ее слагающие, это понятие файла и процесса (а кто то добавит еще и pipe), пытливый пользователь всегда будет иметь представление о происходящем.
Локальные переменные
Переменные интерпретатора shell (переменные текущей оболочки, что важно) могут использоваться сценариями в период функционирования интерпретатора shell, то есть носят локальный характер для данного процесса. После завершения выполнения интерпретатора (процесса, поскольку оболочка ни что иное как процесс) действие этих переменных прекращается и это то что определяет понятие "локальные переменные" если запускается на выполнение другой процесс или происходит выход из среды интерпретатора команд, текущее значение локальной переменной не сохраняется..
Например, локальная переменная <имя_файла> может иметь значение< loops.doc>. Это значение важно для пользователя только во время выполнения текущего интерпретатора команд. Переменные этого типа недоступны для других интерпретаторов shell или процессов, что имеет свои преимущества, придает необходимую гибкость "вычислительному процессу" как таковому. Чтобы просмотреть значения всех переменных интерпретатора, достаточно воспользоваться командой set имея понятие или помня про команду env которая отобразит значения переменнных среды, переменных проще говоря взятых из профильных файлов заданных стартовыми сценариями при загрузке системы и регистрации пользователя.
Присваивание значений переменных
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://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 в зависимости от установленной системы. см. Системные файлы запуска. Любое изменение переменных окружения заставляет оболочку обновить свои переменные, и все дочерние процессы ( команды, запускаемые из системной оболочки) наследуют это окружение.
Пространство, выделяемое переменным окружения, ограничено. Создание слишком большого количества переменных окружения или одной переменной, которая занимает слишком большое пространство, может привести к возникновению определенных проблем.
Команда env (environment) позволит просмотреть все переменные среды, переменные доступные для всех дочерних процессов.
Команда set покажет переменные текущей оболочки, локальные переменные, важная особенность в контексте сценария, по скольку можно задать переменные не влияющие на переменные других оболочек или процессов.
Экспорт переменных оболочки (команда 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
..............................................................