Несколько советов по использованию bash

Тут приведены некоторые полезные хитрости, направленные на более удобное использование командной строки. Все мы не хотим повторно набирать какую-то длинную команду и ищем ее в истории. Тут — пара трюков от том, как можно энто самое удобство малость повысить.

1. Потеря комманд в .bash_history

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

bash по умолчанию пишет в историю набранные за сеанс команды только при своем закрытии (перед самоликвидацией). Поэтому при открытии нового терминала в другой вкладке вы не увидите только что набранные команды из первой вкладки — они еще не записаны в хистори.

К тому же закрыв первый терминал, а потом второй вы не найдете в истории команд набранных в первом терминале. Потому что по умолчанию bash не дописывает файл .history, а переписывает.

Исправить ситуацию можно, дописав в конфигурационный файл ~/.bashrc пару строк

    shopt -s histappend
    PROMPT_COMMAND='history -a'

Теперь каждая введенная вами команда будет писаться в историю сразу же. Не бойтесь — дырку на жестком месте такая конфигурация не протрет. Не так уж часто вы команды в баше набираете. 🙂 Да и слава богу кеширование дисков пока еще рулит.

2. Эвристическое исправление ошибок директорий

Если дописать такую строчку

    shopt -s cdspell

то bash будет пытаться исправлять допущенные вами опечатки (пропуски и перестановки символов, например /ect/init.d вместо /etc/init.d) в пути у команды cd. Не бойтесь, у rm такая фича работать уже не будет. Только у cd.

3. Не писать в историю подряд идущие строки-дубликаты

Пишем в ~/.bashrc

    export HISTCONTROL="ignoredups"

А если вы не хотите, чтобы в историю попадали вызовы каких-то «неинформативных» команд, то их логирование можно запретить:

    export HISTIGNORE="&:ls:[bf]g:exit"

После этой команды в хистори не будут писаться команды &, ls, bg, fg, exit. Можно дописать и свои, через двоеточие, можно использовать шаблоны.

4. Не разрывать многострочные команды

Еще команда в конфигурационный файл

    shopt -s cmdhist

5. Поиск по истории команд

Иногда команды бывают большими и сложными, и чтобы заново ее не писать и не искать по истории 100 раз нажимая «вверх», можно воспользоваться поиском.

Если вы помните кусочек команды которую хотите найти, то можно просто нажать в bash’e комбинацию Ctrl + R и набрать этот кусочек. bash вам покажет последнюю команду с такой подстрокой. Можно продолжать нажимать Ctrl + R и bash будет выдавать более старые подходящие команды, подходящие под искомую строку.

6. Вернуться в предыдущую директорию

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

    [toor@localhost html]$ cd /var/www/html
    [toor@localhost html]$ cd /etc/
    [toor@localhost etc]$ vi my.cnf
    [toor@localhost etc]$ cd -
    /var/www/html
    [toor@localhost html]$

Эта команда вернет нас в директорию где мы были раньше.

7. Хранить дату выполнения в истории команд bash

По умолчанию утилита history, не сохраняет в .bash_history время исполнения каждой команды.

В баше трейтьей версии сделать это можно и весьма просто. Если объявить глобальную переменную HISTTIMEFORMAT с форматом выводимых данных, то утилита history будет сохранять и выводить эту дату.

Итак, пишем в ~/.bashrc строчку

export HISTTIMEFORMAT='%h %d %H:%M:%S '

После этого в .bash_history перед каждой командой появится коментарий с цифрой — временем выполнения этой команды в формате timestamp:

#1260787129
htop
#1260802594
export HISTTIMEFORMAT='%h %d %H:%M:%S '
#1260802598
history | grep squid
#1260802658
mc
#1260802777
chown -R svn:svn svn

А командочка history будет выдавать историю данных с датой в формате, который мы переменной задали (в похожем формате выдают дату и время утилита ls):

995  Dec 14 13:38:49 htop
996  Dec 14 17:56:34 export HISTTIMEFORMAT='%h %d %H:%M:%S '
997  Dec 14 17:56:38 history | grep squid
998  Dec 14 17:57:38 mc
999  Dec 14 17:59:37 chown -R svn:svn svn

Но можно сделать и по ГОСТУ, в приятном русскому глазу виде «ДД.ММ.ГГГГ»

export HISTTIMEFORMAT='%d.%m.%Y %H:%M:%S '

А можно и в формате ISO: «YYYY-MM-DD»

export HISTTIMEFORMAT='%Y-%m-%d %H:%M:%S '

Простая генерация паролей

Достаточно часто на практике приходится генерировать пароли для разных аккаунтов и сервисов — почты, ftp, samba и просто для нерадивых пользователей, теряющих и забывающих пароли при каждом удобном случае. Очевидно, что придумать новый пароль достаточно просто, но его устойчивость к взлому, как правило, будет сомнительной, поскольку любимые наши пароли — 111, 12345 и «интернет», а также год рождения, номер паспорта или мобильного телефона — известны всем и каждому.

Поэтому для себя я использовал простенький скрипт следующего вида (файл passgen.sh):

#!/bin/bash
echo `tr -cd [:digit:] < /dev/urandom | head -c8`

Этому скрипту необходимо дать права на выполенение

chmod u+x passgen.sh

и в дальнейшем использовать из консоли:

~$ ./passgen.sh
93723588

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

#!/bin/bash
x=`tr -cd [:alnum:] < /dev/urandom | head -c8`
echo ${x:0:4}-${x:4:4}

«Расширенная» версия генератора позволит нам получать буквенно-цифровые пароли в формате XXXX-XXXX:

~$ ./genpass.sh
sv81-1AxP

Прозрачный MC

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

К слову, пользователи KDE могут сделать это штатными следствами – в настройках Konsole, а для пользователей других WM такой способ просто недоступен.

Немного «погуглив», я нашел решение. В любом эдиторе (только не том, что входит в MC), например nano открываем файл ~/.mc/ini (в консоли это выглядит так: nano -w ~/.mc/ini). Идем в самый конец файла и дописываем там следующюю секцию:

[Colors]
base_color=normal=,default:selected=,:marked=,default:markselect=,:menu=,:menuhot=,:menusel=,:menuhotsel=,:dnormal=,:dfocus=,:dhotnormal=,:dhotfocus=,:input=,:reverse=,:executable=,default:directory=,default:link=,default:device=,default:special=,:core=,:helpnormal=,:helplink=,:helpslink=,:

Сохраняем изменения, закрываем, набираем mc и наслаждаемся видом «крутого» MC.

Очень полезное дополнение – MC будет прозрачным только под обычным юзером, от имени которого вы сделали эти изменения, если вы наберете su -c mc, то MC останется непрозрачным (в отличие от «прозрачности для МС» в KDE).

Очень удобно.

Руссификация FreeBSD 7

В /etc/rc.conf добавить:

font8×14=”cp866-8×14″
font8×16=”cp866b-8×16″
font8×8=”cp866-8×8keymap=”ru.koi8-r”
scrnmap=”koi8-r2cp866″

(если нет, то либо используйте sysinstall либо поправьте вручную)

В /etc/ttys для всех теримналов должно быть прописано cons25r вместо cons25, если это не так — исправьте.

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

pw user mod username -L russian

В домашней папке пользователя должен присутствовать файл .inputrc

set meta-flag on
set convert-meta off
set output-meta on

10 трюков в командной строке bash

1. Простой способ перехватить вывод и ошибки

Хотите направить stdout и stderr в один файл?

command &> file

Может вы разбираетесь в некой программе при помощи strace, и желали бы видеть системные вызовы вместе с ошибками программы?

strace badapp &> errors_and_output

Плюсы: легко запоминается, и проще чем «послать ошибки на вывод, а затем всё это в файл».
Совместимость: любой линукс.

2. Распараллеливание циклов

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

for HOST in $(< ListOfHosts); do ssh $HOSTsudo apt-get update& done

Может вам нужна куча ssh-туннелей одновременно:

for HOST in $(< ListOfHosts); do ssh -C -N -R 80:localhost:80 $HOST & done

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

Плюсы: сберегает метрическую туеву хучу (2/3 имперской туевой хучи) времени ожидания завершения.
Совместимость: любой линукс.
Минусы: у баша должны быть ограничения на количество одновременных задач, но пока автор (и переводчик) в них не упёрся.

3. Ловля утечек памяти через крон

Утечки памяти в линуксе нечасты, но бывают, особенно с бета-дистрибутивами или самодельным софтом. Часто выявить программу с подтёком не так-то просто. В линуксе есть программа Out-Of-Memory, позволяющая отыскивать и убивать такие процессы, но пока она сработает, система уже может начать сильно тормозить — настолько, что вы теряете терпение и перезагружаетесь.

Обычный способ узнать потреблении памяти программой это запуск top (или его графического эквивалента, наподобие System Monitor), и проверка Размера Резидентной Части (Res или RSS) интересующих процессов (память, отведённая программой, вам не нужна — утечки происходят от использования, а не от отведения, и программа может отвести (allocate) кучу памяти без вреда для системы). Большинство граждан не в курсе, что top можно запускать пакетно, что означает, что можно использовать cron и top для создания простого отчёта об использовании программой памяти:

  • запустите top
  • кнопками < и > добейтесь сортировки процессов по RSS (размер резидентной части)
  • нажмите W для записи конфигурации в файл
  • добавьте крон-задачу:
  • crontab - <<< '*/15 * * * * top -n 1 -b'

    И каждые 15 минут будете получать письмо с выводом топа.

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

    4. stdin прямо из командной стоки

    Не поняли, что это была за фигня (<<<)? Баш позволяет слать процессам стандартный ввод прямо из командной стоки.

    Плюсы: позволяет писать команды с командной стоки, даже для альтернативно дружественных программ, которые требуют ВСЁ со стандартного ввода. [Грозит кулаком MySQL-ю].
    Совместимость: bash 3 и новее.
    Минусы: всё ещё немало систем с bash 2.

    5. Установить первичный пароль, который надо поменять

    Многие организации имеют хорошие и надёжные политики паролей. Пароли хранятся на виндозных машинах. Линукс либо не не покрывается политикой, либо политика не соблюдается — люди не в курсе авторизации под линукс (большинство граждан не понимают PAM, а линуксовые админы часто не осознают, что линукс может чудесно авторизоваться через Active Directory), и было время, что разработчики OpenSSH не любили PAM (это с тех пор поменялось).

    Поставить пароль, который должен быть поменян при первом логине:

    umask u=rw,go=
    openssl rand -base64 6 | tee -a PasswordFile | passwd –stdin joe
    chage -d 0 joe

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

    Плюсы: пользователи не будут с начальным паролем бесконечно.
    Совместимость: любой линукс с обновлённым OpenSSH (если ваши пользователи заходят в первый раз по SSH). РедХат утверждает, что это всё ещё не работает в RHEL 3/4, но после приложения их обновлений, всё хорошо.
    Минусы: нет.

    6. Простое добавление публичного ключа на удалённый хост

    Для логина но новый хост по ключу надо сначала на этот хост записать публичную часть ключа. Конечно, это можно делать вручную, но вскоре это надоедает (и почему у ssh нет authorized_keys.d…), а ведь для этого есть специальная утилита:

    ssh-copy-id -i .ssh/id_rsa.pub hostname

    Введите пароль последний раз, ssh скажет:

    Now try logging into the machine, with “ssh ‘hostname’”, and check in:

    .ssh/authorized_keys

    to make sure we haven’t added extra keys that you weren’t expecting.

    Попробуйте. До свидания, пароли!

    7. Распаковка RPM без дополнительного софта

    На дебиано-подобных дистрибутивах это не проблема, потому что .deb файлы есть просто .ar архивы. Каждое руководство по РедХату упоминает rpm2cpio (идёт по умолчанию с rpm), но если честно, я не способен запомнить синтаксис cpio, античный формат, сейчас использующийся только, мм, пожалуй, только рпм-ом.

    Эта команда ставит пакет во временную директорию, но не меняет RPM базу (только во временной диркетории, которую вы потом сотрёте). Поскольку в ней нет больше ничего, мы запрещаем зависимости и скрипты.

    mkdir /tmp/deleteme
     
    rpm -ivh –root /tmp/deleteme –nodeps –noscripts package.rpm

    8. Изменился ли файл с момента поставки

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

    dpkg -S /etc/foo/foo.conf
     
    rpm -qf /etc/foo/foo.conf

    Потом разверните оригинальный пакет при помощи tar (DPKg) или трюка с rpm, данного выше (RPM), и запустите:

    diff /etc/foo/foo.conf /tmp/deleteme/etc/foo/foo.conf

    И найдите разницу.

    Плюсы: быстрое нахождение плохих конфиг-файлов (strace тут тоже может пригодиться)
    Совместимость: любой линукс.
    Минусы: у вас остаётся больше времени на работе, чтобы читать Digg.

    9. — Первым делом отключите связь… Ало? ало? идиоты!

    Ковыряетесь в файрволе удалённо? Нервно как-то, правда? Не то нажал, и связь потеряна.

    Почему бы не откатить ошибку? Зарядите откат того, что вы собираетесь менять.

    at now + 5 minutes <<< 'cp /etc/ssh/sshd_config.old /etc/ssh/sshd_config; service sshd restart'

    Если ошибётесь, процесс выполнится и восстановит установки. А если не ошибётесь, запустите atq, и atrm <номер задачи> для удаления.

    Плюсы: прикрывает задницу на случай ошибки.
    Совместимость: любой линукс, в котором разрешён at, а он обычно да.
    Минусы: помнить, что это надо сделать перед рискованным действием.

    10. Открыт ли порт

    Хотите проверить, запущен ли сетевой сервис? Netcat с опцией -w (сколько ждать) будет полезен:

    nc -w 3 server ssh <<< ' '

    Соединиться на ssh порт на хосте по имени server, ждать 3 секунды перед тем, как послать, мм, ничего, и закрыть соединение. Был ли порт открыт, будет отражено в статусе nc.

    if nc -w 3 localhost 22 <<< ''&> /dev/null
    then
    echo 'Port is open'
    else
    echo 'Port is closed'
    fi

    Источник