2008-12-26

MySQL Query Browser: работа с удаленной БД через SSH

Имеем: удаленный сервер MySQL, в моем случае это база данных сайта на masterhost.
Хотим: работать с данными не через phpMyAdmin по http, а используя удобный и привычный MySQL Query Browser и MySQL Administrator на локальном компьютере.
Нужно: клиент SSH, ну и соответственно логины-пароли доступа к удаленому аккаунту.
Легко:
1) Если на локальном компьютере установлен сервер MySQL - отключаем, освобождая порт:
$ sudo /etc/init.d/mysql stop
2) Подключаемся по протоколу SSH, вводя пароль когда попросят:
$ ssh -C uXXXXXX@uXXXXXX.ssh.masterhost.ru -L 3306:uXXXXXX.mysql.masterhost.ru:3306
3) Открываем MySQL Query Browser, вводим host - localhost (или 127.0.0.1), порт - 3306, логин, пароль и имя базы данных на сервере.
Пользуемся с удовольствием.

2008-12-23

Копирование сбойных файлов с CD/DVD в Linux

Прислали мне диски с конференции, наконец-то. Естественно, чтобы смотреть видео с них на nokia n810, надо конвертировать их в видеофайлы, к примеру mkv. Но вот беда! Последний трек на последнем диске оказался с ошибкой, и ни в какую не желал копироваться полностью. Выводилась Input/Output error. Поиски решения навели меня на статью Восстановление данных R.LAB, откуда я взял вот что:

dd if=/dev/scd0 of=~/video/file.iso bs=8K conv=noerror,sync

где:
bs=8K для пущей скорости, noerror не дает вылетать на ошибках, sync дописывает проблемные блоки нулями, чтоб не возникло смещений на приемнике.
В результате создается образ диска, ошибки выловлены, плохие участки заменены нулями. Затем создаем каталог и монтируем в него получившийся образ:

sudo mkdir /media/iso
sudo mount -t iso9660 -o loop ~/video/file.iso /media/iso/


Теперь можно и копировать. Видео конечно не ахти как выглядит на покореженных участках, зато  его можно посмотреть. После копирования отмонтируем образ:

sudo umount /media/iso

При желании удаляем образ, все-таки 4,5 гигабайт не лишние.
P.S. О том, как бороться с ошибками при записи дисков, хорошо написано здесь.

2008-12-18

PDF, Ubuntu, Python: история продолжается

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

Можно внести информацию о всем документе с помощью упомянутой ранее утилиты pdftk таким образом:
$ pdftk file.pdf dump_data output metainfo

В файл metainfo запишется информация следующего характера:
InfoKey: Title
InfoValue: untitled
InfoKey: Producer
InfoValue: ReportLab http://www.reportlab.com
InfoKey: Author
InfoValue: anonymous
InfoKey: Subject
InfoValue: unspecified
InfoKey: CreationDate
InfoValue: 20081217165436
PdfID0: ebd25ab8427fa1508e9924204f74b274
PdfID1: ebd25ab8427fa1508e9924204f74b274
NumberOfPages: 1


Соответственно, InfoKey - ключ, InfoValue - значение. Думаю, тут все понятно, двинем дальше. Теперь мы можем поменять значения ключей и сохранить файл, а потом изменить значение метаданных в нашем PDF файле:

$ cp file.pdf file.cp.pdf
$ pdftk file.cp.pdf update_info metainfo output file.pdf
$ rm file.cp.pdf


Зачем такой огород? А затем, что pdftk умеет сохранять метаданные только в другой файл, поэтому мы создаем временный, потом обновляем его данные, сохраняя в исходный, и удаляем временный. Вот петрушка... Но это еще цветочки. Ягодки в том, что если прописать в файле с метаданными текст на русском языке, то evince покажет его крякозябрями, а если попробовать извлечь инфо из обновленного файла, то увидим вместо наших русских буковок вот примерно такое: "￐ᅠ￑テ￑", что совсем не соответствует желаемому. К тому же, так задача пометок отдельных страниц не решается. Копаем дальше.

Эта же утилита умеет пристегивать к отдельным страницам PDF документа файлы. Во! Это уже что-то! Составляем файл с нужными данными (рекомендуется HTML или Excel файл, потому что тогда Adobe Reader адекватно среагирует, то есть откроет его). Пристегиваем файл с информацией к первой странице PDF:

$ cp file.pdf file.cp.pdf
$ pdftk file.cp.pdf attach_files to_page 1 output file.pdf
$ rm file.cp.pdf


Ну наконец-то. Неужели это все? Проблема решена? Щазз! Мы только подходим к трудностям. Ведь нам надо как-то извлечь оттуда прикрепленные файлы. А вот тут нас ждет 2 проблемы.

1) Не нашел (а я искал!) в pdftk возможности извлечения файлов выборочно, из определенных страниц, только все скопом:
$ pdftk file.pdf unpack_files output unpack/
Здесь все файлы извлекаются в папку unpack, если она конечно существует, иначе будет error. Одноименные файлы перезаписываются.

2) Все шло более-менее гладко, пока я экспериментировал с файлами PDF журнала LinuxFormat. И картина изменилась, когда дело дошло до настоящих чертежей, отсканированных на нашем широкоформатном сканере. Нет, записывать метаданные и даже прикреплять файлы к страницам получалось нормально, но вот когда я попытался извлечь прикрепленные файлы я увидел примерно вот что:
Unhandled Java Exception:
java.lang.NullPointerException
   at java.lang.String.toLowerCase(libgcj.so.81)
   at java.lang.String.toLowerCase(libgcj.so.81)
   at com.lowagie.text.pdf.PdfEncodings.convertToBytes(pdftk)

Все это в различных вариациях на тему некоего libgcj.so.81. Из всего этого я сделал пару выводов: а) pdftk написана на Java, хотя бы частично и б) проблема связана с текстовой информацией в файле.

Вот тут я был озадачен. Текстовой информации в файле не подразумевалось никакой, только одно-единственное изображение. Ладно бы там была какая-нибудь кириллица, и он на кодировках спотыкался. Но ведь неоткуда там тексту взяться! И тем не менее, файлы сторонние обрабатывались на ура, а мои сосканированные - ни в какую.
Сейчас поведаю, через какие извращения я прошел, чтобы превратить мой PDF в корректно обрабатываемый pdftk. Все это я делал на Python, о библиотеках, которые тут приводятся, я говорил чуть раньше.
Приготовились смеяться? Начали!

[файл workpdf.py]

#!/usr/bin/env python
# -*- coding: utf-8 -*-


# Допустим, что файл называется так:
filename="00.pdf"

import os
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics, ttfonts
from pyPdf import PdfFileReader


# Полчение размера страницы в пикселах
input = PdfFileReader(file(filename, "rb"))
p=input.getPage(0)
width = p.mediaBox[2]
height= p.mediaBox[3]


# Починка файла (чтобы convert не ругался)
os.system("pdftk "+filename+" output 01a.pdf")

# Конвертирование его в картинку
os.system("convert 01a.pdf  workpdf_temp_file.jpg")

# Удаление ненужной копии
os.system("rm 01a.pdf "+filename)

# Задаем настройки шрифта
MyFontObject = ttfonts.TTFont('Verdana', '/usr/share/fonts/truetype/msttcorefonts/tahoma.ttf')
pdfmetrics.registerFont(MyFontObject)


# Создаем основу нового PDF
MyCanvas = canvas.Canvas("test.pdf")

# Задаем размеры, равные исходному файлу, добавляем шрифты и тестовый текст
# Не знаю зачем, но видимо pdftk очень хочет найти текст в файле
MyCanvas.setPageSize((width, height))
MyCanvas.setFont("Verdana", 40)
MyCanvas.drawString(-100, -100, "test")


# Добавляем картинку из исходного файла
MyCanvas.drawImage("workpdf_temp_file.jpg",0,0)

# Завершаем и сохраняем файл
MyCanvas.showPage()
MyCanvas.save()


# А теперь барабанная дробь: прикрепляем файл и открепляем его без ошибок!
print os.system("pdftk test.pdf attach_files info to_page 1 output "+filename)
print os.system("pdftk "+filename+" unpack_files output unp/")


# И удаляем никому не нужные теперь файлы
os.system("rm test.pdf workpdf_temp_file.jpg")

Ну как? Животики надорвали? А главной проблемы - извлечения отдельно взятого файла от отдельно взятой страницы многостраничного PDF документа - я так и не решил. Пока не решил. А вы?

2008-12-15

Python и PDF

О том, с помощью чего и как можно работать с документами PDF в консоли я уже упоминал раньше. Несомненно, с помощью pdftk можно кое-чего достичь, и очень часто этого будет вполне достаточно.
Теперь передо мной встала другая задача: динамически вносить измененния в мета-информацию PDF файлов, и очень желательно - автоматически обрезать белые поля, остающиеся после сканирования документов. И оказалось, это не так просто.
С помошью того же pdftk можно получить информацию документа, записать ее в файл, изменить, а потом сделать update этой информации в другой файл. Что-ж, неплохо. Только кириллица там не прижилась, и слишком много телодвижений, да еще вручную. Это не наш метод. Хотя, если придется, то никуда не денешься.
К делу был привлечен Python, к которому я подбираю библиотеки для работы в PDF.
Кандидат номер 1:
pyPdf, ставится из стандартного репозитария Ubuntu (python-pypdf). Его описание, документация и несколько вполне ясных примеров с комментариями есть на сайте производителя. Вот что этот модуль умеет: извлекать информацию из документа, разбивать документ на страницы по отдельным файлам, собирать их в одно, обрезать, собирать многостраничные документы в одну страницу, шифровать и дешифровывать PDF. Минимум необходимого. Но я так и не нашел возможности вносить изменения в мета-информацию, а это то мне и нужно было.
Кандидат номер 2:
ReportLab, тоже есть в репозитарии Ubuntu. Документация обширная, я только начал вникать, но уже понятно, что эта библиотека - для создания документов, а что насчет правки уже мозоль натершей на языке мета-информации? Пока не знаю, возможно я найду возможности все-таки...
У кого есть опыт в этой сфере - не жадничайте, поделитесь! Неужели я один такой?
По поводу обрезки белых полей - глухо, как в танке. Пробовал использовать convert из комплекта ImageMagic и его опции -trim, а также -fuzzy, вроде бы специально предназначенных для такой задачи. Но результат нулевой. Цвета конечно не идеальные, но про -fuzz написано на сайте разработчика, что он как-раз для такого случая! Ан нет, не сработало. Откликнитесь, коллеги, у кого получилось?

2008-12-13

Перезапуск apache, mysql, networking (сеть) и др.

Любого человека, перешедшего на Linux, первое время мучают вопросы, кажущиеся гуру элементарными. Например, я довольно долго не знал, как мне перезапустить сетевые соединения. Перезапускал Ubuntu каждый раз, когда менял содержимое /etc/network/intefaces. Тоже самое было, когда установил LAMP, не знал, как перезапустить apache и mysql. Просто "sudo apache restart" не помогает.
Ну так вот, суть ответа - в папке /etc/init.d/ Там расположены скрипты, которые правильно работают с этими и многими другими службами. Поэтому перезагрузка сети будет выглядеть так:

sudo /etc/init.d/networking restart

Для всего остального вместо networking пишем apache2, mysql и т.п. Кроме restart доступны start, stop и force-reload. Пользуйтесь и наслаждайтесь!

2008-12-12

Утилитка для получения расширения файла

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

#!/bin/bash
mkvmerge -o ${1%avi}mkv $1 $2


Это простой пример упаковки видео и аудиоконтента в MKV, где вместо первого аргумента скрипту подсовывается имя видеофайла, вместо второго - имя аудиофайла. Но я же не всегда работаю с avi! Значит, расширение нужно как-то автоматически вычислять.
Честное слово, я искал простой системный способ сделать это. Кроме basename ничего не нашел, но это не то, что нужно. Если он есть - подскажите!
Ну так вот, пришлось взять в руки пилу, молток и SciTE, и сварганить скрипт самому:

[ файл ~/bin/ext.py ]

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

class FileExt:
def __init__(self):
try:
self.ind=sys.argv[1].rindex(".")
self.word=sys.argv[1]
except:
self.ind=sys.argv[0].rindex(".")
self.word=sys.argv[0]
def getext(self):
return self.word[self.ind+1:]

e=FileExt()
print e.getext()


Может быть и не лучший способ, но работает! Теперь мой скрипт может стать таким:

#!/bin/bash
mkvmerge -o ${1%`ext.py $1`}mkv $1 $2


P.S. Более изящный (и короткий) вариант кода:

import sys,os
try:
path,ext=os.path.splitext(sys.argv[1])
print str(ext).lower()
except:
print "Неверный аргумент"

2008-12-09

Кодирование MKV (matroska) для Nokia N810 используя mencoder

Открытия, как обычно, следуют за засадами. Несколько раз сталкивался с проблемами, когда кодировал файлы .mkv. Например, если пытаюсь извлечь видеотрек из .mkv в файл avi - возникает ошибка при воспроизведении, видео идет какимим-то цветными кубиками.
Или рассинхронизируются аудио- и видеопотоки. Или звук становится таким, как будто его эквалайзером загнали на максимум, и страшно жужжит.
Сегодня нашел в сети такой вариант, и вроде бы он нормально отработал. Буду тестировать.

mencoder filein.mkv -o fileout.mkv -of lavf -oac lavc -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:v4mv:vqscal:mpeg_quant -vf scale=-2:240

P.S. Проверил. Хороший метод.