Использование bash completion в командной строке, собственных скриптах и приложениях. Часть 1

    Часть 2

    Системный администратор — человек ленивый. Обычно он старается сделать максимум работы, приложив минимум усилий, а для этого зачастую требуется автоматизировать многие рутинные процедуры. Например — набор полных имен хостов при создании ssh-соединения, или же длинных аргументов некоторых команд :)

    Сегодня я попробую рассказать про использование такого функционала шелла как bash completion.

    Итак, почти любая оболочка по умолчанию умеет добавлять пути к файлам и директориям:

    root@mould:~# mkdir very_long_dir_name
    root@mould:~# cd ve[Tab]
    root@mould:~# cd very_long_dir_name/


    bash (в моем случае) после нажатия клавиши Tab допишет имя диркетории (если его можно определить однозначно по первым набранным символам), или покажет варианты:

    root@mould:~# ls .s[Tab]
    .ssh/ .subversion/


    Но при этом некоторые шеллы умеют дополнять не только пути, но и аргументы для ряда команд. Например:

    root@mould:~# apt-get up[Tab]
    update upgrade


    Или даже более сложные конструкции:

    root@mould:~# apt-get install bash-[Tab]
    bash-builtins bash-completion bash-doc bash-minimal bash-static


    За данный функционал в debain-based дистрибутивах (не могу ничего сказать про остальные) отвечает содержимое пакета bash-completion.
    Для того, чтобы активировать возможности completion достаточно сделать следующее:

    root@mould:~# . /etc/bash_completion

    Или добавить такой вызов в ваш .bashrc файл, после чего перелогиниться:

    if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
    fi


    Скорее всего это у вас уже написано, но закомментировано.
    Попробуем начать использовать одно из самых часто требующихся комплишенов — дополнение имен хостов при доступе к ним по ssh.
    Для начала потребуется отключить хеширование имен хостов в ~/.ssh/known_hosts. При «коробочных» настройках строка в этом файле выглядит примерно так:

    |1|yVV33HmBny6RPYWkUB5aW+TksqQ=|f11ZL/FI9/Krfw2bqN0tBJeeq4w= ssh-rsa AAAAB3Nz__много-много-символов__2bYw==,

    что нас не устроит.
    После выставления значения HashKnownHosts No в конфиг-файле ssh-клиента (/etc/ssh/ssh_config или ~/.ssh/config), и очистки .ssh/known_hosts (иначе в него будут добавляться правильный строки только для новых хостов) мы получим удобочитаемый вариант записи в known_hosts после первой попытки залогинтся на хост:

    mould,11.22.33.44 ssh-rsa AAAAB3NzaC1y__много-много-символов__c2EAANq6/Ww==.

    А это, в свою очередь, позволит использовать комплишен имен при установке ssh-соединения:

    veshij@dhcp250-203:~ $ ssh mould[Tab]
    mould mould01e


    Если в вашем «подчинении» более 5-10 машин это будет весьма удобно.
    И, кстати, дополнение заработает не только для ssh, а еще для ряда других программ: ping, traceroute, telnet, etc. И не только по hostname, а еще и по ip-адресу.

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

    root@mould:~# my_test_script --[Tab]
    --help --kill-all-humans --conquer-the-world


    Поделиться публикацией

    Похожие публикации

    Комментарии 43

      0
      Будет весьма и весьма полезно
        +1
        Работать под рутом? =)
          0
          Это как-то связано с темой статьи?
            0
            Это мой коммент, на как обычно пустой и бессмысленный первый комментарий, я бы даже сказала спамерско-бесполезный… Не заметили, что он подойдет примерно к 70% всех постов?
              0
              нечто среднее между троллиногом и развитием темы? :)
        0
        Мне давно было интересно, как это реализуется. Приятно что так просто, но скрипт на 10к строк это жесть, конечно.
          0
          Скрипт на 10к строк реализует основной функционал, модули для своего дополнения укладываются строк в 15-20 :)
          0
          давно хотел попробывать это сделать, но не доходили руки. valgrind'у например это очень нужно, у него куча длинных опций. жду продолжения
            –2
            Ну пока что тема интереса не вызывает :)
              0
              Думаю если Вы напишите ещё один небольшой пост с обещанным примером, минусовать его не будут точно :)
                0
                Постараюсь дописать через пару дней :)
            0
            в CentOS 5.3 такое не нашел, yum search тоже ничего такого не выдает,
            как подключить?
            0
            унёс в закладки
              +1
              Спасибо вам большое, а то у меня на убунте это работает, а в дебиане — нет. Я всю голову изломал как включить…
                0
                в /etc/bash.bashrc раскомментировать три строчки:

                #if [ -f /etc/bash_completion ]; then
                #    . /etc/bash_completion
                #fi

                тогда автодополнение будет работать для всех пользователей
                  0
                  Да, но не факт что все этого хотят :)
                    0
                    добавьте их тогда в ~/.bashrc
                  0
                  Очень хорошая статья!
                  Сейчас напишу для себя автодополнение для команды invoke-rc.d, а то лениво каждый раз писать /etc/init.d/
                    0
                    нижний коммент вам на самом деле :)
                    0
                    Обычно он есть из коробки.
                      0
                      Точно! Ну совсем я совсем ленивым буду =)
                      –2
                      Не нужно. Если требуется настраеваемое автодополнение — привет, zsh. bash должен быть по возможности более ванильный, ибо работать с ним приходится практически везде, в том числе там, куда свои конфиги не утянешь.
                        0
                        Конкретно для ssh удобней использовать .ssh/config если у вас фиксированный набор машин. Опять же алиасы можно делать любые.
                          0
                          Чем это удобнее?
                            0
                            Конкретно в моем случае, в known_hosts сохраняются айпишники, причем они из одной сети. Автодополнение до последнего октета адреса делает мало погоды. В конфиг же я кладу человеческие названия аля db, web1, web2 и т.д.
                            Кроме того в конфиг можно положить еще много чего вкусного, например юзернейм.
                              0
                              В моем случае количество серверов несколько больше, чем то, что можно запомнить по ip-адресам. При этом я вполне знаю на какой хост по имени надо попасть.
                              Конфиг, к тому-же надо поддерживать руками в актуальном состоянии, а машина в known_hosts попадает сама, после первой попытки логина на нее.
                              >В конфиг же я кладу человеческие названия аля db, web1, web2 и т.д.
                              А у вас не поднята даже локальная DNS зона для ваших машин?
                                0
                                Поэтому я и писал про фиксированный набор машин.
                                У нас далеко не локальная зона. Куча vpn-ов к заказчикам, на всех не наподымаешься :)
                                Кроме того, у нас часто используются виртуальные адреса балансера, за которым живет несколько реальных машин, в этом случае ssh сильно огорчается, когда видит в known_hosts другой хэш машины. Я не проверял еще решает ли ваше предложение эту проблему.
                                  0
                                  >в этом случае ssh сильно огорчается, когда видит в known_hosts другой хэш машины
                                  Он огорчится в любом случае :-)
                                  >часто используются виртуальные адреса балансера, за которым живет несколько реальных машин
                                  вы балансируете все соединения на балансер, а не только на некоторый выбранный(80, к примеру) порт?
                                    0
                                    Да. Виртуальный адрес висит на полноценном интерфейсе.
                                    В общем, мы не можем предугадать какая физическая машина обслужит нас по этому виртуальному адресу в конкретный момент.
                                    known_hosts при коллизии приходится чистить
                                      0
                                      Забавно.
                                      Я сталкивался с системами, когда баласер балансирует (oops) соединения на выбранном порту к определенным машинам. При этом доступ к машинам сохраняется по их «исходным» адресам.
                                        0
                                        Это не только и не столько балансер, сколько обеспечение реданденси, защита от физического выгорания одного из спаренных узлов. Тогда адрес переключится на запасной.
                                        Доступ к машинам по исходным адресам тоже есть. Но обычно надо попасть на «активную»
                                          0
                                          понял :)
                                        0
                                        А зачем чистить? В плане что можно выставить StrictHostKeyChecking в no, и тогда ssh будет ругаться, но прилежно коннектится к удаленным хостам.
                                          0
                                          Сейчас так и есть. Но это у меня :) У остальных, кто про ключик не знает, проблема осталась.
                            0
                            прекрасно! я давно думал что надо найти комплешн для имён хостов — где-то видел что так работает — но всё время забывал. Мерси огромное!
                              0
                              Пожалуйста :) Скоро будет вторая часть, там интереснее :)
                              0
                              друг, рассказывай о автодополнении для собсвеноручных скриптов!
                                0
                                Да-да, где уже вторая часть?
                                0
                                Обещанного продолжения не было уже полтора года, потому его попробовал написать я. Но, увы, кармы не хватает на публикацию. Помогите кто чем можете =\
                                  0
                                  помог, продолжай начатое :)

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

                                Самое читаемое