воскресенье, 26 декабря 2010 г.

понедельник, 9 ноября 2009 г.

Mongo, Mysql, Ruby and PHP

Вот тут я сравнивал MongoDB и MySQL в Ruby и результат не сильно меня обрадовал, хотя на MongoDB возлагаю большие надежды.
Я провел некоторые дополнительные бенчмарки.
Скрипты для бенчмарков тут: http://github.com/latrommi/benchmarking
Результаты ниже.
----------------------------------------------------------------
For my English friends:
Some days ago I did some MongoDB benchmark tests.
Here is more extended version.
Benchmark scripts: http://github.com/latrommi/benchmarking
and results below.
----------------------------------------------------------------
Вывод один: это не значит, что MongoDB хуже MySQL, это значит, что для нее ещё не написано нормального, быстрого драйвера для Ruby.

Conclusion: no fast Ruby driver for MongoDB.

вторник, 13 октября 2009 г.

MongoDB VS MySQL


Just insert test.


  1. #!/usr/bin/ruby



  2. require 'rubygems'

  3. require 'benchmark'



  4. require 'mongo'

  5. require 'mysql'



  6. # init benchmark cycle

  7. def cycle

  8. 10000.times{ |i|

  9. doc = {

  10. "text" => "i am any text and a little tail with me: #{i}",

  11. "count" => i,

  12. "coords" => {"x" => 203 + i, "y" => 102 + i}

  13. }



  14. yield doc

  15. }

  16. end



  17. # init mysql

  18. mysql = Mysql.new('localhost', 'testuser', 'testpass', 'test')

  19. mysql.query("DROP TABLE IF EXISTS `insert_bm`")

  20. mysql.query("DROP TABLE IF EXISTS `insert_bm_coords`")



  21. mysql.query("CREATE TABLE `insert_bm_coords`(

  22. `id` int unsigned not null auto_increment,

  23. `x` int not null,

  24. `y` int not null,

  25. PRIMARY KEY (`id`)

  26. )")



  27. mysql.query("CREATE TABLE `insert_bm`(

  28. `id` int unsigned not null auto_increment,

  29. `text` varchar(255) not null,

  30. `count` int not null,

  31. `coords_id` int unsigned not null,

  32. PRIMARY KEY (`id`)

  33. )")



  34. # init mongodb

  35. mongo_db = Mongo::Connection.new.db("ololo_db")

  36. mongo_db.collection("beta").drop

  37. mongo = mongo_db.collection("beta")



  38. # do benchmarking

  39. Benchmark.bm {|x|



  40. x.report("mysql:") {

  41. cycle{|doc|

  42. mysql.query("INSERT insert_bm_coords(x,y) VALUES(#{doc["coords"]["x"]}, #{doc["coords"]["y"]})")

  43. mysql.query("INSERT insert_bm(text, count, coords_id) VALUES('#{doc["text"]}', #{doc["count"]}, #{mysql.insert_id()})")

  44. }

  45. }



  46. x.report("mongodb:") {

  47. cycle{|doc|

  48. mongo.insert(doc)

  49. }

  50. }

  51. }





Result:

10_000:
user system total real
mysql: 0.300000 0.150000 0.450000 ( 1.763819)
mongodb: 5.690000 0.680000 6.370000 ( 7.201129)

1_000_000:
user system total real
mysql: 30.960000 12.950000 43.910000 (179.318003)
mongodb:569.650000 18.410000 588.060000 (678.889538)

UPDATE: after installing C extension (`gem install mongo_ext`).


10_000:
user system total real
mysql: 0.280000 0.110000 0.390000 ( 1.679100)
mongodb: 3.110000 0.270000 3.380000 ( 4.089022)

1_000_000:
user system total real
mysql: 32.400000 13.030000 45.430000 (179.684186)
mongodb:326.150000 17.000000 343.150000 (423.631974)


I'm confused. Can anybody explain it?

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

UPDATE: here is explanation: http://blog.knopkodav.ru/2009/11/mongo-mysql-ruby-and-php.html

пятница, 31 июля 2009 г.

Gentoo + rails + passenger + nginx


I installed ruby by compiling it myself (portage handled ruby doesn't quite do
it for me...). Then I installed the passenger gem 2.2.4. After installing
passenger gem went to the root passenger dir and ran "rake nginx" to get the
helperserver needed. Then I copied the nginx-0.7.61.ebuild and modified it to
include the use flag passenger. Then using the hint from the ebuild attached to
this bug got the full path for the nginx passenger module and put that into my
ebuild.

Then added the passenger use flag to /etc/portage/package.use for nginx and
emerged nginx 0.7.61 with passenger.

Added the config info to /etc/nginx.conf and I'm away everything works very
nicely :)


via http://bugs.gentoo.org/266446

вторник, 28 июля 2009 г.

Любителям длинных имён переменных

%username%, помни:
url -- полный путь к странице: http://localhost/blog/2009/07/28/kak-ya-upal-v-rechku
path -- только путь: blog/2009/07/28/kak-ya-upal-v-rechku

И не надо никаких названий переменных, типа: full_path, relative_path, etc.

среда, 22 июля 2009 г.

Converting Drupal tables to RoR from any to any database.

OK, OK, it's fairly not only for Drupal source databases :-)

STEP 1 - init databases connections
Create two new connections in database.yml file like this:


# DATABASE CONVERTING SPECIFIC
# old connection
old:
adapter: mysql
database: dbname
username: username
password: userpass
host: localhost

# new connection (may be like your development or production connection)
new:
adapter: postgresql
database: dbname
username: username
password: userpass
schema_order: development # for example
host: localhost


STEP 2 - write rake task
create convert.rake file in your lib/tasks rails application directory

1 namespace :db do
2 namespace :convert do
3 task :old2new => :environment do
4 print "OK, let's do it now!\n"; STDOUT.flush
5
6 # define universal model for old tables
7 class OldModel < ActiveRecord::Base
8 end
9
10 # demonic convertor
11 def convert(srctable, dstclass)
12 print "- converting class " + dstclass.to_s + "...\n"; STDOUT.flush
13
14 dstclass.establish_connection(:new)
15 dstclass.delete_all
16
17 OldModel.set_table_name(srctable)
18 OldModel.find(:all).each { |old|
19 new = dstclass.new
20 new = yield(old, new)
21 new.save(false)
22 }
23 end
24
25 # connect to old dying database
26 ActiveRecord::Base.establish_connection(:old)
27
28 # CONVERTING
29
30 # users
31 convert('rctc_users', User) {|old, new|
32 # prepare each field individually, yeah.
33 new.id = old.uid
34 new.login = old.name
35 new.email = old.mail
36 new.password = Digest::MD5.hexdigest(old.pass + SALT)
37 new
38 }
39
40 # convert your tables below like above
41 # ...
42
43 print "Wow! Processing complete!\n"
44 end
45 end
46 end

STEP 3 - RUN IT!

$ rake db:convert:old2new

суббота, 18 июля 2009 г.

Как починить man, less и другие проблемы tty в OpenVZ

сабж.

# rm /dev/tty
# mknod -m 666 /dev/tty c 5 0


пруфлинк: http://forum.openvz.org/index.php?t=msg&goto=34878&

понедельник, 16 июня 2008 г.

PHP $argv ахтунг.

argv.php
#!/usr/local/bin/php -q
print_r($argv);

FreeBSD:
% ./argv.php a b c
Array
(
[0] => ./argv.php
[1] => a
[2] => b
[3] => c
)

Gentoo Linux:
$ ./argv.php a b c
Array
(
[0] => a
[1] => b
[2] => c
)


WTF?



UPD:
http://bugs.php.net/bug.php?id=44673

среда, 23 апреля 2008 г.

OpenOffice Macro security button bug #81230

В OpenOffice не работает кнопка Macro Security.

1) находим ~/.openoffice.org2/user/registry/data/org/openoffice/Office/Common.xcu
2) в секцию
<node oor:name="Security">
<node oor:name="Scripting">
...
</node>
</node>

вставляем свойство:
<prop oor:name="MacroSecurityLevel" oor:type="xs:int">
<value>1</value>
</prop>

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

Говорят, это зависит от билда мозиллы при сборке ОО.
Источник.

понедельник, 21 апреля 2008 г.

Потрошим Interbase .gdb файлы

Interbase поразил очевидностью своей эксплуатации.

Была задача извлечь из .gdb файла содержимое и перелить в другую БД. Сразу скажу, что с Interbase я вообще никогда не сталкивался, поэтому рассуждения, что называется, с нуля.

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

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

# emerge firebird -v
# cp /path/to/your/database-file.gdb /usr/lib/firebird/

На любителя, можно еще для гарантии добавить:
# chmod 666 /usr/lib/firebird/database-file.gdb

$ fbsql -u SYSDBA -p masterkey /usr/lib/firebird/database-file.gdb -ch WIN1251
Database: /usr/lib/firebird/database-file.gdb, User: SYSDBA
SQL>

Ура! В этот момент мы имеем работающую БД и консольку, откликающуюся на запросы.

Почему базу скопировали в /usr/lib/firebird ?
Потому что иначе не будет работать нестандартная кодировка. Можно настроить т.н. embeded вариант, но он предполагает наличие ./intl/fbintl.so в папке с программой, т.е. fbsql.
Я пробовал добавить это в папку с файлом базы, т.к. в Windows это кажись работало (как это делают в программах от Борланда, прости, Господи):
$ mkdir ./intl
$ cp /usr/lib/firebird/fbintl.so ./intl/
однако нифига счастливого не произошло. Будет дешевле скопировать саму базу куда положено.

Проверим, все ли так, как нам надо:
SQL> show tables;
SQL> select * from any_table;

Ну, а дальше все банально:
$ echo "select * from any_table;" > query.sql
$ fbsql -u SYSDBA -p masterkey /usr/lib/firebird/database-file.gdb -ch WIN1251 -i query.sql -o result-1251.txt -pag 99999
$ iconv -f cp1251 -t utf8 result-1251.txt > result-utf.txt

Теперь в result-utf.txt имеем выковыренные запросом данные. Изменение их вида и перегон в другую БД оставлю читателю.

P.S. все вышенаписанное проделано на Gentoo.

среда, 12 марта 2008 г.

PHP Daemon

А теперь немного извращений: демон на PHP.

ЧАСТЬ 1. ПИШЕМ ДЕМОНА.
Описание команд читать в мануалах. По-возможности, я даю на них ссылки.

declare(ticks=1);

$g_signals = array(
  'SIGTERM' => 0,
  'SIGHUP' => 0,
);

$g_ppid = null;
$g_pid = null;

dmn_sys_init(); // сердце демона!

$g_ppid = posix_getppid(); // pid родителя
$g_pid = posix_getpid(); // pid дочернего (текущего) процесса

// поехали!
while(1){
  // делаем что-то полезное.

  if($g_signals['SIGTERM'] == 1) // если получен сигнал завершения процесса, то не спеша, не паникуя тихонечко заканчиваем работу и выходим.
    break;

  if($sleep_time > 0)
    sleep(1); // спать одну секунду (на самом деле это идеологически не правильно, но для шаблона подойдет)
}

function dmn_sys_init(){
  global $g_pid;

  // 1. создаем дочерний процесс. при одном работающем это может быть не нужно, но если планируется запуск одного контрольного и нескольких рабочих процессов, то этот код необходим.
  if(-1 == ($g_pid = pcntl_fork()))
    exit("Could not fork.\n");

  // очень важный момент! Здесь определяем в каком мы процессе после разветвления.
  if($g_pid != 0){
    // 2. мы в родительском процессе
    // тут нам нужно отслеживать завершение дочерних процессов.
    // делается это банально просто: при создании процесса накручиваем счетчик дочерних процессов
    // при завершении дочернего процесса уменьшаем счетчик. Когда дочерних не осталось - выходим.
    // ждать завершения можно командой pcntl_wait.
    // написание этого кода я оставлю читателю в качестве домашного задания

    // для тех, кому лень думать есть приятные новости - дочерние процессы можно не ждать,
    // а делать в лучших традициях мира животных - выкидывать их из гнезда и тихонько помирать.
    exit("The end of parent process.\n");
  }

  // 3. мы в дочернем процессе!
  // отцепляем процесс от консоли
  if(-1 == posix_setsid())
    exit("Could not detach from terminal.\n");

  // устанавливаем хуки для обрабатываемых сигналов
  if(!pcntl_signal(SIGTERM, "dmn_sys_sig_handler"))
  exit("Could not setup SIGTERM handler.\n");

  if(!pcntl_signal(SIGHUP, "dmn_sys_sig_handler"))
  exit("Could not setup SIGHUP handler.\n");
}

// функция-хук обработки сигналов от операционной системы
function dmn_sys_sig_handler($signo)
{
  global $g_signals;

  switch ($signo){
  case SIGTERM:
    $g_signals['SIGTERM'] = 1;
    break;
  case SIGHUP:
    $g_signals['SIGHUP'] = 1;
    break;
  default:
    $g_signals['OTHER'] = $signo;
  }
}


ЧАСТЬ 2. ПИШЕМ RC СКРИПТЫ.
Здесь пример примитивнейшего RC скрипта для Gentoo.
RC скрипт и PHP файлы записать в /etc/init.d/my-php-daemon и /usr/lib/my-php-daemon соответственно.

#!/sbin/runscript

depend() {
  # выставляем зависимости
  need net
}

start() {
  # показываем юзеру что мы делаем
  ebegin "Starting my PHP daemon"

  # ведем лог
  echo --------------------- >> /var/log/my-php-daemon/rc.log
  date >> /var/log/my-php-daemon/rc.log

  # запускаем демоненка
  php-cgi -f /usr/lib/my-php-daemon/index.php >> /var/log/my-php-daemon/rc.log

  # конец
  eend $?
}

stop() {
  # показываем юзеру что мы делаем
  ebegin "Stopping my php daemon"
  # останавливаем демона так - ищем процесс, выполняющий файл /usr/lib/my-php-daemon/index.php и посылаем ему сигнал SIGTERM.
  # внимание! если таких процессов несколько, то все они получат сигналы SIGTERM.
  pkill -TERM -f /usr/lib/my-php-daemon/index.php

  # ведем лог
  date >> /var/log/my-php-daemon/rc.log
  echo --------------------- >> /var/log/my-php-daemon/rc.log

  # конец
  eend $?
}


Таким образом все варнинги и ошибки PHP будут сыпаться в /var/log/my-php-daemon/rc.log, но, к сожалению, без даты. Добавить дату - это будет читателю второе домашнее задание.

Конечно, мануал не претендует на полноту и безупречность, но это лучше, чем ничего. А еще лучше для простого изучения.

БОНУС-ТРЕК
Поскольку PHP бывает весьма не предсказуем, то для контроля работы демона можно написать небольшой cron скриптик:

$g_vs_gw = "http://gw1.viasms.ru?"
$g_vs_eid = "12345";
$g_vs_password = "secure_word";

$g_needed = array(
  'my-php-daemon' => array(
    'regexp'=>'/php-cgi.+my-php-daemon/',
    'reset_cmd'=>'/etc/init.d/my-php-daemon zap --nocolor',
    'start_cmd'=>'/etc/init.d/my-php-daemon start --nocolor'
  ),
);

// fill array with system fields
$needed = array();

foreach($g_needed as $key=>$val){
  $needed[$key] = $val;
  $needed[$key]['running'] = 0;
}

$exec = shell_exec("ps -C php-cgi -o pid= -o command=");
$pss = explode("\n", $exec);

foreach($needed as $key=>$val)
  if(!$val['running'])
    foreach($pss as $ps)
      if(preg_match($val['regexp'], $ps))
        $needed[$key]['running'] = 1;

foreach($needed as $key=>$val){
  if(!$val['running']){
    print date("Ymd-His") . "\n";

    print shell_exec($val['reset_cmd']);
    $cmdresult = shell_exec($val['start_cmd']);
    print $cmdresult;

    $msg = $key . ' service is down. ' . $cmdresult;
    $pass = md5(md5($g_vs_password) . $msg);

    $url = $g_vs_gw . '?' .
      'eid=' . urlencode($g_vs_eid) .
      '&pass=' . urlencode($pass) .
      '&msg=' . urlencode($msg);

    print $url . "\n";
    readfile($url);
    print "\n";
  }
}


Этот скрипт во время своего запуска проверяет все демоны, указанные в массиве $g_needed. Если один из них не работает, то скрипт сбрасывает его состояние (zap) и запускает снова. Ориентировано, опять таки, на дистрибутив Gentoo. Для подстройки для вашего дистрибутива подкрутите элементы массива reset_cmd и start_cmd.

О результате выполнения пишет лог и отправляет SMS сообщение с текстом о состоянии запуска.
В качестве SMS шлюза используется сайт viasms.ru. Для этого в переменных $g_vs_eid и $g_vs_password надо указать id и пароль события.

В результате, работы скрипта к вам придет SMS сообщение примерно следующего содержания:


my-php-daemon service is down. Starting my PHP daemon [ ok ].


И вы сможете дальше спокойно пить пиво :О)

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

Синхронизация Google

Для ищущих способы синхронизации сервисов Google с телефоном, компьютером, конкретным клиентом:

GCALDaemon is an OS-independent Java program that offers two-way synchronization between Google Calendar and various iCalendar compatible calendar applications. GCALDaemon is primarily designed as a calendar synchronizer but it can also be used as a Gmail notifier, Address Book importer, Gmail terminal and RSS feed converter.

пятница, 29 февраля 2008 г.

Как сделать зашифрованный диск

Дано: Gentoo Linux
Рабочая болванка - 1 штука.

Для начала убедимся, что у нас в ядре поставлены нужные галочки (версия 2.6.23):
BLK_DEV_LOOP=y
Prompt: Loopback device support
Location: -> Device Drivers -> Block devices

BLK_DEV_CRYPTOLOOP=y
Prompt: Cryptoloop Support
Location -> Device Drivers -> Block devices -> Loopback device support

В разделе Cryptographic API указать используемые алгоритмы шифрования, в нашем примере:
CRYPTO_TWOFISH=y
Prompt: Twofish cipher algorithm
Location:
-> Cryptographic API

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

(добавлено 20080423): Проверить софт: sys-apps/util-linux должна быть с USE флагом loop-aes.

Затем:
1. создаем чистый файл под размер болванки. В примере ниже будет создан файл 1024*4200k байт.


# dd if=/dev/zero of=./disk.dat bs=1024 count=4200k

2. создаем шифрованный loop device и вводим пароль для шифрования:

# losetup -e twofish256 /dev/loop0 ./disk.dat
Password:

3. создаем файловую систему на вновь созданном устройстве

# mkfs.ext2 /dev/loop0

4. монтируем устройство

# mount /dev/loop0 /mnt/secure-disk

5. После этого в папку /mnt/secure-disk копируем все необходимые данные.
Оставшееся место можно, как обычно, контролировать командой df.

6. Затем размонтируем и удаляем устройство

# umount /mnt/test && losetup -d /dev/loop0

Полученный таким образом файл disk.dat можно записать на болванку. Важно помнить, что файлы больше 2Гб требуют на диске файловую систему UDF, которая, если не ошибаюсь, в Windows не поддерживается. Проблему можно обойти сделав несколько фалов размером до 2 гб и записать диск в обычном формате ISO.

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

(http://knopkodav.blogspot.com/2008/02/blog-post.html)

# losetup -e twofish256 /dev/loop0 ./disk.dat
Password:
# mount /dev/loop0 /mnt/secure-disk -t ext2
...
# umount /dev/loop0
# losetup -d /dev/loop0


Пока не изученные альтернативы:
loop-aes

пятница, 8 февраля 2008 г.

Drupal тип поля password_confirm

Никогда не ставьте
'#maxlength' => ххх,

для необязательных типов полей
'#type' => 'password_confirm',

получите ошибку
"warning: mb_strlen() expects parameter 1 to be string, array given in /var/www/localhost/htdocs/includes/unicode.inc on line 370."

Это связно с тем, что Друпал проверят длинну поля, а поскольку password_confirm - массив из двух полей, то имеем некорректный параметр передаваемый в mbstrlen.

Немного бэктрейса (лишнее вырезано):
warning: mb_strlen() expects parameter 1 to be string, array given in /var/www/html/localhost/htdocs/includes/unicode.inc on line 370.


Array
(
[#type] => password_confirm
[#description] => To change the current password, enter the new password in both fields.
[#maxlength] => 30
[#size] => 40
[#post] => Array
(
[sz_personal_pass] => Array
(
[pass1] =>
[pass2] =>
)
)
[#name] => sz_personal_pass
[#id] => edit-sz-personal-pass
[#value] => Array
(
[pass1] =>
[pass2] =>
)
[#needs_validation] => 1
)

среда, 9 января 2008 г.

Static /dev on Gentoo OpenVZ VPS

(в модификации от 28 июля 2008)

В OpenVZ VPS по-умолчанию почему-то не содержит девайсов /dev/random, /dev/urandom.
Недостаток легко устраняется несколькими действиями:

----- СПОСОБ 1:

1) редактируем файл /vz/private/123/etc/conf.d/rc
в нем меняем RC_DEVICES="static"

После этого подразумевается, что все устройства этой VPS в /dev вы создадите руками.
Этим и займемся:
2) mknod --mode 666 /vz/private/123/dev/ptmx c 5 2
3) mkdir /vz/private/123/dev/pts
4) rm -f /vz/private/123/dev/null
mknod --mode 666 /vz/private/123/dev/null c 1 3
5) mknod --mode 444 /vz/private/123/dev/urandom c 1 9
6) mknod --mode 444 /vz/private/123/dev/random c 1 8

Последние два нужно обязательно, но по-отдельности опционально.
Реально можно отказаться от использования /dev/random, если поставить флаг USE="urandom" (справедливо для arp). Но, иной софт может и не понять.

Все это можно делать не останавливая VPS, поскольку делается в папке private.

После изменений перезапускаем:
# vzctl stop 123
# vzctl start 123

----- СПОСОБ 2 (спасибо анонимному читателю за подсказку, этот способ проще и корректнее):

1) редактируем файл /vz/private/123/etc/conf.d/rc
в нем меняем RC_DEVICE_TARBALL="yes"

2) После изменений перезапускаем VPS:
# vzctl stop 123
# vzctl start 123

Внутри самой VPS создаем устройства:
2) mknod --mode 444 /dev/urandom c 1 9
3) mknod --mode 444 /dev/random c 1 8

Теперь при ребуте они будут создаваться автоматически.

-----

Дополнительные ссылки:
http://forum.openvz.org/index.php?t=msg&goto=5140
http://wiki.openvz.org/Physical_to_VE#.2Fdev.2Furandom
http://mlblog.osdir.com/openvz.user/2006-01/index.shtml

пятница, 21 декабря 2007 г.

USB Linux Scanner "Segmentation fault" error

Замучался со сканером Canon Canoscan LiDe25 на Mandriva 2008. Из за попытки сканирования падает OpenOffice, Kooka, XSane ни слова при этом не произнося. Причем находит его нормально.

Еще под рутом сканер работает замечательно, под юзером - нет. Собственно, что имеем:


$ sane-find-scanner
found USB scanner (vendor=0x04a9 [Canon], product=0x2220 [CanoScan], chip=LM9832/3) at libusb:004:002
# Your USB scanner was (probably) detected. It may or may not be supported by
# SANE. Try scanimage -L and read the backend's manpage.
$ scanimage -L
Segmentation fault

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

$ export SANE_DEBUG_DLL=255
$ scanimage -L
...
[dll] add_backend: adding backend `v4l'
[dll] add_backend: adding backend `hp_rts88xx'
[dll] add_backend: adding backend `epkowa'
[dll] add_backend: adding backend `smfp'
[dll] sane_get_devices
[dll] load: searching backend `smfp' in `/usr/lib/sane'
[dll] load: trying to load `/usr/lib/sane/libsane-smfp.so.1'
[dll] load: dlopen()ing `/usr/lib/sane/libsane-smfp.so.1'
[dll] init: initializing backend `smfp'
Segmentation fault
$ sudo scanimage -L
...
device `plustek:libusb:004:002' is a Canon LiDE25 USB flatbed scanner


Ага, предпологаем, что вся беда в smfp, тем более, что сканер использует бэкенд plustek (бекенды можно подсмотреть тут).
Идем в /etc/sane.d/dll.conf и комментируем последнюю строчку, попутно читая комментарий:

#
# The following backends are not included in the sane-backends distribution
# If you want to use them, download them from their webpages and read their
# documentation
#
# HPLIP backend homepage: http://hplip.sf.net/
# Uncomment the following line if hpaio is installed:
#hpaio
hp_rts88xx
#primascan
epkowa
#smfp

Готово.
Честно говоря, я так и понял почему под рутом оно работало, но разбираться времени нет, поэтому пусть будет так.

пятница, 14 декабря 2007 г.

понедельник, 10 декабря 2007 г.

Azzurri Clay Database Modeling for Eclipse

Полчаса возни и найден бесплатный, хороший Azzurri Clay Database Modeling for Eclipse.

На первый взгляд все очень даже неплохо, сумел сделать reverse engineering, имеет кучу опций.
Посмотрим каков он в деле. Ищем здесь по тэгам, если будут глюки :)

PDT VS PHPEclipse

Сравнение. Скорее просто перечисление недостатков.

http://www.eclipse.org/pdt/. Eclipse update: http://download.eclipse.org/tools/pdt/updates/
- нет проверки синтаксиса на использование необъявленных переменных;
- в Outline показывает все функции проекта, очень много, не удобно;
- в Content Assist неправильно отсчитывает запятые в параметрах функции;
- жутко глючный фолдинг.

http://phpeclipse.sourceforge.net/. Eclipse update: http://phpeclipse.sourceforge.net/update/nightly/
- Content Assist при обнаружении множества функций с одним названием в проекте не показывает вообще ничего;
- нет возможности подсветить числа;
- редко обновляется.
Среди плюсов:
+ проверка синтаксиса на наличие необъявленных/неинициализированных переменных.

В многом остальном проекты похожи.

После длительного использования PDT нашел для себя phpeclipse, который порадовал своим пусть пока одним, но очень большИм преимуществом (см. выше). Посмотрим как себя поведет дальше.

MySQL Workbench bug

"The GRT environment for the Workbench could not be initialized. Please verify your installation."

Такое сообщение при запуске MySQL Workbench.
Лечится правкой файла /usr/share/mysql-gui/workbench/lua/Workbench.lua:

находим ~1686 строчку, правим


local lowestX= 999999999.0
local lowestY= 999999999.0
local highestX= 0.0
local highestY= 0.0

на

local lowestX= 999999999
local lowestY= 999999999
local highestX= 0
local highestY= 0

Взято здесь.
Там для фикса этого бага написано много вариантов, но для меня сработал именно этот.