2004年1月12日月曜日

Debian GNU/Linux, USB接続のプリンタの利用とネットワーク印刷 @ kernel 2.2.17

hp deskjet 5551 動作報告とSamba利用のプリントサーバ

先日、 hp のインクジェットプリンタ、 deskjet 5551 を購入した。 「パソコンから紙に印刷をしたい」という家族からの要望により、代わりに買ってきた次第だ。 家族からは、WinME 搭載のノート型コンピュータからこのプリンタを使って印刷ができればよい、と言われていた。 だが、スペースの関係上、このプリンタを私の部屋に設置しなくてはならなくなった。 部屋に設置するというなら、私もプリンタの恩恵にあやかりたいと思い、

  • Linux からも印刷をできるようにする。
  • home LAN 経由で印刷データをプリンタに転送できる(印刷できる)
という環境を目指した。
なお、LinuxPrintingで、どのプリンタを買おうか吟味してから電機屋へ買いにいった。 YドバシCメラにて、2,2800円だった。

なお、まだまだ不備もある。 今まだ残っている問題を以下に挙げておく(投げやり)

  • Linux からテキストを直接印刷できない。(フィルタの不備です)
  • 例えば Windows での印刷の際の「印刷進渉表示」や「インク残量表示」などのプリンタからの情報がパソコンまで届かない。
  • 世界中のクラッカーが私の部屋のプリンタで印刷ができてしまう。

下地となる環境詳細

  • OS = debian GNU/Linux
  • Kernel version = 2.2.17 (USB backport パッチ済み[詳細]
  • イーサネットLAN[詳細]により、同一ネットワーク上に筆者の debian box と ノート型コンピュータ(WinME搭載)がある。

何をしたいか。

  • Linux box と プリンタをUSBで直接つなぎ、Linux からプリンタで印刷をする。(PS形式データのみ)
  • samba を Linux上で走らせておき、WinMEから印刷データを受けとってプリンタに流す。

そもそも Linux がインクジェットプリンタで印刷する手順がわからなかったので、適当に以下のように解釈。

プリントしたいデータ(すべてPS形式とする)をプリンタスプーラに送る。

スプーラはそのデータに対して、ちょっと処理をかましておく。(フィルタ処理)

フィルタ処理の仕事は、プリントしたいデータを ghostscript(gs)hpijs(hp inkjet server)を通して hp deskjet 5551 が印刷可能なデータに変換すること。

変換されたデータを usb デバイスへと流す。

とりあえず、gsとhpijsなるものをインストールしておく。 もちろん、筆者は debianパッケージを使い、dpkgコマンドを使って楽々インストールをする。(ぉ
ちなみに、これは後々判明することなのだが、現在(2003 Mar)安定版としてインストールできる hpijs(ver 1.0.4-1)では deskjet5551 が動かなかったので、テスト版の hpijs (ver 1.3.2) を使用した。

USBのプリンタを使う、ということで、カーネルコンフィグ。

# cd /usr/src/kernel-source-2.2.17
# make xconfig

  設定画面が上がるので、
  USB support → USB Printer support の m にチェックを入れて
  保存して終了

# make-kpkg kernel_image
# cd ..

  /usr/src に kernel-image-2.2.17_Custom.1.000_i386.deb などの
  カーネルパッケージができているので、それを組み込む

# dpkg -i kernel-image-2.2.17_Custom.1.000_i386.deb
# reboot

  再起動

# depmod -av

  depmod -av の出力の中に printer.o があるのを確認(何
  以下のコマンドで printerモジュールをカーネルに組み込めるようになった

# insmod printer
これでハードウェア面での設定はおおよそ終わった。
プリンタを使うときは、上で示したように # insmod printer コマンドや # modprobe printer コマンド*1でモジュールを組み込んでおかないと当然動かない。 modprobeコマンドは、モジュールの依存関係をも考慮してその他必要なモジュールも一緒に組み込んでくれるから便利。

*1(「# insmod modprobeコマンド」と書いていたのを訂正、modprobeという名のモジュールを組み込むわけではありません、ごめんなさい Apr 3)

LPRng(バークレーLPRの拡張)を入れる。 やっぱり # apt-get install lprng で楽してインストール。 この方法だと、ブート時にLPDを上げるか聞かれるので、景気よく y と答えておいた。 見ると、 /etc/rc2.d/S20lprng ができていた。

次に、ソフトの設定を進めていく。
hpijsのサイトの説明によれば、gs の ver 6.53以上から hpijs に対応しているとのこと。
$ gs -h というコマンドを打ち、その中に ijs という出力があればよいらしい。 また、hpijsの使用例として

  • $ gs -sDEVICE=ijs -sIjsServer=hpijs -dIjsUseOutputFD -sDeviceManufacturer="HEWLETT-PACKARD" -sDeviceModel="DESKJET 990" -r300x300 -dNOPAUSE -dSAFER -sOutputFile="/dev/lp0" file.ps -c quit
  • $ lpr -Plp0 tiger.ps
などと載せていた。 特に上の例のコマンドは長過ぎ。 特に、急いでいるときなどには打ちたくない。

deskjet 5551 をプリント出力先として /etc/printcap ファイルに書き加える。 (この辺は他サイト等の情報を元にしている。)

hp_deskjet_5551|hp deskjet 5551:\
:lp=/dev/usb/lp0:\
:sd=/var/spool/hp_deskjet_5551:\
:lf=/var/spool/hp_deskjet_5551/log:\
:af=/var/spool/hp_deskjet_5551/acct:\
:if=/usr/bin/hp_deskjet_5551-if:\
:mx#0:\
:sh:
上記のように書いてしまったので
  /dev/usb/lp0というキャラクタデバイス
  /var/spool/hp_deskjet_5551/log などのディレクトリ
  /usr/bin/hp_deskjet_5551-if というフィルタの役割をするシェルスクリプト
の3点セットを作っておく。
# mkdir /dev/usb
# mknod /dev/usb/lp0 c 180 0

# mkdir /var/spool/hp_deskjet_5551
# chgrp lp /var/spool/hp_deskjet_5551
/dev/usb/lp0 にアクセスされたらメジャー番号180、マイナー番号0番のキャラクタ型デバイスをセットする、という。 いまいちよくわからなかったが、/proc/devices 内の記述を参考してみた。
プリンタからの情報を得るには、この辺が重要になるのかな。 そして、/usr/bin/hp_deskjet_5551-ifというシェルスクリプトだが、これもまた他サイトの情報を参考にしている。
#! /bin/sh
#
# filter for hp deskjet 5551

/usr/bin/gs -q -sDEVICE=ijs -sIjsServer=hpijs -dIjsUseOutputFD -sDeviceManufacturer="HEWLETT-PACKARD" -sDeviceModel="deskjet 5551" -r300 -dNOPAUSE -dSAFER -sOutputFile=- -
上記の最後の1行は、先ほど見かけたあの長いコマンドを deskjet5551 風にアレンジしたもの。 まずはこの長い gs コマンドを普通にターム上で打ち込んでみて、ちゃんと ps ファイルがプリンタから出力されるのを確認してから、スクリプトに組み込む。 こんな風に(以下)打つと、name.ps がプリンタから出力される。
# gs -sDEVICE=ijs -sIjsServer=hpijs -dIjsUseOutputFD -sDeviceManufacturer="HEWLETT-PACKARD" -sDeviceModel="deskjet 5551" -r300 -dNOPAUSE -dSAFER -sOutputFile="/dev/usb/lp0" name.ps -c quit
やっぱり、改行文字をバックスラッシュでエスケープしたほうが見やすくてかっこいと思った・・・。

試し印刷。 こんどは lpr コマンド使用で ユーザでも印刷ができるか確かめる。

$ lpr -Php_deskjet_5551 name.ps
筆者の場合は、lprコマンドで psファイルを指定した場合にのみ印刷ができるようになった。 もじらなどでの印刷はできるが、$ lpr hoge.txt などのコマンドを打つと印刷に失敗する・・・。 magicfilter なるものを使うとこの辺を処理してくれるらしいのだが、それって自分で filter を書き直せば出来そうな気もするけど・・・。
以下次号にご期待・・・。(ぉ
とりあえず、これでLinuxからの印刷に関する設定をいったん中断する。

Sambaをインストール
やっぱり

# apt-get install samba samba-common
でインストール。すると、 debconfで初期設定ができる。 以下はこのdebconfで聞かれることをおおざっぱに訳したものと、設定例。
  1. debconfでsmb.confの設定をしますか? ---- ok
  2. Workgroup/Domain name? ---- home.pr.jp(※ WinMEのネトワク名に合わせること)
  3. 最近の窓は暗号化パスワードを使います。もし生テキストのパスワードがいいっていうなら、窓のレジストリを書き換えて、/etc/samba/smbpasswd というファイルで、各ユーザごとに smbpasswdコマンドでちゃんと設定してください。で・・・、暗号化パスワードを使いますよね? ---- yes
  4. nmbd と smbdのログの場所が /var/log から /var/log/samba に別々の名で保存されるようになりましたのでよろしく。 ---- ok
  5. サーバは daemon か inetd から上げられます。どっちがいいですか。なお、daemonが推奨されますよ。 ---- daemons ok
  6. パスワードについて、手動で smbpasswd コマンドを打ってメンテナンスしてください。 ---- ok
  7. /etc/samba/smbpasswd ? ---- yes
このあと、/etc/samba/smb.conf にプリンタ周りの設定を書き加える。 主だって変更した設定についてのみ、以下に挙げる。
[global]
 workgroup = MSHOME

[homes]
 変更無し

[printers]
 comment = All Printers
 path = /var/spool/samba
 create mask = 0700
 printable = Yes
 browseable = No

[printer1]
 path = /tmp
 guest ok = Yes
 printable = Yes
 print command = cat %s > /dev/usb/lp0 ; rm -f %s
 printer name = hp_deskjet_5551
[printer1] 以下が deskjet 5551 周りの設定である。 WinME 機から送られてくるデータはプリンタが扱える形式のデータのはずなので、デバイス /dev/usb/lp0 に cat コマンドで直接流し込んでいる。 なお、 %s は印刷データのファイル名に変えられる。

ユーザをつくる。
# smbpasswd -a username コマンドで username というユーザを作る。 このとき、 Linux 側にも username さんというユーザがいなくてはならない。

WinME に、deskjet 5551 のドライバを「ネットワークプリンタ設定」でインストールする。 その際、ネットワークプリンタとして hp_deskjet_55 を追加してやればいい。 なお、なぜ窓上で hp_deskjet_55 と尻切れとんぼに表示されるのかは謎である。

おまけ情報。
YドバシCメラのプリンタコーナーでは、hpやキヤノンの社員が接客をしてくれる。 売場には「競合他社との闘い」「客の取り合い」という見えない火花が散っている。 プリンタに関しては、さすがに相手は社員さんなので、何を聞いても正確に答えてくれる。 だが、YドバシCメラ1階の店内にはびこる Yahoo BB! の勧誘員はどうだかは知らない。