Рубрика: blog

  • Модуль интеграции Dreamkas для OpenCart 3.0.2.0

    Модуль интеграции Dreamkas для OpenCart 3.0.2.0

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

    Введение

    Те, кто сталкивался с сервисом Dreamkas (онлайн-кассы, фискализация чеков, сканеры, терминалы и вот это вот всё по 54-ФЗ), могут иметь интернет-магазин на базе OpenCart.

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

    (далее…)
  • VK API: загрузка изображения на стену. Рабочий код на PHP7 + cURL

    Публикую просто чтобы не потерялось.

    Если хорошо попросите и если я не забуду, оформлю полноценный репепт публикации постов с твоего сайта на страницу пользователя, с прикреплением фотографии. Когда твоё приложение в ВК зарегистрировано как веб-сайт, а не Stand-alone приложение.

    Пока тут только серверная часть. Она большого труда не составляет.

    Забудь всё, что ты видел о загрузке фотографий через curl. Я двое суток ебал мозги с целью выяснить почему я делаю так, как говорили когда-то и говорят до сих пор (например, про @ перед именем загружаемого файла, например, что уже неактуально для PHP >= 5.5)…. и почему при успешном запросе к серверу фотографий, ВК мне отдаёт пустой photo = []

    Будем считать, что у тебя уже есть ID приложения и ты получил жизненно важный access_token. Конкретно в контексте данного поста не играет роли, является ли твоё приложение веб-сайтом или Stand-alone. Механизм на сервере один.

    Наверняка ты уже заебался также, как и я, уже изучил документации, ответы сервера и всякое такое. Поэтому не буду рассказывать что будет происходить после каждого чиха.
    (далее…)

  • DavFS2. Куда утекает свободное место? Got error 28 from storage engine

    DavFS2. Куда утекает свободное место? Got error 28 from storage engine

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

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

    Однажды утром, после свежего бекапа, MySQL стал падать с ошибкой:

    Got error 28 from storage engine

    Эта ошибка возникает во время выборки записей из БД. Поскольку выборка хранится в кеше на диске и в этот момент возникает ошибка, значит что-то с ним не так. Самое банальное — закончилось место. По факту так и оказалось. СУБД просто негде было хранить файлы кеша.

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

    Начал поиски обжоры.

    (далее…)
  • Ностальгия. Как я погрузился в транс

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

    Однажды, пришёл к нам новый человек на должность штатного дизайнера. Я был обычным лаборантом в местном IT-отделе и по совместительству типографии.

    Я даже не помню уже как его зовут. Мы с ним сидели рядом и частенько говорили о всяком. Я рассказывал ему как хочу стать программистом, но какого-то ляда просиживаю сраку в железке. Он мне рассказывал как работать в Adobe InDesign и верстать буклеты. В то время в институте активно проходили всяческие конференции, соревнования и прочие подобные мероприятия городского и регионального масштабов, и требовались графические материалы для рекламы, мерча и всякого такого.
    (далее…)

  • Резервное копирование базы данных на Cron с выгрузкой в облако на примере Яндекс.Диск. Версия 1.

    Резервное копирование базы данных на Cron с выгрузкой в облако на примере Яндекс.Диск. Версия 1.

    Привет.

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

    Он приведён поэтапно, можешь скопировать пункты 4.1-4.5, убрав оттуда заголовки, и получишь готовый скрипт. Или можешь скачать, ссылка будет в конце. А лучше прочитать пост и вникнуть в суть происходящего.

    ОС на сервере — CentOS 6.7
    Версия СУБД — MySQL 5.5 (да, знаю, старая)

    Скрипт будет вертеться на сron, конечно же. Это чтобы само всё. Но это в конце.

    Монтирование Я.Диска в систему.

    1.1 Ставим davfs2 систему:

    yum install davfs2

    1.2 Создаём папку, в которую у нас будет монтироваться удалённое хранилище:

    mkdir /mnt/yadisk

    1.3 В файл /etc/davfs2/secrets пишем:

    /mnt/yadisk полныйадресemail@yandex.ru пароль

    1.4 В файле /etc/fstab указываем настройки монтирования хранилища (в одну строку, конечно):

    https://webdav.yandex.ru/ /mnt/yadisk davfs user,rw,_netdev,file_mode=600,dir_mode=700 0 1

    В конце файла должна быть пустая строка.

    Разгадку этого заклинания можно разобрать вот тут: rus-linux.net (отлично всё расписано)

    1.5 Тестируем:

    mount /mnt/yadisk # монтирование
    df -h /mnt/yadisk # проверка свободного места

    В результате должно отобразиться свободное место на Яндекс.Диске, типа того:

    [root@server ~]# mount /mnt/yadisk
    [root@server ~]# df -h /mnt/yadisk
    Filesystem            Size  Used Avail Use% Mounted on
    https://webdav.yandex.ru/
                           10G  1,8G  8,3G  18% /mnt/yadisk

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

    umount /mnt/yadisk # Размонтируем диск

    Три-четыре. Закончили упражнение.

    Делаем дампы базы данных

    Дамп базы данных создаётся штатной утилитой mysqldump, которая идёт в комплекте с MySQL. Подробнее о ней можно прочесть здесь: MySQL.ru. Я же покажу здесь только необходимое мне самому.

    Синтаксис всей команды, например, таков:

    mysqldump --host=localhost --user=root --password=1234 -q --default-character-set=utf8 mybigdatabase > /home/mybigdatabase.sql

    Разберёмся с этой командой:

    —user — Имя пользователя БД
    —password — Его пароль
    —host — Адрес базы данных (скорее всего это localhost)
    —default-character-set — Кодировка текста дампа (скорее всего, это будет utf8)
    -q — Вывод текста дампа непосредственно на стандартный вывод stdout без буферизации запроса. Вообще, этот ключик нам необязателен, ибо у нас будет прямая запись вывода в файл. Но без него оно нафиг не надо, а с ним пусть будет.
    mybigdatabase — Имя базы данных
    > — Перенаправление вывода с перезаписью
    /home/mybigdatabase.sql — …например, в этот файл

    Можешь поиграться, чего-нибудь подампить, если есть чего.

    Упаковка дампа

    Используем команду gzip таким простым образом:

    gzip /home/mybigdatabase.sql

    В этой же папке образуется файл mybigdatabase.sql.gz, который меньше исходного на порядки.

    Можно использовать tar, но придётся вносить правки в скрипт. Если хочешь заморочиться — пожалуйста, но особой разницы не будет.

    tar -czf mybigdatabase.tar.gz /home/mybigdatabase.sql

    Всё.

    Объединение вышеописанного

    Теперь определяемся что и зачем будет делать наш скрипт. Всё очень просто:

    1. Инициализация — готовим переменные, параметры, пути, адреса;
    2. Создание дампа — собственно, бекапа БД;
    3. Упаковка дампа — для экономии места;
    4. Отправка бэкапа в облака — на случай смерти локального файла:
      1. Монтирование хранилища;
      2. Копирование файла в хранилище;
      3. Размонтирование хранилища;
    5. Завершение — выводим сообщения с результатами и итогами работы скрипта.

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

    Создаём файл db_backup.sh там, где душе угодно. Мне угодно в домашней папке рута.
    Пишем в него нижеследующее.

    4.1 Инициализация:

    #!/bin/bash
    
    # Данные для работы с БД
    DBHOST=localhost # Адрес БД
    DBUSER=root # Имя пользователя базы данных
    DBPASSWD=1234 # Пароль от базы данных
    DBNAME=mybigdatabase # Имя базы данных для резервного копирования
    DBCHARSET=utf8 # Кодировка базы данных (utf8)
    
    # Даты
    DATE=`date +%F` # Префикс для структурирования бекапов (формат: 2017-05-22)
    DATETIME=`date +%F-%H-%M-%S` # Полная текущая дата и время (формат: 2017-05-22-12-23-34)
    
    # Локальное хранилище
    LOCALDIR=/root/db_backup # Полный путь к каталогу, где будут храниться резервные копии
    LOCALPATH=$LOCALDIR/$DATE # Полный путь к папке за сегодня
    LOCALFILE=$LOCALPATH/$DBNAME-$DATETIME.sql # Полный путь к файлу дампа
    LOCALFILEGZ=$LOCALFILE.gz # Полный путь к архиву дампа
    # Путь к бекапу будет выглядеть так:
    # /root/db_backup/2017-05-22/mybigdatabase-2017-01-01-12-23-34.sql.gz
    
    # Облачное хранилище
    CLOUDUSE=1 # Копировать ли в облако? Закомментировать строку, если не надо
    CLOUDMNT=/mnt/yadisk # Точка монтирования облака относительно корня
    CLOUDDIR=db_backup # Папка в облаке, куда будут лететь файлы (внутри папки CLOUDMNT, т.е. без / в начале)
    CLOUDPATH=$CLOUDMNT/$CLOUDDIR/$DATE # Полный путь к папке текущей даты в облаке относительно корня
    CLOUDFILE=$CLOUDPATH/$DBNAME-$DATETIME.sql # Полный путь к файлу дампа в облаке
    CLOUDFILEGZ=$CLOUDFILE.gz # Полный путь к архиву в облаке
    
    # Путь к бекапу на примонтированном хранилище будет выглядеть так:
    # /mnt/yadisk/db_backup/2017-05-22/mybigdatabase-2017-01-01-12-23-34.sql.gz
    
    # Начало процесса
    echo "[-----------------------------[`date +%F-%H-%M-%S`]-----------------------------]"
    echo "[`date +%F-%H-%M-%S`] Starting backup"

    4.2 Создание дампа:

    if ! [[ -d $LOCALPATH ]]; then # Если нет папки за сегодня
     mkdir $LOCALPATH 2> /dev/null # создаём её, ошибки игнорируем
    fi
    echo "[`date +%F-%H-%M-%S`] Generate a database dump: '$DBNAME'..."
    mysqldump --user=$DBUSER --host=$DBHOST --password=$DBPASSWD -q --default-character-set=$DBCHARSET $DBNAME > $LOCALFILE
    if [[ $? -gt 0 ]]; then
     # если дамп сделать не удалось (код завершения предыдущей команды больше нуля) - прерываем весь скрипт
     echo "[`date +%F-%H-%M-%S`] Dumping failed! Script aborted."
     exit 1

    4.3 Упаковка дампа:

    else # иначе - упаковываем его
     echo "[`date +%F-%H-%M-%S`] Dumping successfull! Packing in GZIP..."
     gzip $LOCALFILE # Упаковка
     if [[ $? -ne 0 ]]; then # Если не удалась
      echo "[`date +%F-%H-%M-%S`] GZipping failed! SQL-file will be uploaded."
      GZIP_FAILED=1 # Создаём флажок, что упаковка сорвалась
     else
      echo "[`date +%F-%H-%M-%S`] Result file: $LOCALFILEGZ"
     fi

    4.4 Отправка в облака:

    if [[ $CLOUDUSE -eq 1 ]]; then # Если задано копирование в облако - делаем всякое такое 
     mount | grep "$CLOUDMNT" > /dev/null # Проверяем примонтировано ли уже у нас облако (вывод не важен) 
     if [[ $? -ne 0 ]]; then # Если нет 
      mount $CLOUDMNT # значит монтируем 
     fi 
     if [[ $? -eq 0 ]]; then # если монтирование успешно - копируем туда файл 
      echo "[`date +%F-%H-%M-%S`] Cloud: successfully mounted at $CLOUDMNT" 
      echo "[`date +%F-%H-%M-%S`] Cloud: copying started => $CLOUDFILEGZ" 
      if ! [[ -d $CLOUDPATH ]]; then # Если в облаке нет папки за сегодня 
       mkdir $CLOUDPATH 2> /dev/null # создаём её, ошибки игнорируем 
      fi 
      if [[ -f $LOCALFILEGZ && GZIP_FAILED -ne 1 ]]; then # Если у нас архивирование выше не сорвалось 
       cp -R $LOCALFILEGZ $CLOUDFILEGZ # Копируем архив 
      else 
       cp -R $LOCALFILE $CLOUDFILE # Иначе - копируем большой тяжёлый дамп 
      fi 
      if [[ $? -gt 0 ]]; then # Если не скопировался - просто сообщаем 
       echo "[`date +%F-%H-%M-%S`] Cloud: copy failed." 
      else # Если скопировался - сообщаем и размонтируем 
       echo "[`date +%F-%H-%M-%S`] Cloud: file successfully uploaded!" 
       umount $CLOUDMNT # Размонтирование облака 
       if [[ $? -gt 0 ]]; then # Сообщаем результат размонтирования (если необходимо)
        echo "[`date +%F-%H-%M-%S`] Cloud: umount - failed!" 
       fi # Конец проверки успешного РАЗмонтирования 
      fi # Конец проверки успешного копирования 
     else # если монтирование НЕуспешно - сообщаем 
      echo "[`date +%F-%H-%M-%S`] Cloud: failed to mount cloud at $CLOUDMNT" 
     fi # Конец проверки успешного монтирования 
    fi # Конец проверки необходимости выгрузки в облако

    4.5 Завершение

    fi # Конец проверки успешного выполнения mysqldump
    echo "[`date +%F-%H-%M-%S`] Stat datadir space (USED): `du -h $LOCALPATH | tail -n1`" # вывод размера папки с бэкапами за текущий день
    echo "[`date +%F-%H-%M-%S`] Free HDD space: `df -h /home|tail -n1|awk '{print $4}'`" # вывод свободного места на локальном диске
    echo "[`date +%F-%H-%M-%S`] All operations completed!"
    exit 0 # Успешное завершение скрипта

    5. Устанавливаем задачу в cron

    Из под root запускаем crontab -e. Подробности по работе с crontab можно найти здесь: Codenet.ru | Ubuntu.ru

    В окне запустившегося редактора пишем нижеследующее:

    # в качестве командного интерпретатора использовать /bin/sh
    SHELL=/bin/sh
    # результаты работы отправлять по этому адресу
    MAILTO=example@site.com
    # Запуск скрипта дампа боевой БД и запись в лог
    0 8,20 * * * bash ~/db_backup.sh >> ~/db_backup/db_backup.log

    Важна последняя команда:

    • 0 — в ноль минут 8,20 — в 8 часов утра и 20 часов вечера (без пробела) * — каждый день — каждой недели * — каждого месяца;
    • запускается интерпретатор bash;
    • который получает путь к скрипту ~/db_backup.sh (а равно /root/db_backup.sh, если всё происходит под рутом);
    • выполняет его;
    • а вывод дописывается (>>) в файл лога ~/db_backup/db_backup.log

    Сразу разъясню простой момент с угловыми скобками:

    • > (равносильно 1> ) — перенаправление всего вывода в указанное место с перезаписью. Существующий файл перезаписывается полностью, отсутствующий — создаётся.
    • 2> — перенаправление вывода ошибок stderr в указанное место. Если отправить в /dev/null, то сообщений об ошибках в выводе на экране не окажется.
    • >> — перенаправление вывода без перезаписи. Если файла нет — он создаётся, если файл есть — результат дописывается в его конец. Подробнее о перенаправлениях выводов можно прочесть здесь: OpenNET.ru. Там очень богатый функционал и синтаксис.

    Пример конечного лога

    [-----------------------------[2017-01-01-17-40-50]-----------------------------]
    [2017-01-01-17-40-50] Run the backup script...
    [2017-01-01-17-40-50] Generate a database backup: 'mybigdatabase'...
    [2017-01-01-17-44-17] Dumping successfull! Packing in GZIP...
    [2017-01-01-17-47-36] Result file: /root/db_backup/2017-01-01/mybigdatabase-2017-01-01-17-40-50.sql.gz
    [2017-01-01-17-47-38] Cloud: successfully mounted at /mnt/yadisk.
    [2017-01-01-17-47-38] Cloud: copying started => /mnt/yadisk/db_backup/2017-01-01/mybigdatabase-2017-01-01-17-40-50.sql.gz
    [2017-01-01-17-48-58] Cloud: file successfully uploaded!
    [2017-01-01-17-48-58] Stat datadir space (USED): 666M   /root/db_backup/2017-01-01
    [2017-01-01-17-48-58] Free HDD space: 100500G
    [2017-01-01-17-48-58] All operations completed!

    Заключение

    На этом пока всё.

    В планах сделать лимиты на объём папок с бекапами. При превышении заданного лимита — удалять старые бекапы.

    Это будет во второй версии. Когда-нибудь.

    Принимаю инфу об ошибках, критику и предложения.

  • Русификация NetDrive 2.6

    Интерфейс NetDrive на момент публикации поста

    Я был искренне удивлён, что в рунете до момента написания поста не всплывало русификатора этой прекрасной утилиты. Она платная, варез обсуждать не будем. А вот перевод очень важен. Если его и реально найти, то для чрезвычайно устаревших версий и со всяким говном вдовесок.

    Поэтому я решил сделать свой перевод. Переведено 100% фраз, но просмотреть как отображаются некоторые из них мне не удалось. Поэтому сорри, если где-то всплывёт косяк в отрисовке интерфейса.

    Версия NetDrive, на которой тестировался перевод — 2.6.15.953, но в теории должно подойти к любой минорной.

    (далее…)
  • Ошибка Laravel 5.3 — Exception in random.php line 185: There is no suitable CSPRNG installed on your system

    Ошибка Laravel 5.3 — Exception in random.php line 185: There is no suitable CSPRNG installed on your system

    Столкнулся с ошибкой после установки Laravel 5.3 на VPS.

    Exception in random.php line 185:
    There is no suitable CSPRNG installed on your system

    Коротко, конфигурация сервера:

    $ cat /etc/redhat-release
    CentOS release 6.6 (Final)
    $ php -v
    PHP 5.6.27 (cli) (built: Oct 14 2016 13:58:34)
    Copyright (c) 1997-2016 The PHP Group
    Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with XCache v3.2.0, Copyright (c) 2005-2014, by mOo
    with XCache Optimizer v3.2.0, Copyright (c) 2005-2014, by mOo
    with XCache Cacher v3.2.0, Copyright (c) 2005-2014, by mOo
    with XCache Coverager v3.2.0, Copyright (c) 2005-2014, by mOo
    $ httpd -v
    Server version: Apache/2.2.15 (Unix)
    Server built:   Oct 16 2014 14:45:47

    Эта ошибка Laravel решается элементарно.
    (далее…)

  • Пупсик. Цепная передача (ч.3)

    Пупсик. Цепная передача (ч.3)

    Часть 1: Пупсик. Я его купил! (ч.1)

    Часть 2: Пупсик. Первые вложения, первые впечатления (ч.2)


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

    С чем я заморочился дальше?

    (далее…)
  • Пупсик. Первые вложения, первые впечатления (ч.2)

    Пупсик. Первые вложения, первые впечатления (ч.2)

    Часть 1: Я его купил!

    Часть 3: Пупсик. Цепная передача (ч.3)


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

    Можете считать, что я понемногу, ненавязчиво стал заниматься своим здоровьем. Но мне это не присуще и потому странно.

    (далее…)
  • Пупсик. Я его купил! (ч.1)

    Пупсик. Я его купил! (ч.1)

    Привет. Не так давно сбылась одна небольшая, очень давняя и чисто летняя мечта: я купил велосипед.

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

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

    Но я держался за розовый руль и был безмерно счастлив.

    Что это?

    • Модель — Stels Navigator 830 Disc 2011 года;
    • Размер колёс — 26 дюймов;
    • Размер рамы — неизвестен, без опознавательных знаков.

    Покупался в 2011 году, до меня сменил как минимум двух хозяев.

    Влюбился я в этот девайс моментально, с первого взгляда на единственную фотографию, которую предоставил продавец в объявлении:


    Тем сильнее мне повезло, что эта модель выпускалась в двух вариантах: с дисковыми тормозами и блевотными v-brake. Вот так когда-то выглядел Disc-эдишн, который мне в итоге достался:

    Ценник был озвучен 8500 рублей. Зацепило меня то, что даже за эту цену я нигде не найду подобный велосипед на двойных ободах и с дисковыми тормозами. На тот момент я был в этом уверен, хотя всё, что я мог представлять о велосипедах — новые хотя бы с подобными критериями стоят дороже раз в *дцать.

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

    Вот фотография с другого ракурса, когда я уже его купил, а парень пошёл за бутылкой для воды:

    Помимо вышеобозначенного также было замечено, что регулировки вилки не работают (пластиковые вертелки сверху бесполезны и выступают уже видимо в роли заглушек), размер рамы оказался не совсем под мой почти двухметровый рост. За вилкой рама имеет диагональный шрам от аргоновой (как заверил продавец) сварки (хорошо видно на первом фото). Когда я уже поехал домой оказалось, что колёса кривые (обе восьмёрки), чего я не заметил сразу.

    Перечислю детально чем обусловлена моя покупка.

    Плюсы:

    • сам факт наличия и достаточная работоспособность дисковых тормозов: механизмы и диски в пригодном состоянии;
    • целые камеры;
    • живая вилка;
    • не скрипящие, не хрустящие втулки и каретки;
    • алюминиевая рама;
    • наличие неродной подножки;
    • диски на двойных ободах;
    • рабочие шифтеры;
    • не самый плохой задний переключатель Shimano Altus;
    • целые покрышки (без дыр, трещин и пр.);
    • задние звёзды достаточно живые, не сточены;
    • со слов продавца, передвигался байк по городу и вовремя смазывался.

    Минусы:

    • стёртые покрышки, обе разные;
    • восьмёрки на обоих колёсах, заднее при езде задевало раму;
    • сорваны многие гайки у спиц;
    • старое родное седло, местами изношенное и грязное по бокам (где тканевые вставки);
    • поломанные и исцарапанные от падений пластиковые корпуса шифтеров на руле;
    • сами эти манетки совмещены с тормозами;
    • ручки тормозов на обеих манетках болтаются по вертикали;
    • порванные (!) и смотанные проволокой на коленке тросы переднего и заднего переключателей, что не способствовало нормальному переключению скоростей;
    • розовый, туды его в нос, руль!
    • вцелом ужасное состояние покраски практически во всех местах;
    • вынос руля видимо тоже хотели покрасить, в итоге оставили просто наполовину и неаккуратно обшкуренным наждачкой;
    • неочень удачно проваренная скоба переднего переключателя Shimano Tourney;
    • …который уже не мог нормально возвращаться в исходное положение на 1 звезду;
    • задний переключатель тоже в убитом состоянии, не настроен;
    • не самые лучшие педали и местами уже не той формы, что должна быть;
    • трос заднего тормоза уже на износе в месте крепления к механизму;
    • передние звёзды сточены;
    • нет крыльев;
    • уставшая цепь;
    • …без замка.

    Плюшечки и бонусы:

    • здоровенная цепь с замком и тремя ключиками;
    • металический держатель бутылки на раме;
    • сама бутылочка;
    • …мысли об успешном лете.

    И я руководствовался минусами.

    Почему?

    Я считаю, что человек, который покупает велосипед (да что бы то ни было ещё) с рук, ни в коем случае никогда и ни при каких условиях не должен расчитывать на «сел и поехал». Нельзя это.

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

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

    Философия «сел и поехал» при покупке б/у техники по-моему применима только к дебилам.

    На момент покупки я полностью понимал с чем мне придётся столкнуться. И сознательно купил с рук груду металла за N рублей, чтобы вложиться ещё на X*N их же.

    А логика здесь очевидна. Я изучаю рынок, запчасти и всяческие велонюансы в то время, пока моими руками велосипед восстанавливается. Ещё поговаривают, что нормальных велосервисов у нас в городе нет, поэтому вариант «отдать и заплатить, чтобы сделали «хорошо»» не покатит, а мне он и не нужен.

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

    Попутно выслушиваю от близких и знакомых о том, какой же я долбо-, простите, -ёб, что купил вот ЭТО. Нытьё в духе «да нафига тебе эта развалюха?», «да он же такой-сякой», и вообще «лучше бы подкопил, купил новый, не разбитый, побольше, побыстрее, вот такой модели, да вон у того парня». У всех сразу находятся многочисленные знакомые, которые дёшево продают крутые велосипеды.

    Может быть, я и поторопился, но не жалею. Я уже обрёл своё счастье.

    И имя ему — Пупсик.


    Часть 2: Пупсик. Первые вложения, первые впечатления (ч.2)

    Часть 3: Пупсик. Цепная передача (ч.3)