openSUSE :: MySQL & Ruby
Наконец-таки нашел немного времени для знакомства с Ruby. Присматривался к нему уже наверное лет 5. Сначала SUSE стала создавать свои web сервисы на Ruby, потом вышел WebYaST… Что связанно с SUSE, Ruby исползуется повсеместно. Наконец и YaST был переписан на Ruby, а это значит, что openSUSE стал первым дистрибутивом, где установщик полностью написан на этом языке. Сегодня его просто нельзя уже игнорировать. Итак, я собираюсь начать восхождение как можно быстрее. Вы со мной? 🙂
Я покажу, что Leap 42.1 прекрасно подходит для изучения Ruby. В качестве примера рассмотрим работу с MySQL (на работе мне постоянно приходится писать автономные программы, поведение которых зависит от данных в БД); что-нибудь самое простое.
Если вы уже работали с БД, к примеру, в Python или Lisp, то приведенный ниже код поймете сразу. Require подключает модуль mysql. Мы создаем mysql-объект con. С помошью его метода query создаем SQL-запрос. Пробегаемся по выводу при помощи each do, при этом каждой строке из вывода присваиваем имя row. Я использую puts для вывода информации на экран. В Ruby есть и всем известный print. Разница в том, что puts добавляет символ новой строки в конец вывода, а вот print этого не делает. 14-16 строки обрабатывают ошибку (показывают ее вывод, но программа продолжает работу), если такая возникнет при попытке соединиться и получить данные. В конце мы вызываем close, который закрывает соединине.
#!/usr/bin/ruby require 'mysql' begin con = Mysql::new('10.10.10.10', 'login', 'password', 'centreon') con.query('SHOW columns FROM nagios_server').each do |row| puts "#{row[0]} #{row[1]} #{row[2]} #{row[3]}" end rescue Mysql::Error => e puts e.errno puts e.error ensure con.close if con end
При первом запуске (используем свежую Leap 42.1 x86_64) получаем ошибку:
> ./mysql-test.rb
/usr/lib64/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55: \
in `require': cannot load such file -- mysql (LoadError)
from /usr/lib64/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from ./mysql-test.rb:2:in `'
Тут все понятно: require не может найти mysql. Для установки воспользуемся gem. Это аналог Lisp’овского QuickLisp или Python’овского pip.
> gem --help RubyGems is a sophisticated package manager for Ruby. This is a basic help message containing pointers to more information. Usage: gem -h/--help gem -v/--version gem command [arguments...] [options...] Examples: gem install rake gem list --local gem build package.gemspec gem help install Further help: gem help commands list all 'gem' commands gem help examples show some examples of usage gem help platforms show information about platforms gem help show help on COMMAND (e.g. 'gem help install') gem server present a web page at http://localhost:8808/ with info about installed gems Further information: http://guides.rubygems.org > gem list --local mysql *** LOCAL GEMS *** >
Нет ни одной установленной в системе mysql gem.
Обратите внимание на вывод gem’овской help – для команды list сказано только по поводу –local аргумента. Там есть еще –remote. Последний покажет доступные для установки gem’ы. Я не привожу тут вывод, потому что список слишком большой.
Для установки воспользуемся командой install:
# gem install mysql
Fetching: mysql-2.9.1.gem (100%)
Building native extensions. This could take a while...
ERROR: Error installing mysql:
ERROR: Failed to build gem native extension.
/usr/bin/ruby.ruby2.1 extconf.rb
mkmf.rb can't find header files for ruby at /usr/lib64/ruby/include/ruby.h
extconf failed, exit code 1
Gem files will remain installed in
/usr/lib64/ruby/gems/2.1.0/gems/mysql-2.9.1 for inspection.
Results logged to
/usr/lib64/ruby/gems/2.1.0/extensions/x86_64-linux/2.1.0/mysql-2.9.1/gem_make.out
И я вам скажу честно – так происходит со многоими gem’ами 🙂
Но на самом деле ничего страшного не случилось. Дело в том, что gem’у нужен файл из RPM-пакета. Какого-то RPM пакета… Вызывать zypper нам придется самим. Какой пакет устанавливать? Мне повезло, я вспомнил, что один RPM-пакет нужно было доустановить и в случае с Common Lisp. В том случае это был libmysqlclient, для Ruby же нужен libmysqlclient-devel. Очень рекомендую еще поставить пакет ruby-devel и весь pattern devel_basis. Там много библиотек, необходимых интерпретору.
> sudo zypper in -t pattern devel_basis > sudo zypper in ruby-devel libmysqlclient-devel
После этого попытаемся установить mysql gem снова:
> gem install mysql Building native extensions. This could take a while... Successfully installed mysql-2.9.1 Parsing documentation for mysql-2.9.1 Installing ri documentation for mysql-2.9.1 Done installing documentation for mysql after 0 seconds 1 gem installed > echo $? 0 > gem list --local mysql *** LOCAL GEMS *** mysql (2.9.1)
Выглядит лучше, правда? Теперь вернемся к коду выше. Придумайте для теста какой-нибудь простой SQL запрос. Что-нибудь типа show tables, к примеру. Вывод скрипта, приведенного выше, выглядит так:
./mysql-test.rb id int(11) NO PRI name varchar(40) YES localhost enum('0','1') YES is_default int(11) YES last_restart int(11) YES ns_ip_address varchar(255) YES ns_activate enum('1','0') YES ns_status enum('0','1','2','3','4') YES init_script varchar(255) YES monitoring_engine varchar(20) YES nagios_bin varchar(255) YES nagiostats_bin varchar(255) YES nagios_perfdata varchar(255) YES centreonbroker_cfg_path varchar(255) YES centreonbroker_module_path varchar(255) YES centreonconnector_path varchar(255) YES ssh_port int(11) YES ssh_private_key varchar(255) YES init_script_snmptt varchar(255) YES
Для сравнения, вот так выглядит вывод нашего SQL запроса в mysql(1):
> SHOW columns FROM nagios_server; +----------------------------+---------------------------+------+-----+---------+ | Field | Type | Null | Key | Default | +----------------------------+---------------------------+------+-----+---------+ | id | int(11) | NO | PRI | NULL | | name | varchar(40) | YES | | NULL | | localhost | enum('0','1') | YES | | NULL | | is_default | int(11) | YES | | 0 | | last_restart | int(11) | YES | | NULL | | ns_ip_address | varchar(255) | YES | | NULL | | ns_activate | enum('1','0') | YES | | 1 | | ns_status | enum('0','1','2','3','4') | YES | | 0 | | init_script | varchar(255) | YES | | NULL | | monitoring_engine | varchar(20) | YES | | NULL | | nagios_bin | varchar(255) | YES | | NULL | | nagiostats_bin | varchar(255) | YES | | NULL | | nagios_perfdata | varchar(255) | YES | | NULL | | centreonbroker_cfg_path | varchar(255) | YES | | NULL | | centreonbroker_module_path | varchar(255) | YES | | NULL | | centreonconnector_path | varchar(255) | YES | | NULL | | ssh_port | int(11) | YES | | NULL | | ssh_private_key | varchar(255) | YES | | NULL | | init_script_snmptt | varchar(255) | YES | | NULL | +----------------------------+---------------------------+------+-----+---------+ 19 rows in set (0.00 sec)
Вот так выглядит мой первый шаг изучения Ruby. После опробывания парочки других библиотек (например SNMP, threading или SMTP), нужно браться за изучения типов данных. Это основа языка. Если приницип работы библиотек практически 1:1 как и в Python, то к отличиям типов данных стоит отнестись серьезнее. Еще меня интересует стиль языка, а именно функциональная парадигма. Ходят слухи, что на нем легче писать функциональный код, чем на python. В этом мне еще только придется убедиться.
На последок скажу, что открытой документации по Ruby очень много. Все больше и больше документации появляется сейчас и на русском. Удачи в изучении. Счастливо 😉
leave a comment