Вагрант и каталог, который не хотел удаляться

В одном из фриланс-проектов используется Vagrant, а я недавно поставил свежий El Capitan.

Клонирую я, значится, проект и делаю в нём $ vagrant up —provision. Что-то там крутится, пыхтит, выплёвывает в консоль кучу всякой информации, а потом — умирает. Ну, думаю, ладно. Обновлю-ка, для начала, всё. Сношу виртуальную машину, качаю последние стабильные VirtualBox и Vagrant, устанавливаю, запускаю…

А там сайт-то простой, на php. И всё ставится через composer install. И вот что-то этот Бетховен (см. на лого композера) снова падает с ошибкой, что он не может удалить какой-то там каталог в процессе установки. Ну, думаю, ладно. Нахожу этот каталог на хост-машине — он прекрасно удаляется. Но композер всё равно сходит с ума и не работает.

В общем, где-то час я занимался удалением каталогов на хост-машине и изнутри виртуалки, чистил ~/.composer, убивал и пересоздавал виртуалку — всё без толку. Если зайти через $ vagrant ssh на виртуалку и попробовать удалить каталоги там, то падает с ошибкой «cannot remove `/home/vagrant/project/vendor/packageName’: Is a directory». А если сделать «ls», то получаем следующую картину:

vagrant@vm:~$ ls -l project/vendor
ls: cannot access project/vendor/packageName: No such file or directory
total 0
?????????? ? ? ? ?            ? packageName

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

И тут, во время очередного перезапуска виртуалки, я увидел ворнинг в консоли:

=> default: Checking for guest additions in VM…
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 4.1.12
    default: VirtualBox Version: 4.3

А дай-ка, думаю, обновлю эти самые Guest Additions, ибо отстают они аж на два минорных релиза. Но тут надо заметить, что эта штуку нельзя поставить из виртуалбокса для для headless-вируалки. Поэтому воспользовался вот этим гистом, модифицировав его под себя.

$ vagrant ssh
vagrantup:~$ cd /opt
vagrantup:~$ sudo wget -c http://download.virtualbox.org/virtualbox/4.3.30/VBoxGuestAdditions_4.3.30.iso \
                       -O VBoxGuestAdditions_4.3.30.iso
vagrantup:~$ sudo mount VBoxGuestAdditions_4.3.30.iso -o loop /mnt
vagrantup:~$ cd /mnt
vagrantup:~$ sudo sh VBoxLinuxAdditions.run —nox11
vagrantup:~$ cd /opt
vagrantup:~$ sudo rm *.iso
vagrantup:~$ sudo /etc/init.d/vboxadd setup
vagrantup:~$ sudo apt-get install chkconfig #не уверен, что это нужно
vagrantup:~$ sudo chkconfig —add vboxadd
vagrantup:~$ sudo chkconfig vboxadd on
vagrantup:~$ exit

Тушу виртуалку, поднимаю, делаю composer install — всё работает. По хорошему, теперь бы надо ещё сделать кастомный package для этого всего, но как-то лень.

На самом деле нет

Простите, но я устал от велосипедизации и их лозунгов. Поэтому щас будет порция сарказма, по мотивам http://bike2work.ru/know-how/.

Я В ПЛОХОЙ ФИЗИЧЕСКОЙ ФОРМЕ

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

ВЕЛОСИПЕД ЕДЕТ СЛИШКОМ МЕДЛЕННО

  • Средняя скорость велосипедиста в городе — 15 км/ч. Чем чаще вы будете практиковаться, тем быстрее научитесь ездить.
    Это правда, но только если вы едете по проезжей части. А там, простите, страшно.
  • На дистанциях в пределах 5 км велосипед, как правило, быстрее другого транспорта.
    Истинно так.
  • На дистанциях в пределах 5-10 км скорость велосипеда сравнима или выше, чем у автомобиля.
    Тут уже всё сильно зависит от маршрута. На 10 км получается быстрее, чем на авто, но вы будете весь потный.

Я ЖИВУ СЛИШКОМ ДАЛЕКО ОТ РАБОТЫ

  • Комбинируйте поездки на велосипеде и общественном транспорте. В троллейбусах и автобусах провоз бесплатный.
    Да-да-да, только вот кому вы там нафиг сдались со своим велосипедом в час пик?
  • Используйте велосипед, чтобы добраться от или до ближайшей станции метро и оставьте его на перехватывающей велопарковке.
    И его у вас украдут через неделю.
  • Если боитесь устать, используйте велосипед только в одном направлении: один день для поездки на работу, на другой день — с работы.
    Если вы нашли на работе место, где можно оставить велосипед на ночь — вы счастливчик.

РЯДОМ С РАБОТОЙ НЕТ ВЕЛОПАРКОВКИ

  • Попробуйте привязать велосипед к забору или столбу неподалеку от офиса.
    И его опять украдут через неделю.
  • Поговорите с руководством компании — возможно, вам разрешат занести велосипед в подсобку или держать его на рабочем месте.
    Возможно. А возможно и нет. Но попробовать действительно стоит.
  • Попросите руководство установить велопарковку рядом с офисом. Для этого лучше объединиться с другими велосипедистами.
    Если парковка не охраняемая, ну, вы поняли…

Я БОЮСЬ, ЧТО ВЕЛОСИПЕД СЛОМАЕТСЯ

  • Перед тем как сесть на велосипед, убедитесь, что колёса накачаны, а тормоза и фары работают исправно.
    А ещё что тросики не растянуты, цепь не заржавела, спицы на колёсах не полопались.
  • Пройдите техосмотр в хорошей веломастерской. Не забудьте сообщить, что намерены использовать велосипед для регулярных поездок.
    Ещё бы кто подсказал контакты хорошей веломастерской.
  • Если вы сами не умеете производить мелкий ремонт, узнайте, где на пути вашего следования располагаются мастерские.
    И в чём теперь преимущество велосипеда перед машиной? В ней хоть под дождём эвакуатор ждать не страшно.

НА РАБОТЕ НЕТ ДУША

  • Большинство велосипедистов работает в офисе, где нет душа. Если не гнать, передвигаясь с комфортной скоростью, у вас вряд ли возникнет в нём потребность.
    Блин, расскажите мне, как вы это делаете — двигаетесь со скоростью 15+ км/ч и не потеете?
  • Если вы рассчитываете использовать поездки как вариант фитнеса, налегайте на педали по дороге с работы, а не наоборот.
    Но тогда вы будете ехать на работу ооочень медленно.
  • Слишком крутые горки преодолевайте пешком. Это не сильно увеличит время в пути и поможет сохранить свежий вид.
    Толкать велосипел в горку нисколько не легче чем ехать на нём. Если вы не хипстер на фиксе, конечно.

У НАС В ОФИСЕ ДРЕСС-КОД

  • Если у вас городской велосипед с прямой посадкой, то большую часть года ничто не помешает вам ездить в деловом костюме.
    Действительно, ведь у нас нет ни дождя, ни луж, ни пыли на дорогах.
  • Держите на работе запас офисной одежды.
    Годный совет. Даже если у вас нет дресс-кода.
  • Если по работе или после неё вам предстоит особо торжественное мероприятие, в этот день велосипед можно оставить дома.
    Нет, что, правда можно оставить велик дома?

В ДОРОГЕ МОЖНО ПОПАСТЬ ПОД ДОЖДЬ

  • Заведите себе плащ-дождевик и всегда возите его с собой.
    И резиновые сапоги. И штаны резиновые тоже не помешают.
  • Оснастите велосипед крыльями, которые защитят вас от брызг, летящих из-под колёс.
    Особенно хорошо они защитят от брызг от проезжающих мимо автомобилей.
  • Если за окном льёт как из ведра, необязательно ехать на велосипеде, можно воспользоваться и другим видом транспорта.
    Если за окном льёт как из ведра — лучше вообще сидеть дома. Пока дойдёшь до автобуса — промокнешь всё равно.

МНЕ КАЖЕТСЯ, ЧТО ЭТО НЕБЕЗОПАСНО

  • Согласно статистике, передвигаясь на велосипеде, вы рискуете попасть в аварию гораздо меньше, чем те, кто едет на автомобиле.
    А если летать самолётами — риск ещё ниже. Статистика вообще смешная наука.
  • Изучите и соблюдайте ПДД. Основная масса аварий с участием велосипедистов происходит, когда они нарушают ПДД.
    А ещё в ПДД написано, что велосипеду не место на тротуаре. И как же теперь нам быть?
  • Снабдите велосипед фарами и обязательно включайте их в тёмное время суток. Если со шлемом и в светоотражающей одежде вам будет спокойнее, купите себе и то и другое.
    О, второй годный совет. Велосипедист должен мигать как новогодняя ёлка, нет правда, лучше чтобы вас было видно как можно дальше.

У МЕНЯ МНОГО РАЗЪЕЗДОВ ПО РАБОТЕ, А ВЕЧЕРОМ МНЕ НУЖНО В МАГАЗИН

  • Купите надёжный замок, чтобы спокойно оставлять велосипед на улице.
    А ещё посмотрите на ютьюбе подборку роликов про болторезы и жидкий азот.
  • Прикрепите корзинку на руль и ящик на багажник, чтобы увеличить грузоподъемность велосипеда.
    И будьте готовы к снижению управляемости велосипеда.
  • Если едете на встречу, заложите лишние 5 минут на поиски парковки для велосипеда.
    Что? Для велика тоже нужно искать место для парковки? Ну я лучше поищу место, где можно машину припарковать.

Автоматический импорт ssh-ключа в ssh-agent в МacOS

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

Чтобы не заморачиваться с прописыванием ключей к гитхабу на виртуалке — включён проброс ключей. Однако на MacOS загрузка ключа в ssh-agent через `$ ssh-add` почему-то работает только до перезагрузки системы. Потом нужно снова загрузить ключ.

Перезагружаюсь я редко, но всё равно каждый раз раздражался от необходимости этого лишнего действия. Прописывание команды в `~/.zshrc` не давало нужного результата и так я мучаюсь уже больше полугода. Правильнее сказать — мучился.

Сегодня копнул чуть глубже и нашёл простое рабочее решение. Нужно импортировать ключ в Keychain. Для этого достаточно эту команду в терминале:

$ ssh-add -K [path/to/private SSH key]

Перезагрузился, проверил — ключ успешно импортировался в ssh-agent:

$ ssh-add -l
2048 96:0d:e8:f3:ed:c7:a1:b5:39:a7:a8:f7:13:6c:96:62 /Users/h4/.ssh/id_rsa (RSA)

Первый подход к ES6

Спецификация ECMAScript6 уже пару месяцев как перешла в статус ратифицированного стандарта, а я так и не написал на нём ни строчки. Но вот подвернулся шанс.

Суть задачи проста — у сообщества «Веб-стандарты» есть твиттер-аккаунт для текстовых трансляций с конференций, @webstandards_up, и есть репозиторий для логов этой трансляции. Но не было нормального инструмента для создания md-файлов. Я уже делал попытку написать такой инструмент, но он был не доделан и заброшен.

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

Самая нудная часть — это работа с api twitter. Но тут мне несказанно повезло, потому что создатели jsunderhood.ru создали модули get-tweets и twitter-tokens, а также tweet.md для парсинга тела твита (к сожалению, он не умеет раскрывать картинки). Собственно большая часть движка нашего робота также позаимствована у jsunderhood.ru, поэтому просто расскажу, какие вещи в ES6 мне понравились, а какие — не очень.

Общая поддержка языка

Мне было лень ставить последний io.js и разбираться, что уже можно использовать, а что нет, поэтому я просто сделал npm install --save babel и запускал скрипты через babel-node.

В WebShtorm/PHPShtorm уже давно есть поддержка синтаксиса ES6, так что с этим тоже не было проблем.

Модульная система

Сама по себе конструкция import мне давно знакома из питона, но в этом маленьком проекте я не увидел реальной разницы между использованием импортов и require(). Хотя, общий стандарт — это, безусловно, хорошо.

Поддержка import в шторме пока что частичная. Если нужный модуль описан в файлах приложения — его можно автоимпортировать через Alt+Click, как это делается для python-модулей и require-зависимостей. Но если модуль находится в node_modules — IDE его почему-то не видит.

var, let, const

В принципе, у меня уже давно не было проблем с областью видимости переменных, правило — «всегда объявляй все переменные в начале функции» и поддержка IDE прекрасно справляются. Однако мысль использовать const для вещей которые не должны меняться в ходе работы приложения мне нравится. Вот только получается что почти всё становится константой, в том числе и лямбда-функции.

Кроме того, я привык к «single var» в кодстайле и множество const меня как-то смущают. Но тут дело привычки. На «single const» я скорее всего никогда не соглашусь, стройность отступов ломается.

Стрелочные функции

Мне нравится функциональный стиль написания кода. Все эти map(), filter(), reduce(). Но меня очень утомляло написание анонимных функций внутри этих методов и необходимость пробрасывать контекст. Тут стрелочные функции однозначно рулят.

Не очень нравится как выглядит присвоение лямбда-функции переменной/константе — const extractImages = (tweet) => tweet.entities.media; — два символа «равно», которые стоят почти рядом затрудняют восприятие кода.

Template strings

Это та вещь, которой мне очень не хватало в JavaScript. Собирать строки конкатенацией — это какое-то издевательство, особенно когда ты знаешь, что есть нормальные варианты типа "Hello, {name}".format(greeting). Теперь у нас наконец-то есть template strings (вот только я так и не нашёл изящного переводя для этого термина).

Однако очень хочется посмотреть в глаза тому человеку, который решил, что для литеральной формы записи стоит использовать символ ` — на клавиатуре он находится в самом неудобном месте. Идеальным для меня было бы наличие метода format() у объекта String(), но такой вариант был скорее всего отвергнут по причине совместимости со сторонними библиотеками (привет, Symbol.iterator!).

Выводы

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

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

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

«Ручная» загрузка треков в Garmin Connect

Сегодня утром у меня «моргнул» WiFi как раз во время синхронизации треков из моего Garmin Forerunner в Garmin Express на MacOS. Вроде бы ничего страшного, но софт у Гармина сильно хуже железок, поэтому треки с часов списались, а в «облако» не улетели. И при повторной синхронизации с работающим WiFi ничего не произошло. В общем, зажал Express мои треки.

Но меня так просто не проведёшь. Открываем Finder и переходим в каталог `~/Library/Application Support/Garmin/Express/Registered Devices/`. Там будет столько каталогов, сколько устройств у вас подключено в Garmin Express. У меня их два, а имена каталогов — это серийный номер железки, поэтому я ориентировался по картинке `device_image.png` внутри папки.

Переходим в каталог `PendingSyncUploads`, а в ней — в `FIT_TYPE_4` (или в `FIT_TYPE_9`, или в ту, которая соответствует типу активности, трек от которой мы ищем. И не спрашивайте меня, какой номер чему соответствует. Не знаю). Ищем нужный файл по его имени, имя — дата и время тренировки.

Теперь копируем этот файл и у копии добавляем расширение `.fit`, в моём случае `2015-08-14 07/09/14 +0000_360` переименовался в `2015-08-14 07/09/14 +0000_360.fit`. Файлы без расширения не получится залить на http://connect.garmin.com/

Теперь открываем http://connect.garmin.com/ и нажимаем кнопку загрузки активностей. Вот эту

2015-08-14 10-55-22 Garmin Connect

В выпавшем списке выбираем «Upload Your Activity» и переходим на вкладку «Manual Upload». Ну а уже там выбираем наш *.fit файл и загружаем его.

Возможно, стоит почистить каталог `PendingSyncUploads`, чтобы не было дубликатов в будущем. Но что-то мне подсказывает, что Garmin Express не особо смотрит в эту папку.