gladilov.org.ru gladilov.org.ua

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

маленькие хитрости

Хаки и трюки, подсмотренные на просторах Интернета или «выстраданные» мною самим.



Позднее Ctrl + ↑

Запись и воспроизведение команд в консоли

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

Однако существует интересный способ, как делать «видеозапись команд» в консоли без лишних телодвижений (я не говорю обо всяких доставляемых ttyrec, termrec & ipbt). Выполните в терминале, к примеру, следующие команды:

Показать

script -t 2> timing -a ttyoutput
pwd
cd /
pwd
cd -
pwd
exit

После команды exit запись с терминала прервётся и с помощью команды

scriptreplay timing ttyoutput

можно воспроизвести записанные действия и ответы системы. Для выхода можно использовать комбинацию клавиш Ctrl + D в обычном шеле или набрать exit или logout в csh (если переменная ignoreeof не задана — то Ctrl + D тоже сработает).

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

awk '/@/' ttyoutput

А чтобы получить полный список вводимых команд и ответы интерпретатора:

awk '/./' ttyoutput

Можно даже интерактивно передавать вводмые команды, например — с помощью ключа

‒f (‒‒flush)

один пользователь вводит команды в терминал

mkfifo ttyoutput2; script -f ttyoutput2

другой — наблюдает за операциями в реальном времени с помощью

cat ttyoutput2

Сетевой обмен между удалёнными машинами можно организовать с помощью утилиты netcat.

P. S. Команды script и scriptreplay входят в пакет util-linux, поставляемый вместе с операционной системой (по крайней мере в Linux, хотя впервые утилита script появилась в системе 3.0BSD), поэтому они доступны сразу после установки системы.

P. P. S. Альтернативы — уже упоминавшиеся termrec, ipbt, ttyrec/ttyplay — имеет сходный функционал, есть утилита ttycast, осуществляющая широковещательную передачу команд терминального сеанса в реальном времени.
Также существуют такие утилиты:
TermRecord@github — пишет в html и воспроизводит в браузере.

pip install TermRecord
TermRecord -o /path/to/output_html


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

curl -sL https://asciinema.org/install | sh
asciinema rec


showterm.io — похож на asciinema, но оперирует только с текстом.

gem install showterm
showterm
# or if you have not installed showterm, you can run the standalone
bash <(curl record.showterm.io)


monitor — утилита, перехватывающая ввод/вывод терминала и отправляющая на сайт commands.com.

curl commands.io/install-monitor-(ubuntu|macosx|redhat)
monitor -u myusername

2018   маленькие хитрости   ОС   сисадминство   скрипт   софт

Напильник для Эгеи, часть 2

      Устроил для блога ревизию — все длинные статьи спрятал под спойлер, ведь ката в Эгее нет в принципе, разработчик объяснил причину этого в своей статье.

Реализацию спойлера подсмотрел у других, у себя реализовал следующим образом:

Показать

В файле /user/extras/header-pre.tmpl.php прописал следующие строки:

<script type="text/javascript" src="/blog/user/extras/spoiler-hider.js"></script>
<link rel="stylesheet" href="/blog/user/extras/spoiler-hider.css">


spoiler-hider.js:

// Спойлеры для Эгеи
$(function(){
    $('.spoiler-controller').click(function(){
        var aClasses = this.className.split(/\s+/);
        for (var i in aClasses) {
            if (aClasses[i] == 'spoiler-controller' || aClasses[i] == 'spoiler-shown') {
                aClasses.splice(i, 1);
            }
        }
        if ($(this).hasClass('spoiler-shown')) {
            this.innerHTML = this.innerHTML.replace('Скрыть', 'Показать');
            $(this).removeClass('spoiler-shown');
        } else {
            this.innerHTML = this.innerHTML.replace('Показать', 'Скрыть');
            $(this).addClass('spoiler-shown');
        }
        for (i in aClasses) {
            if (!aClasses[i]) continue;
            var jContainer = $('.'+aClasses[i]).not('.spoiler-controller');
            jContainer.slideToggle();
        }
    });
});

spoiler-hider.css

.spoiler-controller { border-bottom: 1px dashed black; cursor: pointer; }
.spoiler-controller:hover { color: #b30; border-color: #b30; }
.spoiler { display: none; }

Теперь в нужном месте страницы пишу код

<p><b class="spoiler-controller pop-up_camper_<уникальный идентификатор>">Показать</b></p>
<section class="spoiler pop-up_camper_<уникальный идентификатор>"><p></p>

а в конце текста (и спойлера)

</section>


Также изменил размер заголовка блога, указав в /themes/plain/styles/main.css

.title h1 {...; font-size: 24px ;...}


Изменил подсвечивание кода (по этой статье) с помощью highlight.js:

<link rel="stylesheet" href="//yandex.st/highlightjs/7.3/styles/github.min.css">
<script src="//yandex.st/highlightjs/7.3/styles/github.min.css"></script>
<script>
	hljs.tabReplace = '    ';
	hljs.initHighlightingOnLoad();
</script>

hljs.tabReplace нужен для того, чтобы табуляции в коде заменялись на пробелы. highlight.js сам определяет на каком языке написан код, но можно явно указывать язык, добавляя class к тегу pre.


2018   HTML   досуг   маленькие хитрости   сисадминство   софт

IP-адреса для использования в документации

Оказывается, есть специальный RFC5737, описывающий 3 блока IP-адресов, зарезервиорованных для примеров, использования в описаниях спецификаций и в документации. Эти блоки суть 192.0.2.0/24 (TEST-NET-1), 198.51.100.0/24 (TEST-NET-2), 203.0.113.0/24 (TEST-NET-3).

Так же указывается, что раньше для этого использовался блок 128.66.0.0/16, однако, в виду того, что он не упомянут в списке богонов в RFC3330 — его можно использовать как обычно, но с определённой осторожностью.

Права народная мудрость: Век живи — век учись (а дураком помрёшь) 

2018   интересное   интернет   маленькие хитрости   сеть   сисадминство

Получение (списка) сетей, в которых есть 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 целевого узла. Так и провайдера можно узнать точнее. Но это тема для другой заметки...

2018   BASH   досуг   интернет   маленькие хитрости   сеть   сисадминство   скрипт   софт

SVG-код вместо картинки

Вместо того, чтобы франить на ФС мелкий файл с простой картинкой (типа индикатор онлайн/офлайн) можно просто в тег img передавать svg-код этой картинки. Например HTML-код

<img src="data:image/svg+xml,<?xml version="1.0"?><svg height="8px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="8" fill="red"></svg>" />
&nbsp;
<img src="data:image/svg+xml,<?xml version="1.0"?><svg height="8px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="8" fill="gold"></svg>" />
&nbsp;
<img src="data:image/svg+xml,<?xml version="1.0"?><svg height="8px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="8" fill="green"></svg>" />

выведет такие три точки:    (сделал форматирование по строкам для удобства и «читаемости», хе-хе). При размере кластера 4К это может быть существенно...

P. S. Наверное, этим все уже давно пользуются, но до меня только дошла выгода этого метода.

2018   HTML   интернет   маленькие хитрости   сеть

Установка и настройка Nginx + PHP в режиме FastCGI [Debian 9]

Начал новую линейку заметок по теме обучения на системного администратора. Учусь не я, а моя жена, хотя и я тоже многое оттуда воспринял (на самом деле нет ;-). Это не конспекты лекций, не пошаговые руководства, а просто заметки на память, чтобы ей легче было повторять пройденный материал. Помечаться будут тегом ’учёба’ и в начале страницы будет стоять маленький логотипчик . В квадратных скобках указывается ОС, в которой производились настройки/тесты/манипуляции.

Итак, первая заметка.

Показать


 Поставить  nginx и  PHP.

sudo apt-get install nginx php-fpm

В файле */etc/nginx/nginx.conf* убрать коментарий в строке

multi_accept on

и дописать index.php в определении индексных файлов

index index.php index.html index.htm index.nginx-debian.html;

В файле */etc/nginx/sites-available/default* изменить путь к индексному файлу

root /var/www/html/site1

и разрешить FPM, убрав коментарий

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}

Также запретить доступ к файлам, имя которых начинается с префикса .ht

location ~ /\.ht {
deny all;
}

Создать индексный файл сайта

sudo mkdir -p /var/www/html/site1
sudo touch /var/www/html/site1/index.php
sudo echo "&lt;?php phpinfo(); ?&gt;" > /var/www/html/site1/index.php

В файле */etc/php/7.0/fpm/php.ini* исправить значения в строках

memory_limit = 256M
default_socket_timeout = 360

и раскомментировать строки

;user_agent="PHP"
;cgi.fix_pathinfo=1

Отключить уязвимость, поставив значение 0:

cgi.fix_pathinfo=0

Затем перегружаем nginx (любым способом)

systemctl reload nginx
nginx -s reload


Задача решена

2018   маленькие хитрости   ОС   сеть   сисадминство   софт   учёба

Напильник для Эгеи

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

Показать

Возможно, что из-за кривоватых настроек моего сервера Эгея из старого бэкапа сразу работать отказалась (нет баз, не известен пароль к базам и т. д.). Это было, вероятно, тяжкое наследие старой системы, я обновлял её через aptitude dist-upgrade.

Пришлось бэкапить MySQL-базы с наполнением блога, затем переустанавливать заново движок (скачал релиз 2.7, версию 3249), инсталлятор создал новые базы, поверх которых я вытащил из бэкапа мои блоговые статьи, комменты и прочее. Причём начальные таблицы в базе создаются с префиксом ’e2Blog’, нужно не забыть поменять на используемый мной префикс в файле system/defaut/config.php, строка

$_config['db_table_prefix'] = 'e2Blog';

Да, и user/settings.json желательно привести к такому виду

{  "db": {"server": "<узел>","user_name": "<имя>","passw": "<пароль>","name": "<база>"},
    "timezone": {"offset": 10800,"is_dst": false},
    "template": "plain",
    "language": "ru",
    "appearance": {"notes_per_page": 10},
    "comments": {"default_on": true},
    "site_title": "Блог ни о чём",
    "description": "Мысли, факты, цитаты, заметки.",
    "author": "Павел Гладилов",
    "user": {"email": "pavel@gladilov.org.ru"},
    "notifications": {"new_comments": true}  }

Затем выяснилось, что вместо статей открывается страница с ошибкой

Fatal error: Uncaught Error: Call to undefined function dl() in <файл> line <строка>

Пришлось погружать свои ручки в код движка... В результате просмотра кода было найдено решение — замена части кода в ядре движка system/core.php с

if (!extension_loaded('gd')) { if (!dl('gd.so')) { header('Content-type: image/gif'); return false; } }

на

if (!extension_loaded('gd')) { header('Content-type: image/gif'); return false; }

После этого блог заработал, но теперь пропала возможность быстрого сохранения в редакторе по комбинации клавиш Ctrl + Enter (в старых версиях — Ctrl + S) и при попытке движка сформировать или вызвать на редактирование страницу, на которой есть ссылки на несуществующие файлы картинок — открывалась страница с серым фоном и маленьким пустым квадратом посередине. Причём, если такая «кривая» страница открылась — то даже при устранении всех причин всё равно отображается ошибочная страница. Я думаю (но не проверял), что это связано с хранением сгенереных страниц (или их частей) в user/caches/*.psa. Возможно, мне повезло, что со временем истёк срок хранения кешированных «кривых» страниц, и они стали отображаться нормально. Или возникновение такой проблемы как-то связано с разными форматами таблиц старой и новой версии движка. А вообще эту проблему я обошёл с помощью прямой правки заметок в записях таблицы <префикс>Notes, затем там-же стал выставлять атрибут ’Null’ в поле «Uploads» и использовать полный путь к файлам картинок от корня.

В файле user/extras/header-pre.tmpl.php прописываю заголовок для блога — кнопки gladilov.org.ru и gladilov.org.ua.

В файле themes/<имя используемой темы>/templates/layout.tmpl.php рисую верхнее меню:

<?php if ($content['class'] == 'frontpage') { ?>
          <div id="e2-blog-description"><?= $content['blog']['description'] ?></div>
        <?php } ?>
<br />
<table width="650">
<tbody>
<tr>
<td><a href="<ссылка1>"><img src="<картинка1>" style="vertical-align:middle!important" />&amp;&nbsp;<пункт1></a></td>
<td width="15"></td>
<td><a href="<ссылка2>"><img src="<картинка2>" style="vertical-align:middle!important" />&amp;&nbsp;<пункт2></a></td>
<td width="15"></td>
...
<td><a href="<ссылкаN>"><img src="<картинкаN>" style="vertical-align:middle!important" />&amp;&nbsp;<пунктN></a></td>
</tr>
</tbody>
</table>
      </div>
    </div>

Ну и тоже выплывшую при правке system/core.php проблему с невозможностью определить новую картинку для юзера решаю изменением в этом же файле определений DEFAULT_USERPIC_FILENAME и DEFAULT_USERPIC_PLACEHOLDER_FILENAME на путь к моей картинке.

define('DEFAULT_USERPIC_FILENAME','<soul.png>'); define('DEFAULT_USERPIC_PLACEHOLDER_FILENAME','<soul.png>');

Теперь мой блог выглядит приблизительно так:

2018   HTML   досуг   маленькие хитрости   мну   сисадминство   софт

Переменные среды для локализации пользовательского интерфейса

 *nix-системы предоставляют развитые средства настройки пользователюской среды под различные потребности. Одна из задач такой настройки — указание регионального стандарта, с которым хочет оперировать пользователь. Например — чтобы графический системный интерфейс отображал сообщения на родном пользователю языке (был локализован), а ввод осуществлялся на английском. Локализация означает приспособление программы или операционной системы к кодировке и стилям печати времени, даты, денежных единиц принятых в данной стране. Иногда применяют сокращение «l10n». Буквы «l» и «n» — начало и окончание слова «localization», а цифра 10 — количество букв между ними. Есть ещё сокращение i18n — «internationalization».

Показать

POSIX-совместимые системы имеют специальный стандарт (RFC 3066) определения локали — идентификатора, определяющего региональные настройки пользовательского интерфейса, такие как язык, страна, часовой пояс, набор символов и т. п. Он имеет следующий вид:

[language[_territory][.codeset][@modifier]]

Например — ru_RU.CP1251, el_GR.UTF-8 или en_US.iso88591. Существует особое имя для региональных настроек POSIX: C — нейтральное значение по умолчанию, C.UTF-8 — для новых POSIX-систем с поддержкой UTF-8.

Многие системные программы для определения языка сообщений и вида кодировки используют установленные переменные окружения. По умолчанию переменные LC_ALL и LANG имеют пустые значения, а все остальные — значение «POSIX». В русифицированных системах при настройке локали указывается определенная кириллическая кодировка, например, UTF-8 (Unicode) или реже CP1251 (русскоязычная кодировка Microsoft Windows) или KOI-8 (русскоязычная кодировка UNIX).

Имя переменной

Описание

LC_ALL

Переменная LC_ALL, если установлена, определяет всё сразу: язык сообщений, кодировку, вид даты и т. п.

LANGUAGE

Переменная LANGUAGE используется в основном программами из проекта GNU

LC_CTYPE

Переменная LC_CTYPE, если не установлена LC_ALL, определяет кодировку символов. В отсутствии LC_CTYPE и LC_ALL, для определения типа кодировки используется переменная LANG

LC_COLLATE

Переменная LC_COLLATE используется в отсутствии LC_ALL для определения алгоритма сортировки. В отсутствии LC_COLLATE для этого используется переменная LANG

LC_MONETARY

Переменная LC_MONETARY используется, если отсутствует LC_ALL, для определения вида денежной единицы. Если LC_ALL и LC_MONETARY не установлены, то используется переменная LANG

LC_NUMERIC

Переменная окружения LC_NUMERIC используется, если не установлена переменная LC_ALL, для определения национального формата печати чисел (например, с плавающей точкой или запятой). Если не установлены LC_ALL и LC_NUMERIC, то используется переменная окружения LANG

LC_TIME

Переменная окружения LC_TIME используется, если не установлена LC_ALL для определения формата даты и времени. Если не установлены переменные LC_ALL и LC_TIME, то используется переменная LANG

LC_MESSAGES

Переменная LC_MESSAGES используется в отсутствии LC_ALL для определения языка информационных и диагностических сообщений и интерфейса. Если LC_ALL и LC_MESSAGES не установлены, то используется переменная LANG

LC_PAPER

Переменная LC_PAPER, если не установлена LC_ALL, определяет размер бумаги при печати. В отсутствии LC_PAPER и LC_ALL, для определения размера бумажного листа используется переменная LANG

LC_NAME

Переменная окружения LC_NAME используется, если не установлена переменная LC_ALL, для определения формата отображения имён (фамилия пишется первой или последней и т. д.). Если не установлены LC_ALL и LC_NAME, то используется переменная окружения LANG

LC_ADDRESS

Переменная LC_ADDRESS, если не установлена LC_ALL, определяет информацию о местоположении и формат адреса (страна указывается в начале или в конце адреса, где расположен почтовый индекс и т. д.). В отсутствии LC_ADDRESS и LC_ALL, для определения формата указания адреса используется переменная LANG

LC_TELEPHONE

Переменная LC_TELEPHONE используется в отсутствии LC_ALL для определения формата телефонных номеров. Если LC_ALL и LC_TELEPHONE не установлены, то используется переменная LANG

LC_MEASUREMENT

Переменная LC_MEASUREMENT используется, если отсутствует LC_ALL, для определения системы единиц измерения (метрическая, имперская и т. д.). Если LC_ALL и LC_MEASUREMENT не установлены, то используется переменная LANG

LC_LC_RESPONSE

Переменная LC_RESPONSE используется в отсутствии LC_ALL для определения того, как на локальном языке отобрадаются ответы (типа Да и Нет, Y/N, и т. п.). В отсутствии LC_RESPONSE для этого используется переменная LANG

LC_IDENTIFICATION

Переменная LC_IDENTIFICATION используется в отсутствии LC_ALL для определения общих метаданных о языковой информации. Если LC_ALL и LC_IDENTIFICATION не установлены, то используется переменная LANG

LANG

Переменная окружения LANG используется для всего, что не установлено ранее переменными вида LC_*

NLSPATH

Задаёт путь к файлам локализованных сообщений и справки

TZ

Задаёт временную зону, используемую системой

Из командной строки управление переменными осуществляется с помощью команд export и env. Чтобы увидеть, какие переменные из вышеописанных и как установлены, можно использовать программу locale. Посмотреть, какие файлы для локализации имеются в системе можно в каталоге /usr/share/locale/, а также выполнив команду locale -a.

[soul@etcetera:~]$ locale
LANG="ru_RU.UTF-8"
LANGUAGE="ru_RU.UTF-8"
LC_CTYPE="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_PAPER="ru_RU.UTF-8"
LC_NAME="ru_RU.UTF-8"
LC_ADDRESS="ru_RU.UTF-8"
LC_TELEPHONE="ru_RU.UTF-8"
LC_MEASUREMENT="ru_RU.UTF-8"
LC_IDENTIFICATION="ru_RU.UTF-8"
LC_ALL="ru_RU.UTF-8"
[soul@etcetera:~]$ locale -a
C
C.UTF-8
POSIX
ru_RU.utf8
[soul@etcetera:~]

2018   интересное   маленькие хитрости   ОС   сисадминство   софт

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

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

#!/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
2018   BASH   интересное   интернет   маленькие хитрости   ОС   сеть   сисадминство   скрипт   софт
2018   интересное   маленькие хитрости   ОС   сисадминство   софт
Ранее Ctrl + ↓
Наверх