понедельник, 31 августа 2020 г.

Привязать USB устройство к конкретному ttyUSB в Linux

Это делается через настройку udev.

1) Создаем новое правило udev:

    vim /etc/udev/rules.d/91-myrule.rule

2) По сути для того, чтобы создать стабильный алиас для устройства достаточно одной строки:

 ACTION=="add",ENV{ID_BUS}=="usb",ENV{ID_SERIAL}=="usb_serial",SYMLINK+="ttyUSBPort4"

ttyUSPPort4 - это будущее имя устройства, оно, как и все, будет в /dev/

а вот на ID_SERIAL остановимся чуть подробнее:

цитируя udev wiki: "To get definitive information of the device you can use either ID_SERIAL or ID_SERIAL_SHORT". Так что на самом деле для идентификации годятся 2 параметра.

Посмотреть их можно так:

udevadm info /dev/ttyUSBX - где X номер вашего устройства.

Если какой у него сейчас номер тоже не известно - вот способ его определить:

делаем lsusb, видим список всех устройств и их usb_serial

Потом грепаем по очереди все ttyUSB

grep PRODUCT= /sys/bus/usb-serial/devices/ttyUSB1/../uevent

и смотрим, какой serial к какому устройству относится.

среда, 15 января 2020 г.

Осиротевшее обновление debian

Посередине обновления debian сдохла связь, а screen я запустить забыл и процесс завис:
1) Проверяем:
  aptitude

Будет ошибка вида: Could not get lock /var/lib/dpkg/lock

2) Ищем процесс
  ps aux | grep -i apt

..........
  root     13114  3.0  5.9 103704 62592 ?        S     2019 15:10 apt-get upgrade
..........

3) Переключиться на этот процесс не получилось, убиваем его:
  kill -9 13114

4) Теперь система знает, dpkg прервали, запускаем:
  dpkg --configure -a

5) Теперь все работает, перезапускаем апгрейд
apt-get upgrade

понедельник, 20 июля 2015 г.

Восстановить пароль администратора ZTE F660

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

  1. http://192.168.1.1/hidden_version_switch.gch - при смене сбрасывается пароль
Правда, использование этого способа может отключить вам телефон, пока вы не вернете нормальную версию языка на место. Но вы же все равно не собирались оставлять себе китайский? =)
  1. http://192.168.1.1/manager_dev_conf_t.gch - при сбросе настроек - сбросится и пароль
Больше информации можно накопать тут:

четверг, 19 февраля 2015 г.

Php 5.5 & Apache 2.4

Апач ставлю из репозитариев, пхп собирается из сорцов.

Настраиваем конфигурацию пхп, указываем путь к apsx2. Для этого нужно установить apache2-dev.
Компилим пхп, ставим его.

После  установки может появиться ошибка: Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.
Тогда надо скомпилить пхп с --enable-maintainer-zts или поставить апачу mpm_prefork

make install добавит загрузку модуля пхп к апачу ( mods-available/php5.load )
Остается только добавить SetHandler

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

В Апаче 2.4  реализована загрузка модулей путем подгрузки всех файлов из /etc/apache2/mods-enable
Добаляются они туда из mos-available с помощью команд a2enmods. Создаем для модуля php5  конфиг файл (mods-available/php5.conf) и добавляем туда SetHandler.
выклчаем/включаем модуль, файл конфига копируется в mods-enable. Осталось рперезагрузить Апач: 
service apache2 restart


среда, 2 апреля 2014 г.

PHP extension на с++

По умолчанию extension создается для компиляции с-компилятором. Для переключения на с++ есть такой вариант:
1)vim config.m4
2) в блок if test "$PHP_GT_TEST" != "no"; then
  добавить:
  PHP_REQUIRE_CXX()
  PHP_SUBST(GT_TEST_SHARED_LIBADD)
  PHP_ADD_LIBRARY(stdc++, 1, GT_TEST_SHARED_LIBADD)
3) В PHP_NEW_EXTENSION(ext, ext.c, $ext_shared)
поменять ext.c => ext.cc
4) phpize

Создать php extension в unix

Шаги:
1) cd /path_to_php_src/ext
2) ./ext_skel --extname=name
3) cd name
4) vim config.m4, там убрать dnl со строк:
dnl PHP_ARG_ENABLE(gt_test, whether to enable gt_test support,
dnl Make sure that the comment is aligned:
dnl [  --enable-gt_test           Enable gt_test support])
или со строк
dnl PHP_ARG_WITH(gt_test, for gt_test support,
dnl Make sure that the comment is aligned:
dnl [  --with-gt_test             Include gt_test support])
5) phpize
6) ./configure && make && make install

понедельник, 31 марта 2014 г.

Немного установки php

  Configuration File (php.ini) Path => /etc/php5/apache2
  Loaded configuration file => (none)

Если php в упор не видит свой ini file, хотя при компиляции ему ясно указали
  --with-config-file-path=/etc/php5/php.ini
то все просто, надо указывать папку, а не сам файл. Как-то так:
  --with-config-file-path=/etc/php5
и тогда он сам найдет там php.ini

среда, 12 февраля 2014 г.

В mysql записываются знаки вопроса вместо русского

Внезапно, встретился с такой проблемой. Из c++ передавался русский в кодировке windows-1251, таблица - cp1251_general_ci, а записываются все равно ????? Решение оказалось просто - надо после установки соединения 1 раз вызвать:
  mysql_query(conn, "SET NAMES cp1251");

вторник, 11 февраля 2014 г.

Идентификация пользователя

Стал разбираться, как бы точнее идентифицировать пользователя, нашел неплохую статью:
http://javascript.ru/unsorted/id Оставлю тут ссылку, чтобы не потерять.
Сайт, который использует это:
https://panopticlick.eff.org/index.php

понедельник, 3 февраля 2014 г.

Множественные запросы к MySQL

Множественный запрос к MySQL - это запрос, содержащий несколько выражений, записанных через ; Для того, чтобы его провести, при установке соединения нужно указать флаг CLIENT_MULTI_STATEMENTS. Как-то вот так:

mysql_real_connect(mysql, host, user, pwd, db, port, socket, CLIENT_MULTI_STATEMENTS);

Этот флаг так же ставит CLIENT_MULTI_RESULTS. Соответственно, теперь можно будет использовать. Осталось только получить результаты их выполнения. Главная - не забыть, что возвращаются результаты последовательно с каждого выражения, а не только с тех ,кто эти результаты может вернуть. Это, в общем-то, логично, дает возможность узнать, например, количество строк, затронутое каждым из выражений.

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

if (mysql_query(mysql, "CALL my_proc(@a, @b); SELECT @a, @b;") != NULL) {
  if (mysql_next_result(mysql)) > 0)
    cout << "mysql_next_result error" << endl;
    MYSQL_RES *result = mysql_store_result(mysql);
    if (result) {
      ...
      mysql_free_result(result);
    }
    else
      cout << "mysql_store_result error" << endl;
  }
else 
  cout << "mysql_query error" << endl;

Если неизвестно, возвращает ли что-нибудь выражение - можно проверить командой mysql_field_count.

Информация - из документации.

четверг, 30 января 2014 г.

typedef в классах

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

class MyClass {
public:
  typedef map<int, std::string> mymap_type;
private:
  mymap_type mymap;
public:
  ...
  mymap::iterator get_map_beg() {
    return mymap.begin();
  }
}

...

int main() {
  MyClass myclass_var;
  MyClass::mymap_type::iterator it = myclass_var.get_beg();
}

Очевидно, сам класс итератора можно было тоже сделать typedef в классе =)

Плюсов довольно много. Значимые для меня:
 + Уходят длинные некрасивые строки с шаблонами, читать становится проще
 + Проще потом поменять тип, если что-то изменилось. Не надо лазить по всему коду и править типы.

Минусы:
 - могут возникнуть проблемы с зависимостями

среда, 29 января 2014 г.

Немного о блокировках в хранимых процедурах MYSQL

Возникла необходимость вызывать одну и туже хранимую процедуру MYSQL из разных процессов. И невольно задумался о синхронизации средствами самой СУБД. Вот, что я раскопал:

Стандартные LOCK_TABLE() внутри хранимых процедур вызывать нельзя.

Транзакции (START TRANSACTION) сами блокировки не ставят, так что просто создать innodb таблицу не поможет =)

Есть такой вариант : SELECT ... FOR UPDATE. Он блокирует только строки, которые прочитал до дальнейшего UPDATE. Этот UPDATE должен быть в пределах этой же транзакции, иначе будут проблемы (блокировка не снимется, насколько я понял)

Подошедший мне вариант был такой:  GET_LOCK(name, timeout) и RELEASE_LOCK(name).
Работает это все по принципу мутексов. Успешная блокировка возвращает 1, т.е.
SELECT SET_LOCK("my_lock", 10);
 -> 1
Если вернулся 0 - значит заблокировал кто-то другой и таймаут истек. А если вообще NULL - то произошла ошибка.
name - задается строкой.
SELECT RELEASE_LOCK("my_lock") вернет 1, если успешно снял блокировку, 0 - если не смог, потому что ее выставил другой поток и NULL - если такой блокировки нет (например, уже сняли, или таймаут истек.)

Для работы с RELEASE_LOCK неплохо подходит оператор DO
DO RELEASE_LOCK("my_lock");
В отличие от SELECT он просто не вернет результат который очень часто от RELEASE и не требуется.

Проверить наличие блокировок можно функциями IS_FREE_LOCK(nameи IS_USED_LOCK(name).
Принцип возврата - такой же. 1 - если ответ "да", 0 - если "нет" и NULL - если такой блокировки вообще не найдено.

Источник информации - документация :)

MYSQL таблица MEMORY ограничена в размере и не заполняется

При тестах понадобилось создать таблицу типа MEMORY и оказалось, что необходимый объем данных не влезает. Выше определенного числа строки просто не создаются с ошибкой:
The table НАЗВАНИЕ ТАБЛИЦЫ is full

По факту - у MYSQL просто кончилась память под размещение данных в куче. Легко изменить это в настройках MYSQL (в Linux - по умолчанию /etc/my.cnf):
max_heap_table_size=256M

среда, 22 января 2014 г.

Локальные данные в потоках

Появилась необходимость хранить в каждом потоке свои static локальные данные.
Решение:

В c++11 появился thread_local, который объявляет переменную локальной для потока. Соответственно, сколько потоков - столько переменных будет создано.
В gcc для этой же цели есть __thread. Используется оно, как и другие спецификаторы класса:
__thread int i;
Можно использовать совместно с static или extern, но тогда оно обязательно должно стоять сразу после них.
Ссылка на официальный сайт.

И еще немного с++

Встретил очередной нюанс с++:

Если класс не содержит явного копирующего конструктора или operator=, то они создаются неявно.
Об этом надо помнить.

Допустим у нас есть класс, который содержит в себе указатель на свой буффер.



class buf_t
{
  unsigned char* data;
public:
  buf_t(size_t buf_size)
  {
    data=new unsigned char[buf_size];
    printf("buf_t(): data=%p\n",data);
  }

  ~buf_t()
  {
    printf("~buf_t(): data=%p\n",data);
    delete[] data;
  }

};


Легко ошибиться и выполнить присваивание или вызвать копирующий конструктор для такого объекта.
Вот такой код запросто скомпилируется и будет работать неправильно.


int main(int argc,char** argv)
{
  buf_t a(1000);

  buf_t b(a);

  buf_t c(500);
  c=a;


  return 0;
}


Вывод программы будет такой:


buf_t(): data=00902DCC
buf_t(): data=009031B8
~buf_t(): data=00902DCC
~buf_t(): data=00902DCC
~buf_t(): data=00902DCC



Т.е. мы присвоили указатель data объекта a объектам b и c.
В результате у нас 3 раза освободился один и тот же указатель, а data объекта c вообще потерялся.

Решение — сделать private копирующий конструктор и operator=. При этом достаточно их просто объявить, тело функций добавлять не надо.


class buf_t
{
  unsigned char* data;
public:
  buf_t(size_t buf_size)
  {
    data=new unsigned char[buf_size];
    printf("buf_t(): data=%p\n",data);
  }

  ~buf_t()
  {
    printf("~buf_t(): data=%p\n",data);
    delete[] data;
  }

private:
    buf_t(const buf_t&);
    void operator=(const buf_t&);

};

Описание взял отсюда, там же есть еще интересные факты:
http://www.rsdn.ru/forum/cpp/4896711.all
Стал работать с gdlib.
Нашел актуальное описание API тут:
http://www.boutell.com/gd/manual2.0.33.html#reference

понедельник, 14 октября 2013 г.

Передача Windows-1251 (cp1251) с помощью POST и AJAX на сторону сервера.

Внезапно, я обнаружил, что POST AJAX упорно передает мою строку в UTF-8, игнорируя все попытки указать ему кодировку. А серверные программы настроены принимать только windows-1251 и это вызывает некий конфликт. И выражается он в том, что русский текст становится текстом кракозябровым.
Некоторое время погуглив я обнаружил, что нормальное решение этой проблемы как-то не особо существует и основное мнение комьюнити показано, например, здесь. Краткое резюме:
это нельзя, потому что нельзя, используй перекодировку. Я же, со своей стороны решил, что вариант с удвоением трафика + потерей мощности меня не слишком радует.
Дальнейшие раскопки привели меня к причинам такого поведения AJAX: w3. Там написано, что строку надо передавать в UTF-8 и ничего больше не волнует. Но что более интересно, там сказано, что другие варианты можно передавать и не как UTF-8. Например: ArrayBuffer или Blob.
Покопав в этом направление, я нашел еще 1 статью. Этот вариант относится к новым возможностям, появившимся относительно недавно.

Идея проста:
Строка - это тот же массив символов. Просто ajax передаст ее массив 2вубайтовых чисел, а мы хотим передавать массив однобайтовых. Значит, чтобы передать строку на сервер в windows-1251 надо просто записать коды windows-1251 символов нашей строки в массив однобайтовых чисел. А на стороне сервера - просто прочитать из тела запроса как готовую строку в кодировке windows-1251.

Как это сделать:

1) Берем нашу строку data_str и какой-либо функцией меняем ее кодировку на нужную(в моем случае - это windows-1251). Такую функцию легко написать самому или найти на просторах сети, например, тут.

var converted_str = convertToWin1251(data_str);

2) Мы получили converted_str, которая все еще считается строкой в UTF-8, но содержит уже коды необходимой кодировки. Просто так послать ее нельзя, ибо AJAX все равно будет трактовать ее, как UTF-8 и попытается конвертировать, что окончательно ее испортит.
Поэтому, мы создаем массив 8мибайтовых неотрицательных чисел размером под нашу строку:

var send_arr = new Uint8Array(converted_str.length);

3) Теперь осталось только заполнить этот массив

for(var i = 0; i < converted_str .length; ++i)
send_arr[i] = converted_str.charCodeAt(i);

4) выставить правильную кодировку и отправить его:

ajaxVar.open('POST', 'http://FOO.BAR', 1);
ajaxVar.setRequestHeader('Content-Type', 'text/plain; charset=windows-1251');
ajaxVar.send(send_arr);

где ajaxVar - это созданный ajax-запрос.
Собственно, все.

Осталось только принять данные на строне сервера. Они передаются как RAW POST DATA. Неплохо было бы, чтобы принимающая сторона умела работать с ней. С++ С#/ASP.NET насколько я помню, проблем с этим не имеют, PHP это делает так.

P.S. Если кто-то не согласен, нашел способ лучше или просто есть что сказать по существу - добро пожаловать в комментарии =)

четверг, 21 февраля 2013 г.

Добавить поддержку jpeg к gd в php

проверяем наличие и состояние gd:
  php -i 
в секции gd
Если есть строка
  JPEG Support => enabled
то все уже хорошо.

Если ее нет, то:
1) Качаем jpeg, например, в /usr/local/jpeg
2) Компилим jpeg
3) Пересобираем пхп c --with-jpeg-dir=/usr/local/jpeg (./configure && make && make install)
4) Проверяем php -i , должна появиться строка о поддержке jpeg

Не забудьте перезапустить веб-сервер

понедельник, 11 февраля 2013 г.

phpMyAdmin выдает пустые страницы

Для начала стоит проверить логи веб-сервера. В моем случае там было child pid номер exit signal Segmentation fault (11). Немного погуглив, я выяснил, что это проблма взаимодействия phpMyAdmin'а и ускорителей типа eaccselerator или apc.
Решение просто: добавить в конфиг-файл апатча строку php_admin_flag apc.enabled Off.
После этого phpMyAdmin перестанет использовать apc и проблема пройдет.

воскресенье, 10 февраля 2013 г.

Немного о Интернет и whois

Internet Corporation for Assigned Names and Numbers, или ICANN (читается айкэ́н) — международная некоммерческая организация, созданная 18 сентября 1998 года при участии правительства США для регулирования вопросов, связанных с доменными именамиIP-адресами и прочими аспектами функционирования Интернета.
IANA (от англ. Internet Assigned Numbers Authority — «Администрация адресного пространства Интернет») — американская некоммерческая организация, управляющая пространствами IP-адресов,доменов верхнего уровня, а также регистрирующая типы данных MIME и параметры прочих протоколов Интернета. Находится под контролем ICANN.IANA отвечает за распределение всех зарезервированных имён и номеров, которые используются в протоколах, определённых в RFC.
IANA делегирует свои полномочия по распределению IP-адресов региональным регистраторам в виде диапазонов класса A («/8»). Региональные регистраторы, в свою очередь, делегируют более мелкие диапазоны интернет-провайдерам.
Чтобы получить информацию об ip-адресе(информация - из iana answers(Hints for finding the person responsible for an IPv4 address)):1) Использовать whois сервис, каждого из 5 RIR по очереди, пока ответ не будет найден.
Для оптимизации, можно пользоваться списком отсюда. Или iana whois сервером, который укажет нужный

2) Если не нашлось ничего, значит, ip внутренней сети, выделен какой-то организации(apple, например. см. список выше) или был подделан.

Что есть whois:
Whois - это протокол(rfc), реализован поверх tcp, используется для обращения к whois серверу и получения информации о ip/домене

Как обратиться к whois:
Для этого надо подключиться по адресу к whois серверу(смотри список выше) на порт 43 и послать туда интересующий ip адрес. Сервер вернет либо интересующую информацию, либо сообщение, что у него этого нет. Иногда может указать, где искать с заголовком whois

Еще много информации есть на хабре