Случайны выбор дневника Раскрыть/свернуть полный список возможностей
";
echo "";

if($enableUseiconv==1)
$line[0]=iconv("CP1251","UTF-8",urldecode($line[0]));

echo "";

И вместо последней строки вставить следующее:



//Проверяем, HTTPS ресурс в строке или нет (по наличию символа ':')
//Если символа нет, значит это HTTP ресурс, сразу отображаем на страницу
$dv=strpos($line[0], ":") ;
if ($dv < 1) {
echo "
";
} else
{

// Если же все таки символ ':' присутствует, следовательно это HTTPS ресурс, значит
// производим "колдовские" действия...

// Отделяем IP адрес от всей строки, т.е. все символы до ':'
$str1=strpos($line[0], ":");
$row1=substr($line[0], 0, $str1);
$ipaddress = ltrim($ipaddress);
$ipaddress = $row1;

// Производим резолв IP адреса с помощью скрипта gethost.sh
$hostname = shell_exec('/usr/bin/gethost.sh ' . $ipaddress);

// Выводим в таблицу полученную информацию об IP адресе
echo "
";
}


Код писАлся на скорую руку, но вполне работает. А срабатывает он, когда открывается просмотр отчета «Трафик пользователей IP адреса», лично мне по большей части необходим только такой отчет. При желании, можно добавить подобный код на любые другие отчеты.



Сам код довольно прост: сначала определяется, какой в данный момент ресурс выводится на экран в таблицу: HTTP или HTTPS, и если это HTTPS (определяется по наличию символа ":"), то отделяем IP адрес от порта, передаем IP адрес в скрипт gethost.sh, получаем вывод скрипта в виде информации об IP адресе, и выводим на экран.



Были мысли заносить в БД сразу нужные данные, но резолв вышеуказанным образом на этапе заполнения БД приводит к длительному процессу распития кофейных напитков, поэтому я от него отказался.



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



Если есть предложения по улучшению, доработке, переделке данного скрипта, буду рад выслушать.
Original source: habrahabr.ru.

https://habrahabr.ru/post/307686/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best



Найдено 800 сообщений
Cообщения с меткой

bash - Самое интересное в блогах

Следующие 30  »
eugene20237

LINUX: Как сделать нормальное цветное приглашение в bash в Ubuntu

Суббота, 24 Сентября 2016 г. 17:11 (ссылка)

В Ubuntu при создании нового пользователя надо указывать оболочку bash вот таким образом:
useradd ivan -s /bin/bash -m
или сделать тоже самое через usermod для существующего пользователя:
usermod ivan -s /bin/bash -m

Если этого не сделать то в терминале по умолчанию будет sh, а не bash и работать станет неудобно.

Эта информация взята отсюда:
http://askubuntu.com/questions/643411/ubuntu-14-04...mand-line-has-missing-features

На всякий случай добавлю как сделать более разноцветное приглашение bash:
http://www.calculate-linux.org/blogs/ru/193/show

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Из песочницы] Исследование и доработка IP-видеосервера на базе Orange Pi PC

Четверг, 15 Сентября 2016 г. 16:24 (ссылка)





Около полугода назад мне достался миниатюрный видеосервер, применение которому я нашёл в арендуемом для мотоцикла гараже, где он всё это время благополучно работал в связке с двумя китайскими NoName IP-камерами, худо-бедно поддерживающими ONVIF, и 3G-модемом, что позволяло мне удалённо посмотреть видео с камер при оповещениях о детекции движения, к счастью совпадавшими пока только с моим приходом в гараж. Не дал этому микросерверу спокойно работать дальше я сам, так как, ещё когда только получил его в руки, из любопытства разобрал и неожиданно для себя обнаружил, что построен он на одноплатнике Orange Pi PC, который незадолго до этого, благодаря низкой цене, широко освещался в интернете, в том числе и на Geektimes, поэтому я примерно представлял его возможности.



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



Исследование прошивки



Первым делом, в надежде, что видеосервер использует полноценный дистрибутив, я попробовал подключить монитор и клавиатуру к плате, но никакого сигнала на выходе HDMI не было, похоже, порт просто никак не задействован в прошивке, о чём, впрочем, и говорят разработчики, заявляя, что это устройство класса MicroNVR (Network Video Recorder), не подразумевающее никакого взаимодействия пользователя с сервером, кроме удалённого доступа. Вторая цель — ssh, порт которого на устройстве открыт, но сервер поддерживает только авторизацию по ключу, который мне никак раздобыть не удалось.



К счастью для меня, устройство базируется на той версии одноплатника, которая идёт без eMMC, и загрузка осуществляется с обычной MicroSD-карты, выступающей с торца платы. Собственно, всё что нужно для получения доступа к содержимому прошивки — вставить карту в кардридер. На 8Gb SanDisk'е расположено 3 раздела:



/dev/sdb1 on /media/user/disk type squashfs
/dev/sdb2 on /media/user/UBOOT type vfat
/dev/sdb3 on /media/user/07836191-ddf8-45ab-b02b-1103320c2e5b type ext4


Размеры разделов:



/dev/sdb1	25M   25M     0 100% /media/user/disk
/dev/sdb2 16M 2.2M 14M 14% /media/user/UBOOT
/dev/sdb3 58M 9.4M 45M 18% /media/user/07836191-ddf8-45ab-b02b-1103320c2e5b


Раздел «UBOOT», судя по всему, используется только загрузчиком U-Boot. Раздел с ext4 содержит логи (/log) основных подсистем (kern, lighttpd, line, netcfgd, syslog) и настройки сервервера видеонаблюдения, доступные изменению пользователем (/lib/line). А на разделе «disk» со squashfs (compressed read-only) расположены уже все файлы ОС и программ. Получается, операционная система и логическая часть со всеми «Аналитиками» и «Облаками» умещена разработчиками в 25 Мб, что совпадает с размером обновлений на их сайте, т.е. заменяется вся прошивка целиком, а не только ПО видеонаблюдения.



Основной раздел содержит привычный набор директорий:



bin   dev  factory  media  root  sbin  tmp  var
boot etc lib proc run sys usr


В целом, ничего необычного в дереве каталогов нет, всё на своих местах. Запускаемые runit-сервисы лежат в /etc/service:



dropbear  hwclock-fix  lighttpd  line  netcfgd  socklog-klog  socklog-unix


Увидев в списке lighttpd, я решил проверить, смогу ли использовать его для своих целей. Запускается он с конфигурацией:



server.modules += ( "mod_cgi" )

$SERVER["socket"] == ":19587" {
include_shell "/usr/share/adm/lighttpd-gencert"

server.document-root = "/usr/share/adm/www"

cgi.execute-x-only = "enable"
cgi.assign = ( "" => "" )
}


Содержимое /usr/share/adm/www:



datetime       firmware  password  profiles  sysinfo   timezones
factory-reset locale profile settings timezone


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



https://192.168.1.2:19587/sysinfo


Сервер использует генерируемый самоподписанный сертификат и стандартную авторизацию с возможностью поменять пароль (на устройстве хранится только хэш). Готовый HTTPS-сервер с авторизацией и очень простой возможностью добавить свой скрипт сэкономил мне кучу времени и я приступил непосредственно к GPIO.



Доработка прошивки



Простой запрос в гугле «Orange Pi PC GPIO» сразу вывел меня на команды:



echo 0 > /sys/class/gpio_sw/PA1/data
echo 1 > /sys/class/gpio_sw/PA1/data


Найти имена портов тоже не было проблемой:





Посмотрев на имеющиеся скрипты, я создал по их примеру новый с именем alarm и содержимым:




#!/bin/sh
set -e

. ../lib/devline/http.sh
. ../lib/devline/auth.sh

is_auth || http_err_unauth

[ "$REQUEST_METHOD" = "PUT" ] || http_err_method PUT

value="$(head -c "$CONTENT_LENGTH" | tr -d '.')"

echo $value > /sys/class/gpio_sw/PA3/data

echo "Content-Type: text/plain"
echo
echo OK


Обновление прошивки



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



dd if=/dev/sdb2 of=sdb2.img


Затем распаковал squashfs в обычную директорию:



unsquashfs sdb2.img


Скопировал скрипт alarm по нужному пути в squashfs-root и собрал из неё новый squashfs образ:



mksquashfs squashfs-root sdb2-new.img


Который потом залил обратно на флешку:



dd if=sdb2-new.img of=/dev/sdb2


Итог



На данный момент я могу по защищённому каналу замкнуть реле:



curl -X PUT -k --data '1' https://admin:j3ks92ls8f@192.168.1.2:19587/alarm


и разомкнуть его:



curl -X PUT -k --data '0' https://admin:j3ks92ls8f@192.168.1.2:19587/alarm


По большому счёту, лично для меня это было просто оценкой технической возможности реализации задумки. Оценка положительная: у меня есть доступ к портам ввода-вывода и я могу добавить свою логику в прошивку устройства. Бонусом я получил готовый к использованию HTTPS-сервер.



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




  1. Написать скрипт службы, которая будет отслеживать состояние входов с датчиками и реагировать на сработку (оповещать, включать сирену). Тут всё понятно, сложностей ни со службой ни с оповещением не предвидится, даже исполняемый файл curl уже есть на устройстве, т.е. для оповещений есть несколько вариантов: SMTP и получение сообщений по IMAP, готовые сервисы отправки SMS, свой сервер;




  2. Добиться работы через интернет без прямого IP-адреса. Дело в том, что через облако работает только основной софт видеосервера, а lighttp-сервер, реализующий системные настройки, доступен только прямо, что, конечно, не плохо само себе. По этому пункту я не так уверен в простоте реализации, мои идеи пока ограничиваются двумя вариантами: ssh-тунель (надо добавить свой публичный ключ на устройство) или свой сервер и long polling со стороны устройства.



Буду благодарен за ваши идеи.
Original source: habrahabr.ru.

https://habrahabr.ru/post/310090/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Доработка парсера логов Squid для корректного просмотра посещенных HTTPS ресурсов

Суббота, 14 Августа 2016 г. 02:47 (ссылка)

Всем привет! Я получал, и получаю множество писем от людей с вопросами по Squid, который работает на основе моей статьи. Наиболее часто возникает вопрос про просмотр логов Squid каким-либо парсером. Проблема в том, что версия Squid 3.5.8 с настроенным прозрачным проксированием HTTPS логирует посещаемые HTTPS ресурсы не в виде доменных имен, а в виде IP адресов с портами (прим. 164.16.43.56:443). Соответственно, при просмотре статистики посещений вместо человеческой информации проскакивают эти самые IP адреса. Собирать статистику с такими данными довольно сложно. Я связывался с разработчиками Squid по этому поводу, но внятного ответа так и не получил. Единственное, что я выяснил, нормальное логирование работает в более новых версиях Squid, но на них прозрачное проксирование лично у меня так и не заработало должным образом. Поэтому возник вопрос о том, как сделать резолв IP адресов в самом парсере логов.



Лично я пользуюсь парсером Screen Squid, и именно в нем я решил попробовать сделать нужные изменения. Так как мне подобный резолв бывает нужен просто при работе в терминале с Bash, я решил весь процесс резолва сделать в виде скрипта на Bash, а в Screen Squid уже средствами PHP его использовать, когда это будет нужно.



Итак, для всего задуманного нам нужны:




  1. собственно, сам парсер Screen Squid (инструкцию по его установке печатать не буду, все есть на оф.сайте).

  2. Grep

  3. Sed

  4. Nslookup

  5. Whois

  6. Прямые руки



Сам Bash-скрипт представляет из себя следующее:



#!/bin/bash

#Единственный входной параметр - ip адрес, запишем его в переменную
IP="$1";

#Пробуем резолвить IP адрес с помощью NSLOOKUP, применяя GREP и SED
#для извлечение из результата нужной нам информации
hostname=$(nslookup $IP | grep -m 1 "name" | sed 's|.*= ||'|sed -r 's/ Auth.+//' | sed 's/^[ \t]*//;s/[ \t]*$//' );

#Если попытка резолва с помощью NSLOOKUP не удалась,
#то узнаем информацию об IP адресе с помощью whois, опять же
#применяя GREP и SED для извлечение из результата нужной нам информации
if [[ "$hostname" == '' ]]; then
hostname=$(whois $IP | grep -m 1 "owner\|OrgName\|orgname\|NetName\|netname\|origin" | sed 's|.*: ||'|sed -r 's/. Auth.+//' | sed 's/^[ \t]*//;s/[ \t]*$//')
fi

#Выводим на экран результат резолва
echo "$hostname"

exit 0;


В принципе, он уже откомментирован, описывать здесь особенно и нечего. Мы получаем информацию об IP адресе сначала с помощью Nslookup, параллельно фильтруя вывод команды с помощью grep и sed, чтобы исключить ненужную информацию. Дабы не писать кучу строк, были использованы возможности grep по включению нескольких условий для выборки (символы "\|"). Сохраняйте скрипт в любом удобном месте, назначайте ему права на выполнение. Допустим, он сохранен в /usr/bin под именем gethost.sh.



Скрипт можно использовать просто из терминала:



gethost.sh ip_address 


Далее расскажу, как этот скрипт прикрутить к Screen Squid. Допустим, что установлен он в /var/www/html. В этой папке будет подпапка reports, где находится файл reports.php. Вот именно в нем необходимо сделать изменения. В этом файле необходимо найти строки:



$result=mysql_query($queryOneIpaddressTraffic) or die (mysql_error());
$numrow=1;
$totalmb=0;
while ($line = mysql_fetch_array($result,MYSQL_NUM)) {
echo "
".$numrow." ".$line[0]."
".$line[0]."".$hostname."
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Сопроцессы: -что, -как, -зачем?

Пятница, 12 Августа 2016 г. 20:38 (ссылка)

Многие пользователи Bash знают о существании со-процессов, появившихся в 4-й версии Bash'a. Несколько меньшее количество знает о том, что сопроцессы в Bash не какая-то новая фича, а древний функционал KornShell'a появившийся ещё в реализации ksh88 в 1988 году. Ещё меньшее количество пользователей shell'ов умеющих сопроцессить знают синтаксис и помнят как это делать.

Вероятно, я отношусь к четвёртой группе — знающих о сопроцессах, периодически умеющих ими пользоваться но так и не понимающих «зачем?». Я говорю «периодически», так как иногда я освежаю в голове их синтаксис, но к тому моменту, когда мне кажется что «вот тот случай когда можно применить co-proc» я уже напрочь забываю о том как это делать.

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

В заголовке статьи у нас 3 вопроса. Пойдём по порядку.



Что?

Что же такое co-process?

Со-процессинг — это одновременное выполнение двух процедур, одна из которых считывает вывод другой. Для его реализации необходимо предварительно запустить фоновый процесс выполняющий функционал канала. При запуске фонового процесса его stdin и stdout присваиваются каналам связанными с пользовательскими процессами. Соответственно, один канал для записи, второй для чтения.

Пояснять это проще на примерах, поэтому сразу перейдём ко второму вопросу.



Как?

Реализации со-процессов в шеллах разнятся. Я остановлюсь на 3-х известных мне реализациях в ksh, zsh и bash. Рассмотрим их в хронологическом порядке.

Хоть это и не имеет прямого отношения к вопросам статьи, отмечу, что все нижеприведённые примеры сделаны на

$ uname -opr
FreeBSD 10.1-STABLE amd64


Ksh

$ `echo $0` --version
version sh (AT&T Research) 93u+ 2012-08-01


Синтаксис

cmd |&


кажется мне наиболее логичным. Здесь для выполнения команды cmd в фоновом режиме мы используем специальную операцию |&, выражающую соответвенно:

— "&" — фоновый процесс;

— "|" — каналы.



Запускаем фоновый процесс:

$ tr -u a b |&
[2] 6053


Убедимся, что он жив:

$  ps afx | grep [6]053
6053 4 IN 0:00.00 tr -u a b


Теперь мы можем общаться с нашим фоновым процессом.

Пишем:

$ print -p abrakadabra1
$ print -p abrakadabra2
$ print -p abrakadabra3


и читаем:

$ read -p var; echo $var
bbrbkbdbbrb1
$ read -p var; echo $var
bbrbkbdbbrb2
$ read -p var; echo $var
bbrbkbdbbrb3


или так:

$ print abrakadabra1 >&p
$ print abrakadabra2 >&p
$ print abrakadabra3 >&p
$ while read -p var; do echo $var; done
bbrbkbdbbrb1
bbrbkbdbbrb2
bbrbkbdbbrb3


Закрываем «конец» трубы для записи:

$ exec 3>&p 3>&-


и для чтения:

$ exec 3<&p 3<&-



Zsh

$ `echo $0` --version
zsh 5.2 (amd64-portbld-freebsd10.1)


Синтаксис со-процессов в zsh не слишком отличается от ksh, что не удивительно, т.к. в его man'е сказано «zsh most closely resembles ksh».

Основным отличием является использование ключевого слова coproc вместо оператора |&. В остальном всё очень похоже:

$ coproc tr -u a b
[1] 22810
$ print -p abrakadabra1
$ print abrakadabra2 >&p
$ print -p abrakadabra3
$ read -ep
bbrbkbdbbrb1
$ while read -p var; do echo $var; done
bbrbkbdbbrb2
bbrbkbdbbrb3


Для закрытия каналов чтения/записи можно воспользоваться идиомой exit:

$ coproc exit
[1] 23240
$
[2] - done tr -u a b
$
[1] + done exit


При этом запустился новый фоновый процесс, который тут же завершился.

Это ещё одно отличие от ksh — мы можем не закрывать существующий сопроцесс, а сразу инициировать новый:

$ coproc tr -u a b
[1] 24981
$ print -p aaaaa
$ read -ep
bbbbb
$ coproc tr -u a d
[2] 24982
$
[1] - done tr -u a b
$ print -p aaaaa
$ read -ep
ddddd
$


в ksh мы бы просто получили:

$ tr -u a b |&
[1] 25072
$ tr -u a d |&
ksh93: process already exists


Несмотря на эту возможность рекомендуется, всегда явно убивать фоновый процесс, особенно, при использовании «setopt NO_HUP».

Здесь же стоит упомянуть, что иногда мы можем получить неожиданные результаты связанные с буферизацией вывода, именно поэтому в приведённых выше примерах мы используем tr с опцией -u.

$ man tr | col | grep "\-u"
-u Guarantee that any output is unbuffered.


Хоть это и не имеет оношения исключительно к со-процессам продемонстрирую это поведение примером:

$ coproc tr a b
[1] 26257
$ print -p a
$ read -ep
^C
$
[1] + broken pipe tr a b


Буфер не полон и мы ничего не получаем из нашей трубы. Заполним его «доверху»:

$ coproc tr a b
[1] 26140
$ for ((a=1; a <= 4096 ; a++)) do print -p 'a'; done
$ read -ep
b


Разумеется, если данное поведение нас не устраивает, его можно изменить, например используя stdbuf

$ coproc stdbuf -oL -i0 tr a b
[1] 30001
$ print -p a
$ read -ep
b


Bash

$ `echo $0` --version

GNU bash, version 4.3.42(1)-release (amd64-portbld-freebsd10.1)



Для запуска со-процесса в bash также как и в zsh используется зарезервированное слово coproc, но в отличии от рассмотренных выше shell'ов доступ к сопроцессу осуществляется не с помощью >&p и <&p, а посредством массива $COPROC:

${COPROC[0]} для записи;

${COPROC[1]} для чтения.

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

$  coproc tr -u a b
[1] 30131
$ echo abrakadabra1 >&${COPROC[1]}
$ echo abrakadabra2 >&${COPROC[1]}
$ echo abrakadabra3 >&${COPROC[1]}
$ while read -u ${COPROC[0]}; do printf "%s\n" "$REPLY"; done
bbrbkbdbbrb1
bbrbkbdbbrb2
bbrbkbdbbrb3


, а закрытие дескрипторов:

$ exec {COPROC[1]}>&-
$ cat <&"${COPROC[0]}"
[1]+ Done coproc COPROC tr -u a b


Если имя COPROC по каким-то причинам не устраивает можно указать свое:

$ coproc MYNAME (tr -u a b)
[1] 30528
$ echo abrakadabra1 >&${MYNAME[1]}
$ read -u ${MYNAME[0]} ; echo $REPLY
bbrbkbdbbrb1
$ exec {MYNAME[1]}>&- ; cat <&"${MYNAME[0]}"
[1]+ Done coproc MYNAME ( tr -u a b )


Зачем?

Прежде чем попытаться ответить зачем нужны сопроцессы подумаем можно ли реализовать их функционал в shell'ах которые не имеют coproc «из коробки». Например в таком:

$ man sh | col -b | grep -A 4 DESCRIPTION
DESCRIPTION
The sh utility is the standard command interpreter for the system. The
current version of sh is close to the IEEE Std 1003.1 (``POSIX.1'') spec-
ification for the shell. It only supports features designated by POSIX,
plus a few Berkeley extensions.
$ man sh | col -b | grep -A 1 -B 3 AUTHORS
This version of sh was rewritten in 1989 under the BSD license after the
Bourne shell from AT&T System V Release 4 UNIX.

AUTHORS
This version of sh was originally written by Kenneth Almquist.


Именованные каналы никто не отменял:

$ mkfifo in out
$ tr -u a b out &
$ exec 3> in 4< out
$ echo abrakadabra1 >&3
$ echo abrakadabra2 >&3
$ echo abrakadabra3 >&3
$ read var <&4 ; echo $var
bbrbkbdbbrb1
$ read var <&4 ; echo $var
bbrbkbdbbrb2
$ read var <&4 ; echo $var
bbrbkbdbbrb3


Пожалуй, с некоторой натяжкой, можно сказать, что это же реализуемо с помощью псевдотерминалов, но развивать эту тему не стану.



Ну и зачем же нужны сопроцессы? Я процитирую выдержку из перевода статьи Mitch Frazier:

Пока я не могу придумать никаких <...> задач для со-процессов, по крайней мере не являющихся надуманными.


И в действительности я лишь один раз смог с относительной пользой применить со-процессы в своих скриптах. Задумка была реализовать некий «persistent connect» для доступа к MySQL.

Выглядело это примерно так:

$ coproc stdbuf -oL -i0 mysql -pPASS
[1] 19743
$ printf '%s;\n' 'select NOW()' >&${COPROC[1]}
$ while read -u ${COPROC[0]}; do printf "%s\n" "$REPLY"; done
NOW()
2016-04-06 13:29:57


В остальном все мои попытки использовать coproc действительно были надуманными.



Спасибо
Хочется поблагодарить Bart Schaefer, St'ephane Chazelas, Mitch Frazier чьи комментарии, письма и статьи помогли в написании статьи.


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/307562/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Через тернии к сборке

Вторник, 09 Августа 2016 г. 10:31 (ссылка)

Привет, дорогие читатели. Я – разработчик в компании “RTL Service”, в которой мои обязанности по разработке продукта пересекаются с обязанностями DevOps. Конкретнее – я создаю и поддерживаю инфраструктуру сборки и первичного тестирования наших продуктов еще до их попадания в отдел тестирования.



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

В качестве сервера CI (непрерывной интеграции) у нас используется Hudson, можете кидать в меня тапками, но мы руководствуемся принципом «Работает — не трогай».

В дальнейшем есть планы попробовать TeamCity либо Jenkins.



Общая информация о задачах и группах на нашем CI сервере.



Все задачи по сборкам у нас разбиты на 5 больших групп:

https://habrahabr.ru/post/307398/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Открытие API для работы с услугами от российского лоукост-хостера (часть 1)

Пятница, 15 Июля 2016 г. 12:17 (ссылка)

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







Предпосылки к этой публикации появились достаточно давно. Один из клиентов с большим количеством виртуальных серверов поинтересовался о том, есть ли возможность работать с API нашего биллинга. В то время, честно говоря, мы были не готовы к такому диалогу и не смогли предложить готовое решение.

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





В качестве биллинговой системы мы используем продукт российской компании ИСПсистем — BILLmanager4. Для всех продуктов ИСПсистем есть открытое API и оно описано в большей или меньшей степени на их официальном сайте документации ispdoc.com

Работать с API можно как из командной строки, обращаясь непосредственно к интерпретатору mgrctl, так и через адресную строку браузера (или любое другое приложение, которое будет отправлять запрос на веб-сервер: curl, wget и т.п)

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



Сам запрос для заказа виртуального сервера, к примеру, KVM Ferrum на один месяц с автоматическим помесячным продлением, шаблоном ОС Centos-6.7-x86_64-minimal без использования лицензии ISPmanager, будет выглядеть так:



https://billing.ihor.ru/billmgr?authinfo=:&addon_1101=20&addon_1103=1&addon_1104=1&addon_1110=1&addon_1791=4&enum_1112=21&enum_1106=25&agree=on&domain=test-for.habr&ostempl= Centos-6.7-x86_64-minimal&period=1210&price=1100&autoprolong=1210&payfrom=neworder&func=vds.order.7&sok=ok




Теперь попробуем расшифровать все это нагромождение переменных и цифр.

Сам запрос можно разделить условно на две части: это URL биллинга и передаваемые параметры запроса биллингу.

Сами параметры можно распределить следующим образом:



Описание параметров




  • Авторизация — authinfo



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




  • Тарифный план — price



Каждому тарифному плану соответствует свой идентфикатор в биллинге, берется из таблицы «Тарифные планы».




  • Параметры тарифного плана – addon_



К параметрами тарифного плана относятся параметры виртуального сервера, его ресурсы. Каждый параметр тарифного плана имеет свой идентификатор и свое значение по умолчанию, которое соответствует размеру диска, количеству ядер процессора и оперативной памяти, а так же IPv6- и IPv4-адресам.




  • Дополнительные услуги – enum_



В дополнительные услуги входят DNS-серверы и использование лицензии ISPmananger.





(параметры по умолчанию для KVM Ferrum)




  • Период заказа — period

  • Автопродление – autoprolong



Идентификатор периода заказа и автопродления для каждой из услуг абсолютно одинаковы.




  • Доменное имя сервера – domain



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

Ошибка: The domain is already in use. Specify a different domain name.

При массовом добавлении виртуальных серверов, рекомендую использовать формат +<порядковый номер>.




  • Шаблон ОС – ostempl



Неполный список шаблонов приведен в этом тексте чуть ниже. Обращаю внимание, что при заказе шаблона ОС без ISPmanager, в установке значения дополнительных услуг следует отключить использование панели управления ISPmanager (для всех тарифных планов этот идентификатор одинаков — 25)




  • Параметры оплаты – payfrom



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




  • Оплата заказа – func



Так как весь заказ виртуального сервера состоит из 7 шагов, то в API, что не особо очевидно на первый взгляд, следует указывать не только саму функцию vds.order, но и номер последнего шага — 7. Таким образом полное значение этого пункта выглядит так: func=vds.order.7




  • Подтверждение пользовательского соглашения – agree



При заказе любой из услуг мы предлагаем ознакомиться с пользовательским соглашением и принять его (тогда заказ уходит на активацию) или не принять его (тогда заказ отменяется). В API этот пункт так же обязателен: agree=on.





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



Чтобы не загромождать текст большими таблицами со всеми тарифными планами, я приведу только ту часть, которая поможет разобраться, как была составлена строка для заказа виртуального сервера с тарифным планом KVM Ferrum. А так же два других младших тарифных плана SSD и OVZ



Тарифные планы








































price period / autoprolong
Тариф ID 1 мес. 3 мес. 6 мес. 1 год
KVM Ferrum 1100 1210 1213 1214 1211
SSD Ferrum 1033 1180 1183 1184 1181
OVZ Ferrum 2061 1758 1761 1762 1759




Параметры тарифного плана

















































addon_ enum_
Тариф / Значение Диск ОЗУ CPU IPv4 IPv6 NS ISPmgr
KVM Ferrum 1101

/ 20

1103

/ 1

1104

/ 1

1110

/ 1

1791

/ 4

1112

/ 21

1106

/ (1/25)

SSD Ferrum 1034

/ 20

1037

/ 1

1043

/ 1

1036

/ 1

1404

/ 4

1045

/ 21

1039

/ (1/25)

OVZ Ferrum 2062

/ 20

2065

/ 1

2071

/ 1

2064

/ 1

2074

/ 4

2073

/ 21

2067

/ (1/25)



Список шаблонов




  • FreeBSD-11-amd64-minimal

  • Centos-6.7-x86_64-minimal

  • Debian-7-x86_64-minimal

  • Debian-8-x86_64-ispconfig

  • Ubuntu-16.04-x86_64-minimal

  • CentOS-7-x86_64-ispmgr5



Если запрос составлен корректно и заявка на активацию новой услуги принята, Вы получите в ответ что-то типа этого:








Ниже в качестве бонуса прикладываю несколько скриптов для заказа произвольного количества виртуальных серверов для консоли Linux и Windows.

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



Пример на BASH

#/bin/bash
#
# Данные для авторизации
USER=user
PASS=password

# Заказать 10 виртуальных серверов
for i in {1..10}
do
/usr/bin/curl https://billing.ihor.ru/billmgr?authinfo=$USER:$PASS&addon_1101=20&addon_1103=1&addon_1104=1&addon_1110=1&addon_1791=4&enum_1112=21&enum_1106=25&agree=on&domain=$USER-$i.ru&ostempl= Centos-6.7-x86_64-minimal&period=1210&price=1100&autoprolong=1210&payfrom=neworder&func=vds.order.7&sok=ok"
done




К сожалению, не удалось придумать никакого приличного варианта, кроме как продублировать предыдущий цикл с использованием curl, собранного для работы в Windows. Но если из числа читателей есть искушенные в скриптописательстве/программировании под Windows, то прошу поделиться более рациональными сценариями в комментариях.



Пример на PowerShell, файл curl.exe должен находиться в той же директории, откуда выполняется скрипт



USER=user
PASS=password

for ($i=1; $i -lt 10; $i++) {
.\curl.exe https://billing.ihor.ru/billmgr?authinfo=$USER:$PASS&addon_1101=20&addon_1103=1&addon_1104=1&addon_1110=1&addon_1791=4&enum_1112=21&enum_1106=25&agree=on&domain=$USER-$i.ru&ostempl= Centos-6.7-x86_64-minimal&period=1210&price=1100&autoprolong=1210&payfrom=neworder&func=vds.order.7&sok=ok"
}

Original source: habrahabr.ru.

https://habrahabr.ru/post/305716/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Запуск cron внутри Docker-контейнера

Вторник, 12 Июля 2016 г. 14:12 (ссылка)



Так уж вышло, что запуск cron в Docker-контейнере — дело весьма специфическое, если не сказать сложное. В сети полно решений и идей на эту тему. Вот один из самых популярных (и простых) способов запуска:

cron -f


Но такое решение (и большинство других тоже) обладает рядом недостатков, которые сходу обойти достаточно сложно:


  • неудобство просмотра логов (команда docker logs не работает)

  • cron использует свой собственный Environment (переменные окружения, переданные при запуске контейнера, не видимы для cron заданий)

  • невозможно нормально (gracefully) остановить контейнер командой docker stop (в конце концов в контейнер прилетает SIGKILL)

  • контейнер останавливается с ненулевым кодом ошибки





Logs



Проблему просмотра логов с использованием стандартных средств Docker устранить сравнительно легко. Для этого достаточно принять решение о том, в какой файл будут писать свои логи cron-задания. Предположим, что это /var/log/cron.log:

* * * * * www-data task.sh >> /var/log/cron.log 2>&1



Запуская после этого контейнер при помощи команды:

cron && tail -F /var/log/cron.log


мы всегда сможем видеть результаты выполнения заданий при помощи «docker logs».



Аналогичного эффекта можно добиться воспользовавшись перенаправлением /var/log/cron.log в стандартный вывод контейнера:

ln -sf /dev/stdout /var/log/cron.log


Если cron-задания пишут логи в разные файлы, то, скорее всего, предпочтительнее будет вариант с использованием tail, который может «следить» за несколькими логами одновременно:

cron && tail -F /var/log/task1.log /var/log/task2.log




Environment variables



Изучая информацию на тему назначения переменных окружения для задач cron, выяснил, что последний может использовать так называемые подключаемые модули аутентификации (PAM). Что на первый взгляд является не относящимся к сабжу теме фактом. Но у PAM есть возможность определять и переопределять любые переменные окружения для служб, которые его (точнее их, модули аутентификации) используют, в том числе и для cron. Вся настройка производится в файле /etc/security/pam_env.conf (в случае Debian/Ubuntu). То есть любая переменная, описанная в этом файле, автоматически попадает в Environment всех cron-заданий.



Но есть одна проблема, точнее даже две. Синтаксис файла (его описание) при первом взгляде может ввести в ступор обескуражить. Вторая проблема — это как при запуске контейнера перенести переменные окружения внутрь pam_env.conf.



Опытные Docker-пользователи насчет второй проблемы наверняка сразу скажут, что можно воспользоваться лайфхаком под названием docker-entrypoint.sh и будут правы. Суть этого лайфхака заключается в написании специального скрипта, запускаемого в момент старта контейнера, и являющегося входной точкой для параметров, перечисленных в CMD или переданных в командной строке. Скрипт можно прописать внутри Dockerfile, например, так:

ENTRYPOINT ["/docker-entrypoint.sh"]


А его код при этом должен быть написан специальным образом:

docker-entrypoint.sh
#!/usr/bin/env bash
set -e

# код переноса переменных окружения в /etc/security/pam_env.conf

exec "$@"




Вернемся к переносу переменных окружения немного позже, а пока остановимся на синтаксисе файла pam_env.conf. При описании любой переменной в этом файле значение можно указать c помощью двух директив: DEFAULT и OVERRIDE. Первая позволяет указать значение переменной по умолчанию (если та вообще не определена в текущем окружении), а вторая позволяет значение переменной переопределить (если значение этой переменной в текущем окружении есть). Помимо этих двух кейсов, в файле в качестве примера описаны более сложные кейсы, но нас по большому счету интересует только DEFAULT. Итого, чтобы определить значение для какой-нибудь переменной окружения, которая затем будет использовать в cron, можно воспользоваться таким примером:

VAR DEFAULT="value"


Обратите внимание на то, что value в данном случае не должно содержать названий переменных (например, $VAR), потому как контекст файла выполняется внутри целевого Environment, где указанные переменные отсутствуют (либо имеют другое значение).



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

VAR="value"


Тут следует предупредить о том, что $PWD, $USER и $PATH вы не сможете заменить для cron-заданий при любом желании, потому как cron назначает значения этих переменных исходя из своих собственных убеждений. Можно, конечно, воспользоваться различными хаками, среди которых есть и рабочие, но это уже на ваше усмотрение.



Ну и наконец, если нужно перенести все текущие переменные в окружение cron-заданий, то в этом случае можно использовать такой скрипт:

docker-entrypoint.sh
#!/usr/bin/env bash
set -e

# переносим значения переменных из текущего окружения
env | while read -r LINE; do # читаем результат команды 'env' построчно
# делим строку на две части, используя в качестве разделителя "=" (см. IFS)
IFS="=" read VAR VAL <<< ${LINE}
# удаляем все предыдущие упоминания о переменной, игнорируя код возврата
sed --in-place "/^${VAR}/d" /etc/security/pam_env.conf || true
# добавляем определение новой переменной в конец файла
echo "${VAR} DEFAULT=\"${VAL}\"" >> /etc/security/pam_env.conf
done

exec "$@"




Поместив скрипт «print_env» в папку /etc/cron.d внутри образа и запустив контейнер (см. Dockerfile), мы сможем убедиться в работоспособности этого решения:

print_env
* * * * * www-data env >> /var/log/cron.log 2>&1




Dockerfile
FROM debian:jessie

RUN apt-get clean && apt-get update && apt-get install -y rsyslog

RUN rm -rf /var/lib/apt/lists/*

RUN touch /var/log/cron.log \
&& chown www-data:www-data /var/log/cron.log

COPY docker-entrypoint.sh /

COPY print_env /etc/cron.d

ENTRYPOINT ["/docker-entrypoint.sh"]

CMD ["/bin/bash", "-c", "cron && tail -f /var/log/cron.log"]




запуск контейнера
docker build --tag cron_test .
docker run --detach --name cron --env "CUSTOM_ENV=custom_value" cron_test
docker logs -f cron # нужно подождать минуту






Graceful shutdown



Говоря о причине невозможности нормального завершения описанного контейнера с cron, следует упомянуть о способе общения демона Docker с запущенной внутри него службой. Любая такая служба (процесс) запускается с PID=1, и только с этим PID Docker умеет работать. То есть каждый раз, когда Docker посылает управляющий сигнал в контейнер, он адресует его процессу с PID=1. В случае с «docker stop» это SIGTERM и, если процесс продолжает работу, через 10 секунд SIGKILL. Так как для запуска используется "/bin/bash -c" (в случае с «CMD cron && tail -f /var/log/cron.log» Docker все равно использует "/bin/bash -c", просто неявно), то PID=1 получает процесс /bin/bash, а cron и tail уже получают другие PID, предугадать значения которых не представляется возможным по очевидным причинам.



Вот и выходит, что когда мы выполняем команду «docker stop cron» SIGTERM получает процесс "/bin/bash -с", а он в этом режиме игнорирует любой полученный сигнал (кроме SIGKILL, разумеется).



Первая мысль в этом случае обычно — надо как-то «кильнуть» процесс tail. Ну это сделать достаточно легко:

docker exec cron killall -HUP tail


Круто, контейнер тут же прекращает работу. Правда насчет graceful тут есть некоторые сомнения. Да и код ошибки по прежнему отличен от нуля. В общем, я не смог продвинуться в решении проблемы, следуя этим путем.



Кстати, запуск контейнера при помощи команды cron -f также не дает нужного результата, cron в этом случае просто отказывается реагировать на какие-либо сигналы.



True graceful shutdown with zero exit code



Остается только одно — написать отдельный скрипт запуска демона cron, умеющий при этом правильно реагировать на управляющие сигналы. Относительно легко, даже если раньше на bash'е писать не приходилось, можно найти информацию о том, что в нем есть возможность запрограммировать обработку сигналов (при помощи команды trap). Вот как, к примеру, мог бы выглядеть такой скрипт:

start-cron
#!/usr/bin/env bash

# перенаправляем /var/log/cron.log в стандартный вывод
ln -sf /dev/stdout /var/log/cron.log

# запускаем syslog и cron
service rsyslog start
service cron start

# ловим SIGINT или SIGTERM и выходим
trap "service cron stop; service rsyslog stop; exit" SIGINT SIGTERM




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

# запускаем в фоне процесс "tail -f" и ждем его завершения
tail -f /dev/null & wait $!


Или, если cron-задания пишут логи в разные файлы:

# запускаем в фоне процесс "tail -F" и ждем его завершения
tail -F /var/log/task1.log /var/log/task2.log & wait $!




Заключение



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



В конце привожу полные листинги Dockerfile и start-cron, которыми я пользуюсь сейчас.

start-cron
#!/usr/bin/env bash

# переносим значения переменных из текущего окружения
env | while read -r LINE; do # читаем результат команды 'env' построчно
# делим строку на две части, используя в качестве разделителя "=" (см. IFS)
IFS="=" read VAR VAL <<< ${LINE}
# удаляем все предыдущие упоминания о переменной, игнорируя код возврата
sed --in-place "/^${VAR}/d" /etc/security/pam_env.conf || true
# добавляем определение новой переменной в конец файла
echo "${VAR} DEFAULT=\"${VAL}\"" >> /etc/security/pam_env.conf
done

# запускаем syslog и cron
service rsyslog start
service cron start

# ловим SIGINT или SIGTERM и выходим
trap "service cron stop; service rsyslog stop; exit" SIGINT SIGTERM

# запускаем в фоне процесс "tail -f /dev/null" и ждем его завершения
tail -f /dev/null & wait $!




Dockerfile
FROM debian:jessie

RUN apt-get clean && apt-get update && apt-get install -y rsyslog

RUN rm -rf /var/lib/apt/lists/*

RUN touch /var/log/cron.log \
&& chown www-data:www-data /var/log/cron.log \
&& ln -sf /dev/stdout /var/log/cron.log

COPY start-cron /usr/sbin

COPY cron.d /etc

CMD start-cron



Original source: habrahabr.ru.

https://habrahabr.ru/post/305364/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<bash - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda