Семь неожиданных переменных Bash

Original author: Ian Miell
  • Translation
  • Tutorial
Продолжая серию заметок о менее известных функциях bash, покажу вам семь переменных, о которых вы могли не знать.

1) PROMPT_COMMAND


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

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

Попробуйте запустить это в новом шелле, и увидите, что произойдёт с сессией:

$ PROMPT_COMMAND='echo -n "writing the prompt at " && date'

2) HISTTIMEFORMAT


Если запустить history в консоли, вы получите список команд, ранее выполненных под вашей учётной записью.

$ HISTTIMEFORMAT='I ran this at: %d/%m/%y %T '

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

1871  I ran this at: 01/05/19 13:38:07 cat /etc/resolv.conf
1872  I ran this at: 01/05/19 13:38:19 curl bbc.co.uk
1873  I ran this at: 01/05/19 13:38:41 sudo vi /etc/resolv.conf
1874  I ran this at: 01/05/19 13:39:18 curl -vvv bbc.co.uk
1876  I ran this at: 01/05/19 13:39:25 sudo su -

Форматирование соответствует символам из man date.

3) CDPATH


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

Как и PATH, переменная CDPATH представляет собой список путей, разделённых двоеточием. Когда вы запускаете команду cd с относительным путём (т. е. без слэша в начале), по умолчанию оболочка ищет в вашей локальной папке соответствующие имена. CDPATH будет искать в путях, которые вы дали для каталога, куда хотите перейти.

Если установить CDPATH таким образом:

$ CDPATH=/:/lib

а затем ввести:

$ cd /home
$ cd tmp

то вы всегда попадёте в /tmp независимо от того, где находитесь.

Однако осторожно, потому что если не указать в списке локальную (.) папку, то вы не сможете создать любую другую папку tmp и перейти к ней, как обычно:

$ cd /home
$ mkdir tmp
$ cd tmp
$ pwd
/tmp

Упс!

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

Моя устанавливается начальной точкой:

CDPATH=.:/space:/etc:/var/lib:/usr/share:/opt

4) SHLVL


Вы когда-нибудь задумывались, ввод exit выведет вас из текущей оболочки bash в другую «родительскую» оболочку или просто полностью закроет окно консоли?

Эта переменная отслеживает, насколько глубоко вы вложены в оболочку bash. Если создать новый терминал, то он установлен на 1:

$ echo $SHLVL
1

Затем, если запустить другой процесс оболочки, число увеличивается:

$ bash
$ echo $SHLVL
2

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

5) LINENO


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

$ bash
$ echo $LINENO
1
$ echo $LINENO
2

Это чаще всего используется при отладке скриптов. Вставляя такие строки, как echo DEBUG:$LINENO, вы можете быстро определить, где в скрипте вы находитесь (или нет).

6) REPLY


Если, как я, вы обычно пишете такой код:

$ read input
echo do something with $input

то может стать сюрпризом, что не нужно вообще беспокоиться о создании переменной:

$ read
echo do something with $REPLY

Это делает то же самое.

7) TMOUT


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

Если ничего не вводится в течение установленного количества секунд, происходит выход из оболочки.

То есть это альтернатива sleep 1 && exit:

$ TMOUT=1

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 32

    +1

    Я плохой линуксоид если не знал ни про одну из этих возможностей?

      +5
      Нет. Вы просто не читали man bash. Оно вообще занятное — массивы там всякие, сокеты, хитрые подстановки переменных.
      • UFO just landed and posted this here
          0

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

            +5
            Как человек знающий-таки bash (и даже эти переменные)… могу вас только поддержать.

            bash — это ужасная вещь. Он начала создаваться ещё в 70е, когда о безопасности никто не думал, а когда начали думать — то добавили костылей. Что при этом не удалось сделать — так это сделать так, чтобы простые методы были бы безопасны.

            В результате любую задачу в bash можно сделать 10 разными способами из коготорых 9 простых — на самом деле не всегда работают.

            Использовать язык, в котором такого количества мин нету где возможно — очень разумное решение…
          +12
          Хороший линуксоид — не тот, кто всё знает, а тот, кто каждый день учится :)
          +11
          Это похоже на путаницу, которую я почувствовал, когда понял, что локальная папка не была включена в более знакомую переменную PATH… но вы должны сделать это в переменной PATH, потому что вас могут обмануть, запустив фейковую команду из какого-нибудь скачанного кода.

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


          На всякий случай поясняю о чем тут на самом деле речь: нельзя добавлять. в PATH, поскольку из-за этого могут переопределиться базовые команды шелла, как случайно, так и намеренно из-за действий злоумышленника. Так, вызывая ls, хочется быть уверенным что это именно /bin/ls, а вовсе не ./ls

            –22
            семь переменных, десять ядов, эксперты назвали пять продуктов вызывающих пригорание.
            просить убавить кликбейтное давление смысла нет?
            как ощущать себя товаром и продолжать получать удовольствие?
              +1
              Радикально менять название невозможно, поскольку это перевод.

              Что не так с заголовком этого текста?

              Предположим, это была бы написанная с нуля статья. Какое бы вы предложили название для неё?
                –6
                Интереса ради погуглил clickbait bingo.
                Из четырех слов заголовка два оттуда.
                  +4

                  Так вы предложите альтернативу то.

                  • UFO just landed and posted this here
                      0

                      Но вы не упомянули что речь про, так сказать, системные переменные bash.

                      • UFO just landed and posted this here
                        +14

                        Вот это точно кликбейт, когда из заголовка не ясен смысл, и приходится открывать статью чтоб разобраться, при том что тема интересная. А так всё ясно и понятно. Нормальный заголовок.

                +1

                Я давно перешел на fish. Переучивание было немного утомительным. Некоторые вещи работают не так как в bash/zsh, и знания, за 20+ лет пробороздившие мозг, периодически приводят к попыткам написать как в bash.


                Но одна вещь, которая вымораживает и из-за которой нет ни малейшего желания возвращаться. bash теряет историю. Да, у них в ChangeLog как минимум однажды писали, что эта проблема исправлена. Нет, не исправлена. Какие бы настройки истории я не использовал, рано или поздно возникает ситуация, когда я набираю Ctrl-R ansible-, и не вижу ровным счетом ничего. А потом гляжу в историю, и вижу, что она в очередной раз обнулилась. Обычно это случается в самый неподходящий момент, когда ты пытаешься срочно что-то починить или задеплоить.


                За много лет регулярные полные и частичные потери истории так меня достали, что я поклялся никогда не использовать bash в интерактивном режиме. Скрипты продолжаю писать на нем, так как он есть в каждой системе по умолчанию, даже в Windows уже.

                  +1
                  Не всегда так просто можно поменять shell, зачастую есть корпоративный стандарт, а какой-нибудь fish вообще не установлен. История да, это проблема в bash. Я решил её для себя сохраняя в файл, можно даже после каждой команды используя упомянутый тут PROMPT_COMMAND. А потом ещё и делая бакап этих файлов. Так что, не обязательно утомительно переучиваться. Плохо это или хорошо, но bash есть везде. Ну почти везде, не считая совсем урезанных версий на контроллерах.
                    +1
                    Я решил её для себя сохраняя в файл, можно даже после каждой команды используя упомянутый тут PROMPT_COMMAND.

                    А как?
                      0
                      У меня пока прижился вот такой вариант, немного сложный, но для меня работает.
                      Тут синхронизируется история между всеми сессиями на хосте (это упрощённая версия, на самом деле синхронизируется история для всех сессий с одной домашней директорией, например хомяк на NFS)
                      Последняя строка срабатывает при каждом логине это «очистка» истории от «мусора» и не обязательна.
                      export HISTCONTROL=ignoreboth:erasedups
                      export PROMPT_COMMAND="history -n; history -w; history -c; history -r"
                      TMPFILE=$(mktemp); tac "${HISTFILE}" | sed -e 's/[[:space:]]*$//' | awk '!x[$0]++' | tac > "${TMPFILE}" ; cat "${TMPFILE}" > "${HISTFILE}" ; rm "${TMPFILE}"; unset TMPFILE
                      

                        0
                        У меня в PROMPT_COMMAND было, оказывается, добавлено «history -a», но все равно не работало — между разными сессиями не синхронизировалось. Попробовал заменить на ваш вариант.
                    +1
                    Для меня оказалось проще перейти на zsh. В нём после настройки с история ведёт себя хорошо, есть фичи, которых в баше не хватает, а синтаксис после bash гораздо привычнее, чем у fish.
                      –4
                      Хранение истории в bash (точнее, в общем readline) действительно ужасно.
                      Это как раз то место, куда напрашивается применить sqlite :)
                        0
                        > он есть в каждой системе по умолчанию, даже в Windows уже.

                        А вот это спорное утверждение. В бсд, например, по умолчанию нету, пока не вытянется с чем-нибудь по зависимостям. Более того, /bin/sh там ВНЕЗАПНО действительно указывает на sh.
                        Но это ещё ладно, его, неожиданно, по дефолту нету в Убунте, а под его именем скрывается dash, который хоть и совместим с башем в большей части, но бывают сюрпризы (иначе откуда бы я узнал, что там на самом деле не баш?).
                        Ну и да, в эмбеддед обычно бизибокс, который тоже не совсем баш.
                        Вообще, ситуация с этими подменами маразмотична, ИМХО, а тема башизмов давно избита. Поэтому я лично никогда не буду использовать эти 'неожиданные' переменные, дабы не выстрелить себе в ногу. И вообще, писать предпочитаю на sh.
                        PS: в интерактивной режиме баша ещё раздражает например, что по умолчанию стрелки вверх/вниз тупо листают историю, а pgup/pgdown работают не везде, и что ^W стирает весь путь целиком. Поэтому всю жизнь пользовался tcsh, zsh или fish.
                        +6
                        Почему неожиданных то? Редко используемых — возможно. Что неожиданного в том, что есть в man bash (даже то, что его до конца не читают — это ожидаемо ;))? Если переменная PROMPT_COMMAND указывает, какую команду использовать при отображении приглашения — это ожидаемо. Вот если бы эта переменная включала, к примеру, debug mode — это было бы действительно неожиданно.
                          +3

                          10 лет на Линукс и с bash, а они продолжают меня удивлять. Спасибо за перевод, многое узнал впервые. Уж гораздо интереснее, чем типичные "n лайфхаков в командной строке", где в 100500-тый раз опишут что-то вроде Ctrl+R или "cd -"

                            +3
                            Спасибо за cd -
                              0
                                0

                                (Уже не про bash) А есть ещё и git checkout -

                                  0

                                  И git merge -, что в паре с checkout вообще офигенно!

                              +3
                              Не считаю себя крутым линуксоидом, но о трёх возможностях знал. Тут просто как повезёт: нужно будет — узнаешь, если не нужно будет, то и не будешь об этом знать. Хотя кому-то явно будет полезно.
                                +4
                                CDPATH может испортить не только настроение, но и сборку средствами make, например
                                  0
                                  autojump намного интереснее и приятнее CDPATH — и кстати использует описанный выше PROMPT_COMMAND

                                  Only users with full accounts can post comments. Log in, please.