🐧 Linux Fedora 31 :: борем нетривиальную проблему с печатью🖨 (и немного философствуем).

Posted: 2020-03-07 in Приколы, IT
Метки:

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

Итак, наш пациент сегодня — HP LaserJet P1505N.

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

Раньше, очень давно, самые первые принтеры были с «ромашкой», то есть по сути печатной машинкой, и могли печатать только текст и только одним шрифтом, что было намертво заложено в железе.

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

Затем довольно широко распространились струйные и лазерные принтеры. Эти девайсы уже умели гораздо больше, усложнились как сами устройства, так и сценарии взаимодействия с ними. Конечно, существуют стандарты и открытые протоколы взаимодействия, которые сильно упрощают жизнь и часто являются единственным способом наладить взаимодействие. Но само собой, нашлись некоторые особо ушибленные маркетологи, которые решили изобрести свой чугуниевый велосипед с треугольными колёсами и смазкой на говне — то бишь свои закрытые внутренние форматы и протоколы, чтобы дескать их бесценную «интеллехтуальную соппцтвенность» никто не посмотрел и на месте не умер от нахлынувших кошмаров.

Принтеры продавались, но золота требовалось всё больше, а топ-менеджмент старый вариант зиккурата на лазурном побережье уже не устраивал. И в какой-то момент в чью-то прокуренную наркоманскую балду пришла совершенно психоделическая идея — убрать из дешевых принтеров флеш-память, а заодно и постоянно присутствующую прошивку. То есть теперь программа на компьютере (часть драйвера) сперва должна была при первом обнаружении принтера загрузить в него прошивку каким-либо способом, и только после этого принтер мог делать хоть что-нибудь осмысленное.

Естественно (поскольку две чашки риса стоят дороже, чем одна), поначалу такие драйверы и софт были сугубо под виндовс, за что и получили название «win-принтеры». Олд-фаги помнят ещё более хтоническую жуть такого плана — так называемые win-модемы, но этот ужастики для зверей с совсем уж крепкими нервами.

Есть одна очень старая цитата про такие железки:

Win-юзеры — это типа Win-модемов и Win-принтеров: такие же юзеры, но попроще, без мозгов и памяти на борту.

Эта едкая цитата полностью отражает всю суть подобного железа.

Такая экономия оборачивалась просто эпической болью в жопе, если хоть что-то пошло не так, как ожидалось.
— без установленных драйверов железка есмь кирпич, и почти всегда неспособна даже к минимальной самодиагностике.
— аппаратные сетевые принт-серверы идут мимо, ибо не умеют загружать в кривой принтер кривую прошивку
— если версия виндовс не подходит — купите новый принтер
— ранние версии линуксов не могли печатать на такие принтеры, поскольку протокол обмена был закрыт и неизвестен
— на кассу с WinCE вы его тоже вряд ли поставите с первого раза
— иногда индусы раздували связку из драйвера и софта до таких размеров, что оно ставилось 40 минут
— печать на виндовс тоже могла отвалиться в любой момент на ровном месте
— попытка сетевой печати на расшаренный вин-принтер — практически гарантированный способ отбить себе граблями всё что можно.
— Если это ещё и на виндовс разных версий и разрядности — грабли забьют вас до смерти, часто это просто не работает и никаких внятных решений не существует.

В интернетах просто уйма историй борьбы с вин-принтерами, их драйверами, сетевой печатью и прочим непотребством.

В те времена некоторые недалёкие ламеры даже имели глупость утверждать, что «вот мол в вашем линуксе такие замечательные железки, как вин-модемы, вин-принтеры, LPT/SCSI-сканеры, IRDA-порты, SCSI-iomega-zip-ы, аналоговые FM- и TV-тюнеры не работают без плясок с бубном, а значит ваш линукс негоден для десктопа и сдохнет».

Ха-ха-ха. Про роль линукса сейчас говорить смысла нет. Это ключевой компонент серверной и сетевой инфраструктуры, программная основа для абсолютно всех топовых суперкомпьютеров, основа прошивок подавляющего большинства смартфонов, ТВ-приставок, камер видеонаблюдения и прочего IoT, да и при отсутствии специфичного софта нет никаких принципиальных проблем использовать его и на десктопе.

Ну а где все эти ваши железки ? Как насчёт того чтобы запустить их на виндовс ? На современной виндовс, которая Win-10 x64 ? Производители совершенно без затей кинули пользователей, наивно решивших, что они будут пользоваться купленным давным-давно железом, пока оно физически исправно. Не, только не на виндовс. Либо сидите со своим старым железом на старом (и крайне уязвимом !) софте, либо покупайте вместе с новой виндой ещё и новое железо, включая периферию.

Один из первых примеров в моей практике — очень давний случай с таким типичнейшим вин-принетром, как HP LaserJet 1020:
https://aminux.wordpress.com/2008/09/11/windows-2003-ipp-linux-hplj-1020/
Это просто неимоверно злоеб*чий кусок дерьма, выпивший немало крови.

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

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

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

Весьма характерный пример — принтеры HP P1505 и 1505n.
Заметили буковку `n` в конце ? Вот эта самая буковка означает устройство совершенно иного уровня качества. Во-первых, у принтера отрастает сетевой интерфейс. А значит, он будет втыкаться в свитч, а не в рабочую машину, и можно послать лесом всякие cups- и самба- шаринги. Во-вторых, там в разы больше памяти — 32 Мб, а не 2. Сразу появляются SNMP и веб-морда. И самое главное — там китайцам дали достаточно еды, чтобы они туда впаяли флеш-память, и страдать от загружаемой прошивки на n-версии не надо.

Да, прошивка всё ещё обновляется через анус, но жить стало гораздо легче.

В процессе изучения потрошков прошивок этих самых принтеров выяснилось, что для передачи данных используется протокол XQX — закрытое проприетарное нечто от хьюлета, используемое в ряде моделей. Но не во всех — в других моделях может использоваться ничуть не менее проприетарный проктокол ZjStream, но этими двумя список не ограничивается.

На виндовс подобные принтеры — это головная боль с жирнющими драйверами (40 минут установка драйвера — это вот ни разу не шутка, если что), проблемной сетевой печатью и практически полным отсутствием внятной диагностики. Решение будет на уровне включить/выключить/переставить_драйвер/переставить_виндовс.

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

Для P1505n схема будет примерно такая:
[User Application] —print call—> CUPS
—postscript—> cups-filters —> foomatic-rip
—> XQX-wrapper —> Network —> [HP P1505n]

Такая сложная схема позволяет разделить по разным уровням разметку страницы, её рендеринг в открытый PS, получение данных в вендор-специфичных форматах , отправку по сети, мониторинг принтера и разделение доступа.

Именно поэтому линуксовый драйвер может весить всего 500 Кб, а не 400 Мб.
Это же позволяет довольно быстро добавлять поддержку новых протоколов (после раскурки протокола становится доступным всё семейство железок на этом протоколе), не перелопачивая каждый раз всю подсистему печати из-за очередной всратой железки.
И ещё такая архитектура в разы упрощает диагностику даже весьма сложных и неочевидных проблем, плюс делает возможными всякие трюки с системой печати.

Обратная сторона такой сверх-гибкости — обновление компонентов может сломать вам чего-нибудь, что у меня недавно и случилось.

Вообщем, обновив целую кучу пакетов (я придерживаюсь идеи, что лучше самому что-то сломать, чем сидеть на уязвимом софте и быть в итоге взломанным черношляпными хакерами), я обнаружил (причем далеко не сразу), что у меня не печатает принтер, ибо используется он относительно редко. Так вот — если идти привычным путём из мира виндовс — то бишь пытаться переустановить драйвер, выключить/включить/перезагрузить/снести-добавить-заново принтер, то нифига у вас не получится. Попробовать можно, и для развития понимания — даже нужно, но к решению это вас приблизит не так и сильно.

Реально диагностика получается вот такая:

— смотрим, что предложенный изначально драйвер — foo2xqx. Это открытая реализация протокола XQX в рамках проекта Foomatic, который собирает базу принтерных драйверов.
Не забываем посмотреть описание на странице автора:
http://foo2xqx.rkkda.com/

— смотрим, что тип коннекта — socket://ip:9100 (HP/JetDirect)
Это надёжная штука.

— проверяем, что адрес принтера пингуется, в браузере открывается веб-морда, а nmap видит открытый порт 9100. Если нет — курим сеть/файерволы/ACL, резетим принтер, добиваемся видимости по сети.

— поскольку протокол крив и требует сторонних модулей (тут есть выбор — открытый foo2xqx или сторонний проприетарный плагин), то мы сперва делаем трикс — ставим тип принтера Generic PCL5, и пробуем печатать тестовую. Из-за отсутствия конвертера принтер напечатает мусор. Главное — что он должен как-то дергать лапками. Если не дергает — проверяем бумагу, картридж, податчик. Если на этом этапе нет признаков жизни — дело пахнет сервис-центром.

— проверяем, что наши принтеры живы, а конвертер работает. Нам понадобится какой-нибудь небольшой файл в формате PostScript, он без проблем делается с помощью gimp или берется готовый.

Смотрим вот в этот ман:

https://www.mankier.com/1/foo2xqx-wrapper

Смотрим имена принтеров:

lpstat -p

И выполняем вот этим команды:

foo2xqx-wrapper testpage.ps > testpage.xqx
xqxdecode < testpage.xqx
lpr -P raw testpage.xqx

Первая команда превратит PostScript в бинарный формат XQX, вторая команда его проверит и выведет по нему сводку, а третья сразу отправит его на печать в дефолтный принтер.

У меня на этом этапе всё сработало. =)

— Смотрим логи с помощью journalctl -u cups -f и видим, что при ручном вызове foo2xqx-wrapper есть строчки от работы конвертера, а в случае печати из GUI-морды нет. Тут надо ещё напоминить, что описания принтеров заданы в виде PPD-файлов. Просто ищем внутри системных файлов по модели принтера и грепаем интересное нам:

# find /usr/ -name "*1505n*"
/usr/share/cups/model/HP-LaserJet_P1505n.ppd.gz
/usr/share/foomatic/db/source/printer/HP-LaserJet_P1505n.xml

# zcat /usr/share/cups/model/HP-LaserJet_P1505n.ppd.gz | grep xqx
*% You may save this file as 'HP-LaserJet_P1505n-foo2xqx.ppd'
*ShortNickName: "HP LaserJet P1505n foo2xqx"
*NickName: "HP LaserJet P1505n Foomatic/foo2xqx (recommended)"
*1284DeviceID: "MFG:Hewlett-Packard;MDL:HP LaserJet P1505;CMD:ACL;DES:HP LaserJet P1505;DRV:Dfoo2xqx,R1,M0,TF;"
*driverName foo2xqx/foo2xqx: ""
*driverUrl: "http://foo2xqx.rkkda.com/"
*FoomaticIDs: HP-LaserJet_P1505n foo2xqx
*FoomaticRIPCommandLine: "foo2xqx-wrapper %A"

# cat /usr/share/foomatic/db/source/printer/HP-LaserJet_P1505n.xml | grep xqx
foo2xqx
This printer is supported by the foo2xqx free software printer driver.

— Пробуем печатать на виртуальный принтер cups-pdf — там всё ОК. Понимаем на этом этапе, что сам CUPS у нас работает, xqx-конвертер тоже, сеть в порядке. Остается только cups-filters или foomatic.

— Сломать фильтры купса могут три вещи: разрушение файлов (сбой диска), ручная правка настроек или апдейты. Настройки я не трогал, на диск система не жаловалась, так что смотрим /var/log/dnf* на предмет cups, foomatic, xqx.
И видим там относительно недавний апдейт целой пачки пакетов.

— Я сперва откатил cups целиком, вместе с фильтрами:
# dnf downgrade cups
делаем `service cups restart` … пробуем печатать.. и наш принтер заработал!

— осталось понять, что это было. Накатываем апдейты снова `dnf update`, рестартим купс — наблюдаем, что принтер «сломался». Откатываем только cups-filters (`dnf downgrade cups-filters`), даём `service cups restart` — и принтер снова оживает. Получается, что cups-filters обновили не очень удачно, в новой версии сломался вызов враппера, что и вызвало эту проблему. Просто не апдейтим какое-то время cups-filters, пока не выйдет новая версия. Видимо, принтер уже стал достаточно редким, и данный баг прошляпили.

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

Сложно ли это ? Да, сложно, учитывая, что мне впервые пришлось настолько глубоко закопаться в недра системы печати и впервые у меня возникла на линуксе проблема с принтером. Во всяком случае, поздно вечером в полусонном состоянии я это не решил. Однако наличие логов и документации, а также модульность системы позволили мне уже на следующий день спокойно найти причину проблемы и её обойти, не прибегая к отладчику / дизассемблеру / методам слепого тыка и прочей черной магии.

Да пребудет с вами сила, и не ставьте апдейты в пятницу вечером.

2020-03-12 P.S. Буквально вчера появился апдейт. Просто ставим, и у нас снова всё работает, и мы снова на топовых версиях.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.