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


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

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

Следующие 30  »
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)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

VIM: зачем, если есть IDE, и как?

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

Сегодня вышел текст о том, как человек перешёл с Sublime на VIM. В комментариях, как обычно это бывает, появились сообщения в духе "Зачем мне тратить время на Vim, если есть IDE, где всё работает?" (люди даже статьи на эти темы пишут). Хотел внести свои пять копеек, но объём написанного плавно перевёл текст из разряда "комментарий" в разряд небольшой статьи.



В целом, всё, что ниже — это вкусовщина, конечно. Нравится вам ваша IDE (или ваш текущий инструмент), да и пожалуйста. Используйте для текущих задач то, чем вы владеете лучше всего, это аксиома эффективной работы. Но если у вас вдруг появилось немного времени на повышение вашей эффективности в целом, то попробую вас заинтересовать именно Vim'ом, сравнивая его с некой обобщенной IDE.





Зачем?



На мой взгляд минусы любой IDE в сравнении с VIM (или, наоборот, преимущества VIM) следующие:




  • IDE значительно тяжелее VIM (даже с плагинами); отсюда очевидный минус, что для IDE — нужна достаточно мощная рабочая станция.

  • IDE обычно поддерживает небольшое число языков/платформ. Vim же единообразно поддерживает всё на свете. В Vim я пишу на Ruby/Rails, Python (или так), C, OpenCL (+PyOpenCL), CUDA (+PyCUDA), bash, Go, XML, YAML, HTML, Markdown, Textile, CSS, .ini, Sage, Magma, GAP (последние 3 — системы компьютерной алгебры), LaTex, а также редактирую специфические конфиги некоторых программ (типа X, mutt и т.п.) и редактирую почту. Конфиги и почта — это специфический пример, но, что касается языков программирования и разметки, то вам понадобится осваивать несколько IDE со своими особенностями, горячими клавишами и т.п. только потому, что IDE обычно имеет узкий круг поддерживаемых технологий. Vim (как и Emacs) умеет почти всё, и вам не надо заново привыкать к инструменту. Кроме того, создателю плагина надо сосредоточиться только на том, чтобы хорошо сделать поддержку специфических для ЯП вещей, а всё остальное Vim уже умеет. Как следствие, при переходе от одной технологии к другой (условно, сегодня пишете на Ruby, завтра на Python, а потом обратно), вы не лишитесь привычных базовых вещей, как это могло быть при смене IDE, т.к. останетесь в Vim.

  • Vim, как следствие из предыдущего, поддерживает вещи, которые никто другой не поддерживает: попробуйте найдите IDE для Magma. А для Vim всё есть. Объясняется это тем, что для редких вещей создавать IDE неоправданно, а написать базовый плагин для Vim не так сложно.

  • Vim может работать в режиме только консоль. Иными словами с Vim ваш компьютер может быть тонким клиентом. Конкретно в моём случае есть 10-ти летний Full HD ноутбук IBM'овский. Ясно, что его уже на нормальное использование как рабочей станции для программирования не хватает ну никак: тесты на нём будут идти вечность, а упомянутые IDE будут ощутимо тормозить. В тоже время есть доступ по ssh к мощному серверу, на котором в результате и ведётся разработка: гоняются тесты, работает редактор и т.п. Кроме того, связка vim + tmux + ssh — это постоянно открытая рабочая сессия. Начал работать на одной машине (к примеру, на работе), отлогинился не закрывая редактора и т.п., продолжил из дома с ноутбука — чрезвычайно удобно. А в моём случае, так ещё и для некоторых задач основное вычислительное оборудование (несколько GPU) физически воткнуто в сервер, т.е. помимо удобства, описанного выше, быть тонким клиентом ещё и необходимость. Попробуйте-ка проделать всё это в своей IDE!

  • Сама идеология Vim — очень мощная штука в сравнении с классической IDE. Есть книга Practical Vim: Edit Text at the Speed of Thought, её название ("редактируй текст на скорости мышления") прекрасно отражает результат, который вы получаете на выходе. К сожалению, в этом сложно убедить человека, который не попробовал (хотя некоторые пытаются). Суть в том, что эта идеология настолько заразна, что хочется перенести её с редактора на все сферы общения с компьютером: браузер, pdf-просмоторщик, почтовый клиент, музыкальный проигрыватель, файловый менеджер и многое другое.

  • С Vim вам не понадобится мышь, если вы конечно этого захотите (если не захотите, то Vim отлично интегрирован с мышью). Мне больно смотреть, как люди мучаются с тачпадами или носят с собой мышки, располагая их на разных поверхностях, при работе с ноутбуком.

  • Vim невероятно расширяем, любая ваша хотелка так и или иначе реализована или может быть реализована в Vim.

  • Ваша конфигурация для VIM вообще без труда переносится с машины на машину. Будет ли так просто с вашей IDE?



Если не хватило, вот ещё немного литературы на тему: раз, два, три.



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



Как?



Не стоит сразу ставить адские комбайны из чьих-то конфигов. Да, они выглядят круто, но там часто неинтуитивные горячие клавиши, много магии и лишнего. Пройдите vimtutor. Затем ставьте голый VIM (обычно он не такой голый, как кажется на первый взгляд) и работайте. Ну, ок, уговорили. Настройте в vimrc set nocompatible (убрать совместимость с VI) или поставьте sensible (супербазовый vimrc с настройками типа nocompatible), или работайте в neovim (новая в основном совместимая с VIM реализация VIM с человеческими настройками по-умолчанию).



В процессе работы у вас будут появляться хотелки. Как только появится хотелка, нужно:




  • Поискать, эта функция может быть среди базовых возможностей VIM (а чаще оно так и есть).

  • Если не нашли, то ищите соответствующий плагин и устанавливайте. Плагины советую ставить с помощью vim-plug.

  • Обязательно читайте документацию к установленному плагину (:help ). Она всегда хорошая и понятная!



Не ставьте много плагинов за раз. Возьмите за правило, не больше 2 плагинов в день, тогда вы всегда будете знать, что есть причина поломки, или наоборот, причина ускорения работы. Да и если сразу поставить 33 плагина, то у вас в голове возникнет каша, и вы не будете использовать ни один из этих 33 даже на половину.



P.S. На всякий случай дополню: я не утверждаю, что VIM круче IDE в любой ситуации. Я утверждаю, что существуют параметры, по которым VIM круче IDE, и поэтому имеет смысл обратить на него своё внимание. Эти параметры лично для меня существенны, и я их перечислил в параграфе "Зачем?".


Original source: habrahabr.ru.

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

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

Разработка Docker контейнеров с помощью системы многоцелевых сценариев Sparrow

Четверг, 02 Июня 2016 г. 14:28 (ссылка)

В этой статье я хотел бы рассказать как можно создавать сценарии сборки имиджей для Docker контейнеров с помощью системы многоцелевых сценариев Sparrow*.



Читать дальше →

https://habrahabr.ru/post/302278/

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

Щелевая съёмка: реализация на bash (ffmpeg + imagemagick)

Суббота, 08 Мая 2016 г. 00:38 (ссылка)

Не помню что и почему я искал в интернете несколько дней назад, но я наткнулся на интересную статью с необычными фотографиями. А позже на еще одну статью, где описывалась реализация алгоритма создания таких фотографий на python. После прочтения меня заинтересовала эта тема и я решил провести вечера майских праздников с пользой для себя, а именно реализовать алгоритм «конвертирования» видео в щелевое фото. Правда, не на питоне, но подручными средствами на bash'е. Но обо всем по порядку.



Что такое щелевое фото


Вид фотографии, на которой запечатлено не одно событие в один конкретный момент времени, а несколько событий. Это достигается за счет того, что щелевая камера снимает кадры шириной в один пиксель (это и есть «щель») и «склеивает» их в одно фото. Немного запутанно звучит и пока сложно представить, что это такое и как выглядит. Самым доходчивым объяснением для меня был комментарий к одной из вышеупомянутых статей от пользователя Stdit:

image

После этого все становится понятным.



Пример для наглядности:

image



Алгоритм построения щелевой фотографии



  1. Разложить видео на множество изображений.

  2. Обрезать каждое полученное изображение по ширине в один пиксель с заданным смещением (щелью).

  3. Собрать полученное множество изображений в одно.



Звучит нестрашно и просто.



Дано



  • Камера Xiaomi Yi

  • Желание разобраться и сделать несколько необычных фото

  • Пару вечеров свободного времени





Решение


Первое и самое простое, что приходит на ум, это написать bash скрипт, который будет обрабатывать видео и фото в соответствии с описанными шагами алгоритма. Для реализации задуманного мне понадобился ffmpeg и imagemagick. В упрощенном виде на псевдо bash скрипт выглядит так:

ffmpeg -i videoFile frame-%d.png

for ((i = 1; i <= framesCount; i++));
do
convert -crop 1xframeHeight+slitShift+0 frame-$i.png slit-$i.png
done

montage slit-%d.png[1-framesCount] -tile framesCountx1 -geometry +0+0 outputImage




Разберемся что здесь происходит



  • Во-первых, с помощью утилиты ffmpeg разбиваем видео на множество изображений вида frame-0.png...frame-n.png.

  • Во-вторых, с помощью утилиты convert из пакета imagemagick обрезаем каждое полученное изображение (ключ -crop) следующим образом: ширина == 1px, высота == высоте изображения. Так же указываем смещение щели по горизонтали. Сохраняем в файлы вида slit-0.png...slit-n.png.

  • В-третьих, с помощью утилиты montage из пакета imagemagick собираем полученные изображения в одно фото. Ключ -tile указывает на то, что все фото нужно собрать в одно по шаблону «framesCount по горизонтали и 1 по вертикали», то есть собрать множество изображений в один ряд.





Результат


За пару вечеров был написан скрипт, которому на вход подаем видео файл, а на выходе получаем фотографию. В теории на вход можно подавать видео в любом формате, который поддерживает ffmpeg. Выходной файл можно получить в тех форматах, которые поддерживает imagemagick.



Пользоваться скриптом очень просто:

./slitcamera.sh --input=test.avi --output=test.png --slit-shift=100



где input — видео файл для обработки, output — название результирующего файла, slit-shift — смещение щели по горизонтали.



Первым делом для быстрого тестирования я не стал снимать видео на камеру, а скачал первое попавшееся видео с youtube и «скормил» его скрипту. Вот что из этого вышло:





На следующий день с собой на прогулку я взял свою Xiaomi Yi и снял несколько видео. Вот что из этого вышло:



Родное Азовское море (фото сделано из видео разрешением в 1920x1080 пикселей и продолжительностью в 31 секунду, 60к/с)









А эти фото собраны из видео разрешением в 1280x720 пикселей и продолжительностью в 16 секунд, 120к/с. Обратите внимание на фон второго фото. Он не статичен. На фоне было движущееся колесо обозрения.



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



Original source: habrahabr.ru.

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

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

Мой опыт настройки окружения для Web-разработки

Четверг, 05 Мая 2016 г. 20:19 (ссылка)

Речь пойдет не о настройке денвера и не о том, как поставить LAMP-стек. Я решил рассказать о том, какое мы в своей команде используем окружение для разработки. Мы разрабатываем Web-сервисы и ERP-системы, но всё это, в сущности, ничто иное, как сайты. Просто сложные внутри и порой не такие красивые снаружи.



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





Подождите, а чем плох денвер?



Основной недостаток денвера состоит в том, что проекты в production не работают на денвере. А значит мы не можем гарантировать, что тщательно отлаженные на компьютере разработчика скрипты не начнут «чудить», когда попадут в production. В production проекты обычно работают в Linux (в нашем случае это CentOS или Amazon Linux). Кроме того, работая на денвере, мы не сможем использовать различные утилиты и средства, которые нам нужны в проекте (например, catdoc, поиск sphinx и многое другое).



Ок, но ведь не все готовы работать в Linux!



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



Мы используем CentOS 7, но думаю, без существенных изменений все будет работать и на других дистрибутивах.



Создаем образ виртуальной машины



Ок. Первое, что нужно сделать — это поставить на компьютер гипервизор (VmWare Workstation, Oracle VirtualBox или может какой-то другой по вкусу). Мы используем VmWare. После этого создаем виртуальную машину и разворачиваем в ней тот образ Linux, на котором будут работать наши проекты в production. Устанавливаем Web-сервер, СУБД, в общем все, что нам нужно для запуска проекта. Кстати, если есть образ виртуалки для production, то еще лучше — можно его и взять за основу.



Виртуалку удобнее всего подключить через bridged-сетевой интерфейс. Так она будет полноценным участником сети и можно будет легко показывать результаты коллегам или заказчикам, если пробросить порт из внешнего мира.



Сетевая папка



Первый вопрос, который у нас встал на этом этапе. Нам теперь что, скрипты проекта через putty редактировать?! И очевидное решение, которое мы нашли, было удивительно простым. В Windows-машине нужно завести отдельную папку, в которой будут лежать все наши проекты. Эту папку нужно расшарить для доступа по сети и примонтировать в корневую директорию, с которой работает Web-сервер.



Чтобы все это работало надежнее, я написал скриптик cifs_mount.sh, буквально из 2 строчек кода, который поставил в виртуалке на запуск раз в 5 минут.

#!/bin/sh
if ! mount -t cifs | grep -q `cat /root/file_server`
then mount -t cifs -o uid=apache,gid=apache,iocharset=utf8,noserverino,credentials=/root/.cifscreds `cat /root/file_server` /var/www
fi


Скрипт проверяет, не отвалилась ли шара (простите мой французский). И если отвалилась, обратно ее монтирует.



Файл /root/file_server

//192.168.0.2/Projects



Файл /root/.cifscreds

username=developvm

password=secretpass





В целом, это решение работает надежно, как утюг.



Но тем не менее есть один небольшой нюанс.
Иногда бывает, что при копировании больших файлов, вылетает ошибка cifs. Как правило, это связано с тем, что в Windows не хватает выделенной памяти для шары. Вылеты происходят из-за того, что Win7 настроена по умолчанию на экономию памяти для сетевых подключений, в частности, размер выделяемого для этих целей пула памяти ограничен, и если для обработки файла требуется больше, то Win7 шлет Linux фатальную ошибку интерфейса и CIFS падает.



Также бывает наблюдаются периодические проблемы с неполной загрузкой страниц (не подгружаются CSS или вообще ошибки при попытке Apache прочитать файл). Причем это возникает время от времени без какой-либо системы.

При этом в логе ошибок Apache следующие ошибки:

[Tue Oct 20 10:44:28.417589 2015] [core:crit] [pid 9632] (5)Input/output error: [client 192.168.1.5:60666] AH00529: /var/www/project/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable and that '/var/www/project/' is executable, referer: http://192.168.1.102/script.php

[Tue Oct 20 10:44:28.418762 2015] [core:error] [pid 9555] (5)Input/output error: [client 192.168.1.5:60670] AH00132: file permissions deny server access: /var/www/project/css/main/layout-main.css, referer: http://192.168.1.102/script.php





Чтобы ликвидировать все эти проблемы разом, нужно подредактировать реестр Win7, а именно:

1. У HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\LargeSystemCache установить значение 1

2. У HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters\size установить значение 3



После этого перезапустить LanmanServer. “net stop srv”/“net start srv”. На виртуалке перемонтировать шару.





И еще один нюанс касается опции noserverino
В свое время он породил этот мой вопрос на stackoverflow. Если кратко, эта опция нужна. Подробнее можно почитать по ссылке.





Не стоит пугаться этих нюансов! Они накопились у нас почти за 10 лет разработки с использованием этого подхода.



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



Подпапки для проектов.



А что если у нас больше 1 проекта. Каждый раз поднимать новую виртуалку!? Нам на помощь приходят виртуальные хосты. Придется опять написать небольшой скриптик flush_vhosts.sh (сугубо для удобства работы).

#!/bin/sh

rm /etc/httpd/conf.d/vhosts/*

rm /etc/hosts
echo '127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4' >> /etc/hosts
echo '::1 localhost localhost.localdomain localhost6 localhost6.localdomain6' >> /etc/hosts

for D in `find /var/www -maxdepth 1 -mindepth 1 -type d -printf '%f\n'`
do
echo '' >> /etc/httpd/conf.d/vhosts/$D.conf
echo "ServerName $D.wde" >> /etc/httpd/conf.d/vhosts/$D.conf
echo "ServerAlias *.$D.wde" >> /etc/httpd/conf.d/vhosts/$D.conf
echo "DocumentRoot /var/www/$D" >> /etc/httpd/conf.d/vhosts/$D.conf
if [[ $D == *"bitrix"* ]]
then
echo 'php_admin_value mbstring.func_overload 2' >> /etc/httpd/conf.d/vhosts/$D.conf
echo 'php_admin_value mbstring.internal_encoding UTF-8' >> /etc/httpd/conf.d/vhosts/$D.conf
echo 'php_admin_value max_input_vars 10001' >> /etc/httpd/conf.d/vhosts/$D.conf
echo 'php_admin_value pcre.recursion_limit 1000' >> /etc/httpd/conf.d/vhosts/$D.conf
fi
echo "
" >> /etc/httpd/conf.d/vhosts/$D.conf
echo "127.0.0.1 $D.wde" >> /etc/hosts
done

systemctl restart httpd.service


Вот что он делает:

1. Очищает конфигурацию виртуальных хостов.

2. Очищает /etc/hosts.

3. Дальше он проходится по всем подкаталогам нашей примонтированной папки и создает для каждого каталога новый виртуальный хост Apache. Если в названии каталога находится страшное слово bitrix, то он добавляет в конфиг виртуального хоста несколько специфических настроек для этой замечательной CMS. Добавляет в /etc/hosts новые записи для созданных виртуальных хостов.

4. Перезапускает Apache.



Мы использует в адресах проектов для разработки условный домен первого уровня wde (web developer environment). Можно использовать local или кому что нравится. У нас разрабатываемые проекты доступны по адресам project1.wde, project2.wde и так далее. При этом виртуальные хосты создаются с директивой ServerAlias *.your-folder-name.wde, то есть все поддомены будут также обрабатываться созданным для папки виртуальным хостом.



Таким образом, если нам нужно начать работу над новым проектом, достаточно создать новую папку в общей папке проектов. Выполнить скрипт flush_vhosts.sh. А в Windows прописать адрес для нового проекта в файле C:\Windows\System32\drivers\etc\host.

192.168.1.166 wde

192.168.1.166 site1.wde

192.168.1.166 site2.wde

...и т.д.



Звездочки файл hosts к великому сожалению, не поддерживает. Надо прописывать каждый адрес, с которым будем работать. Вместо 192.168.1.166 нужно указать ip, который вы присвоили виртуальной машине. После этого соответствующий проект будет открываться в браузере по адресам site1.wde или site2.wde и так далее.



Для удобства, если вы пользуетесь, phpMyAdmin, его можно настроить дефолтным хостом. Тогда при обращении по любому адресу, когда Apache не будет находить соответствующую папку проекта, он будет открывать phpMyAdmin. Главное не забыть прописать этот адрес (например, просто wde) в файле hosts в Windows.



Организация загрузочного меню


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



Собственно скрипт, выводящий меню. Его нужно прописать в файле .bash_profile домашней директории пользователя, под которым мы входим на виртуалку. Для виртуалки, на которой ведется разработка, я считаю можно входить под root, соответственно добавляем в файл /root/.bash_profile строчку ./menu.sh. Теперь сразу после входа в систему будет запускаться наше меню. При необходимости из него всего можно выйти, нажав Ctrl+C.



menu.sh
#!/bin/sh
SCRIPT_DIR=`dirname $0`
source $SCRIPT_DIR/utils.sh

#menu actions
act_net () {
nmtui ;
}

act_folder () {
$SCRIPT_DIR/mount_cfg.sh ;
}

act_flushvhosts () {
$SCRIPT_DIR/flush_vhosts.sh ;
}

act_reboot () {
read -p "System is going to reboot, are u sure? (y/N) " key ;
if [ $key = "y" ]; then
systemctl reboot ;
exit
fi
key=
}

act_shutdown () {
read -p "System is going down, are u sure? (y/N) " key ;
if [ $key = "y" ]; then
systemctl halt ;
exit
fi
key=
}

themenu () {
clear
server_uptime
mnt_detect
echo "===================================================================="
echo "======================= WELCOME to CENTOS WDE!!! ==================="
echo "===================================================================="
echo "======================== wish you happy coding ====================="
echo "===================================================================="
echo -e "System time: "$curtime"\tUptime:"$uptime;
echo ;
echo -e "Mounted folder: "$MNT;
echo ;
echo "=========================== network info ==========================="
echo "`ifconfig -a`"
echo ;
echo `grep nameserver /etc/resolv.conf`
echo ;
echo "`route -n`"
echo ;
echo "====================== current vhosts configs ======================"
echo "`ls -1 /etc/httpd/conf.d/vhosts/`"
echo ;
echo "===================================================================="
echo "========================= Available actions: ======================="
echo -e "\t\tConfigure ${FG_UN}net${NORM}"
echo -e "\t\tConfigure mounted ${FG_UN}folder${NORM}";
echo -e "\t\t${FG_UN}Flush${NORM} virtual hosts";
echo -e "\t\t${FG_UN}Reboot${NORM}";
echo -e "\t\t${FG_UN}Shutdown${NORM}";

echo
echo "Type underlined chars(lowercase) and press ENTER or just ENTER to refresh";
echo "Type Ctrl+C to exit to shell";
echo "====================================================================";
}

while true
do
themenu
read answer
case $answer in
"net") act_net;;
"folder") act_folder;;
"flush") act_flushvhosts;;
"reboot") act_reboot;;
"shutdown") act_shutdown;;
*) echo 'No action found! Refreshing...'; sleep 1; continue;;
esac
done




utils.sh - содержит функции и переменные, используемые в других скриптах
#!/bin/sh
set -o pipefail
mnt_dir="/var/www"

if [ "$interactive" != 'no' ]; then
#cursor movements
CU_RIGHT=$(tput hpa $(tput cols))$(tput cub 7)
#background colors
BG_BLACK=$(tput setab 1)
BG_RED=$(tput setab 1)
BG_GREEN=$(tput setab 2)
BG_YELLOW=$(tput setab 3)
BG_BLUE=$(tput setab 4)
BG_PURPLE=$(tput setab 5)
BG_CYAN=$(tput setab 6)
BG_WHITE=$(tput setab 7)
#foreground colors
FG_RED=$(tput setaf 1)
FG_GREEN=$(tput setaf 2)
FG_YELLOW=$(tput setaf 3)
FG_BLUE=$(tput setaf 4)
FG_PURPLE=$(tput setaf 5)
FG_CYAN=$(tput setaf 6)
FG_WHITE=$(tput setaf 7)
#text-decoration
FG_BOLD=$(tput bold)
FG_HB=$(tput dim)
FG_UN=$(tput smul)
FG_REVERSE=$(tput rev)
#back to defaults
NORM=$(tput sgr0)
fi

#functions to display progress
dots () {
if [ "$interactive" != 'no' ]; then
while true; do
echo -n "."; sleep 0.5
done
fi
}
estart(){
if [ "$interactive" != 'no' ]; then
echo -n "$1"
dots &
dots_pid=$!
fi
}
efinish(){
estatus=$?
if [ "$interactive" != 'no' ]; then
if [ "$estatus" -eq 0 ];then
echo "[ ${FG_GREEN}OK${NORM} ]"
else
echo "[ ${FG_RED}FAIL${NORM} ]"
fi
kill $dots_pid
wait $dots_pid 2>/dev/null
fi
}


#detect server uptime
server_uptime () {
uptime=$(uptime)
uptime=${uptime%%.*}
s=$(( uptime%60 ))
m=$(( uptime/60%60 ))
h=$(( uptime/60/60%24 ))
d=$(( uptime/60/60/24 ))
uptime=$d'd '$h'h '$m'm '$s's '
curtime=$(date +'%Y-%m-%d %H:%M:%S')
}

#detect cifs mount
mnt_detect () {
MNT=$(mount -l | grep $mnt_dir)
if [ ! -z "$MNT" ]; then
MNT=$FG_GREEN$MNT$NORM
else
MNT=$FG_RED"error(not found)"$NORM
fi
}




mount_cfg.sh - настройка параметров сетевой папки
#!/bin/sh
SCRIPT_DIR=`dirname $0`
source $SCRIPT_DIR/utils.sh

clear
echo "========================================="
echo " Mounted folder configuration"
echo " (/var/www)"
echo "========================================="
echo

old_address=$(cat /root/file_server)
old_username=$(grep 'username=' /root/.cifscreds | awk -F '=' '{ print $2 }')
old_password=$(grep 'password=' /root/.cifscreds | awk -F '=' '{ print $2 }')

echo "Type new value and press ENTER or just press ENTER to leave current value.";
echo ;
read -p "Address of fileserver, type like //ip/folder (current value $FG_YELLOW$old_address$NORM): " address ;
read -p "Username (current value $FG_YELLOW$old_username$NORM): " username ;
read -p "Password (current value $FG_YELLOW$old_password$NORM): " password ;

if [ -z "$address" ]; then
address=$old_address; fi
if [ -z "$username" ]; then
username=$old_username; fi
if [ -z "$password" ]; then
password=$old_password; fi

echo "======================================="
echo " New parameters"
echo "======================================="
echo -e "IP address of fileserver: "$address
echo -e "Username: "$username
echo -e "Password: "$password
echo "======================================="
echo
read -p "Save changes? (y/N) " key ;

if [ $key == "Y" -o $key == "y" ]; then
echo "username=$username
password=$password" > /root/.cifscreds
echo "$address" > /root/file_server
estart "Unmounting..."
umount /var/www
efinish
estart "Mounting..."
/root/cifs_mount.sh
efinish
echo ;
read -p "Done. Press any key" key ;
else
echo ;
read -p "Nothing was changed. Press any key" key ;
fi






Система контроля версий



Дальше остается настроить любимую систему контроля версий. Можно пользоваться desktop-приложением для Windows, можно работать через командную строку в putty прямо на нашей виртуальной машине. Кому, как удобнее.



PS. Кстати, одно из величайших открытий для меня было, что можно поставить git или svn непосредственно на production сервере. Когда я в свое время это понял, это ощущение было сравнимо, наверное, с тем чувством, которое испытал Архимед, когда сел в ванную. Ведь больше не надо мучиться с синхронизацией файлов по ftp\sftp, достаточно ввести svn up или git pull origin master!



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

https://habrahabr.ru/post/282884/

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

HDD посвящается: усмиряем приложение, прожорливое на дисковое время

Понедельник, 02 Мая 2016 г. 10:35 (ссылка)

Корень всех зол



Долгое время у меня была проблема — система очень сильно тормозила после старта. У меня ноутбук с жёстким диском (HDD) и Ubuntu 14.04.

Как выяснилось, причина крылась в одной лишь программе — демоне Dropbox. Dropbox — это онлайновое файловое хранилище, а его демон — программка, синхронизирующая файлы, расположенные в определённой папке, с онлайн-хранилищем. На старте демон начинает считывать свой кэш. У меня он занимает не одну сотню мегабайт, а удалять его вручную не стоит — есть вероятность потерять данные. Учитывая, что у меня жёсткий диск — устройство с механическими частями — демон начинал потреблять время доступа к нему настолько, что пользоваться компьютером и запускать приложения становилось малореально, пока он не прогрузится. Убрать его из автозапуска и запускать вручную? Неприятное решение, у меня и так есть вещи, которые я на старте вынужден запускать сам (например, iotop, он без прав суперпользователя не запускается). Нужно было найти способ сделать приложение менее прожорливым именно на диск.



ionice нам в помощь. Или нет?



Первое, о чём я услышал по этой теме, была утилитка ionice. Она позволяет изменять приоритет доступа к диску для заданного процесса. Согласно мануалу, существуют три класса приоритетности ввода/вывода. Меня интересовал idle, поскольку он, как я понял из описания, нейтрализует прожорливость приложения, пропуская всегда вперёд него процессы других классов приоритета. Казалось, дело в шляпе, и всё, что надо сделать, это:
ionice -c3 -p $(pgrep dropbox)


Сделано. Эффекта — ноль. Как же так? Ладно, роем дальше.



Scheduler'ы, или «я ничего не понял, но звучит круто»



Как выяснилось, по умолчанию ionice на моей системе вообще не функционирует, поскольку должен быть включён планировщик CFQ. А по умолчанию в новых Убунтах включён планировщик deadline. Не стану вдаваться в подробности, чем они отличаются, ибо сам не до конца въехал. В общем, читаю краткое пояснение по этому делу, а потом меняю планировщик командой (вернее, я добавил эту команду в /etc/rc.local, чтобы планировщик GFQ выставлялся на старте автоматически):
echo cfq > /sys/block/sda/queue/scheduler


Заметка
Кстати, в разделе «замечания» мануала отмечено, что поддержка классов и приоритетов работает на CFQ. Но поскольку до туда всё равно никто не дочитывает… XD



Что-то в системе слегка изменилось. Индикатор load при старте системы стал подниматься выше 11, а процессорная нагрузка стала состоять по большей части из wait. Не уверен, что это всё значит в долгосрочной перспективе, но проблема осталась — переключение на CFQ и последующее применение ionice на процесс dropbox на производительность системы на старте никакого заметного эффекта не произвело: ни положительного, ни отрицательного.



Ну кто столько потоков запускает?! О специфике демона Dropbox.



Я уж было разочаровался, но тут я заметил, что в top показан только один процесс dropbox, а iotop показывает несколько. И кстати, почему в top колонка идентификаторов процессов называется PID, а в iotop — TID? В чём разница между ними? Ответ быстро нашёлся. В моём же случае самое важное открытие: демон Dropbox для своих дел запускает несколько потоков. Много потоков. Выяснилось, что не один десяток. И диск начинают читать иногда по нескольку одновременно. Так вот откуда такие тормоза! А ionice не работал потому, что, присвоив класс приоритета основному процессу, он не передаёт этот класс приоритета дочерним потокам. Поэтому они как были со стандартным классом приоритета, так с ним и остались.

Что ж, как говорят британцы, будем применять bodging. По-нашему, «костыли». Сделаем скриптик, который будет засекать процесс dropbox и все его дочерние потоки, брать их идентификаторы (PID или TID, в данном случае ionice'у это изофаллично до лампочки без особой разницы), и присваивать всем класс idle время от времени (на случай, если dropbox убивает часть дочерних потоков и/или создаёт новые).

#!/bin/bash

while true
do
#собираем список дочерних потоков
TIDS=( $(ps -L --pid $(pgrep -x dropbox) -o tid=) )

for i in "${TIDS[@]}"
do
echo $i
#присваиваем приоритет idle
ionice -c3 -p $i
done

sleep 5

done


Добавляем в автозапуск, перезагружаемся.

И всё заработало почти как будто демона Dropbox вообще нету. Эврика!



Итоги

Таким образом можно работать с любым процессом, потребляющим много дискового времени. Достаточно задать приоритет с помощью ionice и не забывать о подводных камнях, в частности:




  • следить, не запускает ли процесс прожорливые дочерние потоки

  • иметь в виду, что на некоторых системах планировщик ввода/вывода по умолчанию — не CFQ (который поддерживает классы и приоритеты)





Какие ещё вещи следует учитывать? Расскажите о своём опыте в комментариях.



Original source: habrahabr.ru.

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

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

Следующие 30  »

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

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

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