gladilov.org.ru gladilov.org.ua

17 заметок с тегом

BASH

bash (bourne again shell) — командная среда, используемая по умолчанию во многих современных Linux-дистрибутивах. Если используется ОС из семейства Linux, то, скорее всего, используется и bash.



Вышел bash 5.0

Почти через 10 лет после выхода bash 4.0 и чуть больше чем через 2 года после выхода bash 4.4 состоялся релиз пользовательской оболочки и интерпретатора скриптов версии 5.0.

В новой версии: Показать


  • Встроенная команда «wait» теперь ждёт создания замены последнего процесса;
  • Новые переменные $EPOCHSECONDS и $EPOCHREALTIME, которые раскрываются в секунды с начала эпохи Unix с точностью до секунд и с точностью до микросекунд соответственно;
  • Новые загружаемые встроенные команды: rm, stat, fdflags;
  • Новая переменная $BASH_ARGV0, которая раскрывается в $0 и устанавливает $0 в назначение;
  • При передаче числового аргумента readline’овская команда shell-expand-line больше не удаляет кавычки и подавляет замену команды и процесса;
  • Команда «history -d» теперь понимает отрицательные аргументы как сдвиг с конца истории команд;
  • При передаче аргумента «name» команде «coproc» теперь активируется режим раскрытия слов, таким образом теперь уникальные coproc’ы теперь могут быть созданы в циклах;
  • Цикл раскрытия имён из именных ссылок в функциях теперь раскрывает их в имена переменных в глобальной области видимости;
  • У встроенной команды «wait» теперь появилась опция «-f», которая указывает ждать полного завершения процесса вместо изменения его состояния;
  • Теперь появилось определение в файле config-top.h, которое позволяет оболочке в ограниченном режиме переопределять статическое значение $PATH независимо от содержимого при запуске;
  • Теперь замена процессов не наследует опцию «v» в отличие от замены команд;
  • Теперь если оболочка в неинтерактивном режиме с включенным управлением процессами замечает, что основноц процесс завершился с SIGINT, то ведёт себя как при получении SIGINT;
  • Теперь Posix режим включает единожды запускаемую SIGCHLD ловушку для каждого завершающегося процесса-потомка даже если управление процессами отключено;
  • Новая shopt опция: localvar_inherit; Если она установлена, то локальная переменная наследует значение переменной с таким же именем в ближайшей предшествующей области видимости; Однако, значения переменных несовместимых типов (например, индексированный массив вместо ассоциативного массива) наследоваться не будут;
  • «bind -r» теперь проверяет связана ли указанная последовательность прежде чем связать её с NULL’ом во избежание создания раскладок для многоклавишных последовательностей;
  • Числовой аргумент для команды «operate-and-get-next» теперь указывает какую строку из истории команд нужно редактировать;
  • Позиционные параметры теперь определяются до запуска стартовых файлов, а потому в них теперь стало можно использовать $@;
  • Появилась новая опция, которая доступна на этапе компилирования, которая позволяет отключить проверку того, чтобы наследованная $OLDPWD была директорией;
  • Встроенная команда «history» теперь может удалять диапазоны команд из истории через «-d начало-конец»;
  • Встроенная привязываемая команда «vi-edit-and-execute-command» теперь переводит readline обратно в режим вставки vi после выполнения команд из редактируемого файла;
  • Дополнение команд теперь учитывает соответствия алиасам и именам функций оболочки без учёта регистра если установлена переменная completion-ignore-case;
  • Новая опция оболочки «assoc_expand_once», которая включает попытку раскрытия индексов ассоциативных массивов только единожды;
  • Теперь оболочка устанавливает $BASH_ARGV и $BASH_ARGC при запуске только при включенном расширенном отладочном режиме, в то время как раньше они устанавливались независимо от дополнительных условий;
  • Встроенная команда «umask» теперь позволяет указывать режимы и маски больше чем восьмеричное 777;
  • Встроенная команда «times» теперь учитывает локаль при выводе разделителя между целой и дробной частями десятичного числа;
  • В наличии новая, отключенная по умолчанию и незадокументированная опция оболочки, которая позволяет включать и отключать отправку истории команд syslog’у во время их выполнения;
  • Больше нельзя определять переменные перед специальными встроенными командами, которые изменяют атрибуты переменных, а затем возвращают их обратно в исполняемую среду, до тех пор пока уровень совместимости не установлен в 44 или меньше;
  • Теперь можно определять дефолтное значение $HISTSIZE во время компиляции в файле config-top.h;
  • Встроенная команда «complete» теперь принимает опцию «-I», которая указывает что нужно дополнять первое слово в строке;
  • Встроенная в bash malloc() теперь использует mmap() (по возможности) для удовлетворения запросов более чем 128 Кб, таким образом free() теперь может задействовать mfree() для возвращения страниц памяти ядру;
  • Опция «globasciiranges» теперь включена по дефолту и может быть отключена при компиляции;
  • Индексированные и ассоциативные массивы теперь разрешают индексы состоящие исключительно из пробелов;
  • Опция «checkwinsize» теперь включена по дефолту;
  • shopt опции «localvar_unset» и «progcomp_alias» теперь видимы и задокументированы;
  • Обработчик имён сигналов теперь понимает имена от «SIGRTMIN+n» до «SIGRTMAX»;
  • Новая загружаемая встроенная команда seq;
  • Выполнение ловушек теперь учитывает внутренние вызовы «eval»;
  • Переменная $_ теперь не меняется при выполнении форкающей команды;
  • Встроенная команда «kill» теперь принимает такие аргументы как -sSIGNAME и -nSIGNUM даже если соответствующие программы не поддерживают соответствующие сигналы;
  • В Posix режиме теперь включена «shift_verbose» опция;

Новое в библиотеке readline: Показать


  • Неинкрементирующий поиск в vi-режиме (’N’, ’n’) теперь может искать шаблон оболочки в соответствии со спецификацией Posix (при доступности используется fnmatch());
  • Доступны новые назначаемые команды «next-screen-line» и «previous-screen-line», которые перемещают курсор в тот же самый столбец следующей или предыдущей строки соответственно;
  • Доступны дефолтные привязки клавиш для control-arrow-key комбинаций;
  • Отрицательный аргумент «-N» команды quoted-insert теперь означает вставку следующих N символов используя quoted-insert;
  • Новая публичная функция rl_check_signals(), которая позволяет приложениям отвечать на сигналы, которые ловит readline пока ожидает ввода используя кастомную функцию чтения;
  • Теперь доступна проверка условий относительно версии readline прямо в файле inputrc; Для этого была внедрена своя собственная реализация сравнения: поддерживаемые операторы «равно» и «неравно», строковые переменные могут сравниваться с числами, двоичные переменные должны сравниваться с «on» и «off», имена переменных от операторов отделяются пробелами;
  • Библиотека для раскрытия истории теперь понимает замену команд и процессов, расширенную универсализацию и позволяет появляться им где угодно в словах;
  • Библиотека истории теперь содержит новую переменную, которая разрешает приложенгиям устанавливать начальное состояние закавычивания, таким образом состояние закавычивания может наследоваться от предыдущей строки;
  • Новая публичная функция rl_set_keymap_name() для установки и использования определяемых приложениями имён раскладок;
  • Клавиша «Insert» на цифровом блоке, если доступна, теперь переводит readline в режим перезаписи;

Источник

Элегантная форк-бомба


ВНИМАНИЕ!
Не запускайте эту команду, чтобы «проверить» её, так как у вашего компьютера скорее всего произойдёт сбой, влекущий за собой принудительную перезагрузку системы.

Текст бомбы:

:(){ :|:& };:

Что она делает:
 :() — объявление функции с именем :
 {:|: &} — в теле функции описан запуск её же и отправка вывода снова в функцию : (в фоне)
 ; — разделитель команд, как и &&.
 : — первый запуск функции :

Источник

Автозапуск команды в screen’е

После переезда моего  сайта на VDS’ку шум раздолбанного вентилятора Asus EEE PC 710 перестал меня беспокоить, но теперь периодически вываливается screen-сессия, в которой крутится демон опроса и наполнения БД новостей TTRSS (чаще всего демон отваливался с ошибкой 12 «недостаточно памяти», но иногда и сам процесс скрина отъезжал).

Показать

Для повторного запуска я сначала стартовал сам скрин

screen -S reader

нажимал Enter и уже в нём запускал демона:

php <путь к скрипту демона>/update_daemon2.php

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

screen -dmS reader sh && screen -S reader -X stuff "php <путь к скрипту демона>/update_daemon2.php^M"

Осталось написать демона, который будет контролировать работу запущенного демона.

Но об этом позже...

Получение списка устройств в сети

Для получения списка устройств, работающих в моей домашней сети (получивших IP от моего DHCP-сервера на своём сетевом интерфейсе), я использую самописный скрипт (смесь PHP и BASH’а). Он отрабатывает около 10 секунд, за это время сканируется сеть для выявления ответивших MAC’ов.

Концепцию можно улучшить, например, переписать его полностью на BASH’е и по cron’у вызывать, допустим, раз в пять минут, пусть он пишет MAC’и наличных сетевых устройств в файл/базу, а WEB-скрипт просто читает оттуда актуальные данные при открытии страницы.

Показать

<?php
// задаю необходимые переменные
$home_iface='eth0'; // интерфейс, посредством которого система включена в домашнюю сеть
$lan='192.168.120.0/24'; // определитель домашней сети (или её гостевого сегмента)
$temp_file='/tmp/dev.tmp'; // путь к временному файлу
// функция анализа и вывода MAC'а на странице
function DrawDevice() { ... }
// получаю MAC интерфейса $home_iface
$home_mac=exec("sudo ifconfig {$home_iface} | grep 'HWaddr' | awk '{print $5}'");
// отображаю его на странице
DrawDevice(trim($home_mac));
// удаляю временный файл, если он есть
if(file_exists($temp_file))exec("rm -f {$temp_file}");
// сканирую сетевой диапазон $lan
exec("fping {$lan} -age -r 1 >/dev/null 2>/dev/null");
// вычленяю устройства с ответившими MAC'амм
// и записываю во временный файл,
// можно писать в базу данных для получения динамики
exec("ip n | grep 'lladdr' | awk '{print $5}' > {$temp_file}",$h);
// получаю список ответивших MAC'ов из временного файла
$h=file_get_contents($temp_file);
// и удаляю его
if(file_exists($temp_file))exec("rm -f {$temp_file}");
$mac=array();
// убираю из списка символы новой строки
$mac=explode("\n",$h);
// в цикле вывожу MAC'и
foreach($mac as$host){DrawDevice($host);}
?>

    Требования:
  • 1. в системе должен быть установлен пакет fping (или любой другой с аналогичной функциональностью, например nmap);
  • 2. пользователь, от которого запущен WEB-сервер, обычно www-data, можно проверить командой
    ps aux | egrep '([a|A]pache|[h|H]ttpd)' | awk '{ print $1}' | uniq | tail -1
    должен иметь возможность выполнения команды ifconfig от имени суперпользователя (sudo ifconfig) или запускать эту утилиту непостредственно по пути её расположения, обычно /sbin/ifconfig, можно проверить командой 
    whereis ifconfig

Статья написана для Блога «Умного дома».

Хитрости BASH и тонкости его настройки

BASH (bourne again shell) — командная среда, используемая по умолчанию во многих современных Linux-дистрибутивах. Если используется ОС из семейства Linux, то, скорее всего, используется и bash. Ниже приведены команды, опции настройки и разные трюки, придающие пользователю терминала более комфортную среду для работы (в BASH).

Показать

Настройка автодополнения и поиска в ~/.inputrc

Для одинарного нажатия Tab при автодополнении в ~/.inputrc (или в /etc/inputrc для всех пользователей)

set show-all-if-ambiguous On


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

"\e[A": history-search-backward
"\e[B": history-search-forward

Тонкости настройки ~/.bashrc

Для записи истории команд сразу, а не только при выходе из шела, необходимо добавить

shopt -s histappend
export PROMPT_COMMAND="history -a"


Для запрета записи дубликатов команд в историю

export HISTCONTROL="ignoredups"


Можно запретить логирование определённых команд

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

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


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

shopt -s cdspell


Звуковой сигнал при запуске оболочки

export PROMPT_COMMAND="echo -ne '\a'"

можно использовать по разнному, например — включить мигание окна KiTTY.


Для того, чтобы не разрывать многострочные команды, используется

shopt -s cmdhist


Если вписать

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

то в истории будут записаны дата и время выполнения команды.


Использование регистронезависимых масок файлов

shopt -s nocaseglob

Тогда, к примеру

ls *.jpg

выведет не только *.jpg, но и *.JPG.

Хитрости BASH

Возврат в предыдущую директорию

cd -


При нажатии ESC и сразу за этим . (в терминологии *nix — Meta .) в строку подставится последний использованный объект. Например, если первой строкой набрано

ls /home/smbdy/logs

во второй наберите

rm ESC .

получите

rm /home/smbdy/logs


Реализация ввода пользовательского пароля с проверкой:

echo -n "Пользователь: "
read username
echo -n "Пароль: "
read -s password
echo -en "\nПовторите пароль: "
read -s password2 && echo -e "\n"
if [ "$password" != "$password2" ]; then
    echo -e "Пароли не совпадают.\nЗавершение работы." && exit 1
fi
echo -n "Всё верно, $username. Продолжаем." && echo -e "\n"


Копирование config.cfg в config.cfg-old

cp config.cfg{,-old}


Узнать, какой шел запущен

echo $0


Строка вида ^строка1^строка2 запустит предыдущую команду с заменой строки1 на строку2

$ ehco foo bar baz
bash: ehco: command not found
$ ^ehco^echo
foo bar baz


Переименование файла в такой-же, но с префиксом

mv long-file-name.txt prefix-!#^

Например, команда

mv file-with-long-name-typed-with-tab-completion.txt old-!#^

переименует ’file-with-long-name-typed-with-tab-completion.txt’ в файл с именем ’old-file-with-long-name-typed-with-tab-completion.txt’.


Функция быстрого переименования расширений

renamer() {
   local fn
   for fn in *."$1"; do
     mv "$fn" "${fn%.*}"."$2"
   done
}

Пример: renamer doc txt — переименует все доки в txt’шники в текущем каталоге.


Если определить функцию command_not_found_handle (), то можно обрабатывать ситуацию «команда не найдена». До выдачи сообщения о не обнаруженной команде bash поместит в $1 введенную строку и выполнит код этой функции. При этом, если функция возвращает код завершения 127, то сообщение о ненайденной команде будет выведено на экран.


Для добавления алиаса с автоприменением определяем новый алиас в ~/.bash_aliases

alias editalias=’edit ~/.bash_aliases && source ~/.bash_aliases’


Имейте в виду, что для работы алиасов из этого файла он должен быть явно включён в вашем ~/.bashrc:

[ -f ~/.bash_aliases ] && source ~/.bash_aliases




Получение (списка) сетей, в которых есть IP узла


Навеяно при изучении фаерволов...

Сайты в сети Интернет не всегда хостятся на одном узле, тем более если это система разветвлённых общемировых порталов типа поисковика Google, магазина Amazon или система доставки видеоконтента Netflix. Поэтому для определённого сайта не всегда достаточно знать его доменное имя. Например, для создания правила переадресации в iptables, ipfw и прочих фаерволах нужно указать IP-адрес(а) узла назначения. Для этого я придумал такую функцию-однострочник (для удобства чтения поделена на две строки):

Показать

gethostnets() { host -t a $1 | awk 'NF>1{print $NF}' | while read -r line; do echo $(whois -a $line | grep inetnum | tr -d ' ' \
| cut -f2 -d':' | awk '{system("ipcalc -rn "$1" | grep -v deaggregate | sort -t/ -n -k2 | tail -n 1")}'); done }

Допустим, нужно поменять маршрут к узлу mail.ru. В командной строке пишем gethostnets mail.ru и функция вернёт список сетей, в которых есть IP-адрес мэилрушного сайта:

$ gethostnets mail.ru
94.100.176.0/21
217.69.140.0/23
217.69.140.0/23
94.100.176.0/21
$

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

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

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

PS1 от Parrot OS

В Parrot OS 3.7 переменная окружения PS1 по умолчанию выставлена вот так:

PS1='\[\033[0;31m\]\342\224\214\342\224\200$([[ $? != 0 ]] && echo "[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200")[\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]\$\[\e[0m\] '

В терминале это выглядит довольно... забавно, думаю, тэг «юмор» будет тут к месту...

Показать

2018   BASH   Linux   интересное   ОС   софт   юмор

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

Пишем скрипт, содержащий код:

#!/usr/bin/env bash
MAILTO=somebody@example.com
WATCHPORT=80
TRESHOLD=500
NUMCONN=`netstat -antpu4 | grep :$WATCHPORT | wc -l`
if [[ $NUMCONN -ge $TRESHOLD ]]; then
DATE=`date`
MAILBODY="Datestamp: $DATE\nServer port $WATCHPORT usage overload!\nCurrent port $WATCHPORT connections: $NUMCONN."
echo -e $MAILBODY | mail -s "Server port $WATCHPORT usage overload!" $MAILTO
fi

Скрипт циклически запускаем с помощью cron’а, например — каждую минуту:

* * * * * /path/to/script.sh

Автоматический запуск screen при входе по SSH

Для работы скрипта требуются установленные в системе пакеты dialog и screen.

Показать

В конец ~/.bashrc дописать:

if [ "$SSH_TTY" ]; then
  if [ ! "$STY" ] ; then
    CHOICE=`~/SCREEN/choose`
    if [ "$CHOICE" ]; then exec screen -dr $CHOICE; fi
  fi
fi

При логине по ssh-протоколу откроется меню с выбором работы в существующих сессиях screen’а или возможностью остаться в консоли ssh-клиента. Если запущенных сессий screen’а нет — меню не откроется.

Содержимое файла ~/SCREEN/choose:

#!/usr/bin/env bash
i=0
declare -ax SCREENS
SOCKETS=`find /var/run/screen/S-$(whoami) -type p 2>/dev/null`
if [ -z "$SOCKETS" ]; then exit 0; fi
for S in $SOCKETS; do ((i=$i+1)); S=`basename $S`; SCREENS[$i]=`screen -ls | grep $S | perl -e '$s=<>; $s =~ s/^\\t(.*)\s/$1/; $s =~ s/\s/_/g; print $s'`; done
MENU=""
for ((j=1; j<=$i; j=$j+1)); do MENU="$MENU $j ${SCREENS[$j]}"; done
MENU="$MENU $j Отменить"
WHICH=`dialog --stdout --menu Select: 0 0 0 $MENU`
if [ "$WHICH" != "$j" ]; then echo ${SCREENS[$WHICH]} | sed -e 's/_(.*)$//'; fi

Запуск Apache с IP в качестве имени сервера

Должен быть доступен ifconfig (в Debian 9 по умолчанию не установлен пакет net-tools), конфиг-файл апача лежит по пути /etc/apache/httpd.conf.

Показать

#!/usr/bin/env bash
APACHECONFFILE=/etc/apache/httpd.conf
if test $(id -u) != 0
    then echo "You must be root to run this script! Aborting."
    exit 1
fi
if ! type /sbin/ifconfig>/dev/null 2>&1
    then echo "ifconfig required but not installed! Aborting."
    exit 1
fi
LC_ALL=C
export LC_ALL
ALL=$(ifconfig -a | sed -n 's/^\([^ ]\+\):.*/\1/p' | paste -sd ' ')
IF=""
for if in $ALL; do
    test "$if" == "ppp0" -a "$IF" == "" && IF=$if
done
for if in $ALL; do
    test "$if" == "ippp0" -a "$IF" == "" && IF=$if
done
for if in $ALL; do
    test "${if/#eth*/eth}" == "eth" -a "$IF" == "" && IF=$if
done
for if in $ALL; do
    test "${if/#enp*/enp}" == "enp" -a "$IF" == "" && IF=$if
done
for if in $ALL; do
    test "${if/#wlan*/wlan}" == "wlan" -a "$IF" == "" && IF=$if
done
test "$IF" == "" && IF=lo
echo Using $IF
IP=$(ifconfig $IF|awk '/inet/{print $2}'|cut -d: -f2)
SERVERNAME=$(awk '/^ServerName/{print $2}' $APACHECONFFILE)
echo ServerName changed from $SERVERNAME to $IP
perl -pi -e "s/(^ServerName).*/\1 $IP/" $APACHECONFFILE
/etc/init.d/apache reload

Ранее Ctrl + ↓
Наверх