这是我自己写的「如何列印」,原本只是一篇小笔记,因为设定印表机的过程很累很复杂,为了怕我自己日久生疏,而写给自己看的。后来越写越长,写成了完整的 Linux 列印设定教学。
本文是采用 samba - LPRng - ifhp filter - ghostscript uniprint 驱动程式搭配的列印架构。如果你是用别的搭配方式,设定会有所不同。
本文作者是我一个人,未曾受过各个列印程式作者的授权,也未曾和各个作者讨论,内文所述不能代表各列印程式的正式文件。本文或有疏失、遗漏、偏颇、错误之处,还请不吝告知,谢谢。
如果你只是要把印表机分享给 Windows 工作站用,或只是要设定一个 Windows 工作站用的 print server ,完全不要在 Linux 下印表,请依下列步骤。如果你真的是要「在 Linux 下设定印表机」,要在 Linux 下列印,或想更深入了解 Linux 下列印的架构,请跳过这一段。
把印表机接到 LPT1 ,做下述测试:
% echo "Hello, world!" >> /dev/lp0
如果印表机有反应,把整张纸退出,看看「 Hello, world! 」有没有印出来。如果一切正常,继续下一步。[1]
% tar xzf LPRng-x.x.x.tgz % cd LPRng-3.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --disable-setuid % make % make test % su $ make install
# 最简化的 printcap 设定,只给 samba 客户端列印使用 lp: :lp=/dev/lp0 :sd=/var/spool/lpd/%P
这时印表机应该会有反应。把整张纸退出,看看「 Hello, world! 」有没有印出来。如果一切正常,继续下一步。[24]$ checkpc -f $ echo "Hello, world!" | lpr
存档后,记得要开一个 /var/spool/lpd/samba 的目录,拥有者是 root ,权限是 1777 。[printers] comment = Printers printable = yes browsable = no public = no valid users = @users printing = lprng path = /var/spool/lpd/samba print command = /usr/bin/lpr -P%p -r %s lpq command = /usr/bin/lpq -P%p lprm command = /usr/bin/lprm -P%p %j lppause command = /usr/sbin/lpc hold %p %j lpresume command = /usr/sbin/lpc release %p %j queuepause command = /usr/sbin/lpc -P%p stop queueresume command = /usr/sbin/lpc -P%p start
如果没有问题,重开 samba ,回到 Windows 工作站,从网路上的芳邻中重新整理,看看能不能看得到这台印表机。[26]$ /usr/local/samba/bin/testparm
这部份请参考 Windows 的说明,和印表机说明书的安装设定说明。记得要印一张测试页,测试看看。[27]
Linux 列印的基本做法如下:
图中虚线为 Windows / samba 网路印表机列印资料传送流程。
我们从最下层往上设定起:
把印表机接到 LPT1 ,做下述测试:
% echo "Hello, world!" >> /dev/lp0
如果印表机有反应,把整张纸退出,看看「 Hello, world! 」有没有印出来。如果一切正常,继续下一步。[1]
印表机硬体通讯传输一切正常,可以直接列印英文后,接下来我们要让她列印 PostScript 文件。如果你的印表机本身就是 PostScript 印表机,(那你一定非常有钱,不然就是在公司或学校电算中心,)可以直接列印 PostScript ,可以跳过这一段。
PostScript 是列印专用的文件格式,是 1985 年由 Adobe 制定的。[2] 大多数雷射印表机都可以直接列印 PostScript 文件。不过我想你和我的便宜喷墨(或点矩阵)印表机,应该都办不到,所以我们继续往下看。
Ghostscript 是 PostScript 印表机模拟程式,透过软体模拟,可以让非 PostScript 印表机,也能印出 PostScript 文件。如此一来,就可以把我们的廉价印表机,当成贵贵的 PostScript 印表机来用了。[3]
Ghostscript 的工作是转译印表指令,将 PostScript 指令,转译成各种印表机专用的低阶列印指令,送印表机执行。因此, Ghostscript 需要知道各种印表机的指令语言。这就是所谓的「驱动程式」。有的印表机 Ghostscript 有随附驱动程式,有的没有。没有随附驱动程式的时候,你可以上 LinuxPrinting 印表机资料库找,有没有别人写过你印表机的 Ghostscript 驱动程式,下载来用。除非是 uniprint 驱动程式,否则下载后,要再重新编译 Ghostscript 。
uniprint (Unified Printer Drivers) 原先是设计给 Epson Stylus Color 系列的一种 Ghostscript 驱动程式规格,下载后可以直接存档使用,不用重新编译 Ghostscript 。 uniprint 驱动程式的附档名是 .upp 。[4]
编辑 Makefile ,修改安装的位置:% tar xzf gnu-gs-6.52.tar.gz 或 ghostscript-x.xx.tar.gz % cd gsx.xx % ln -s src/unix-gcc.mak Makefile
接著安装:prefix = /usr
然后,到 /usr/share/ghostscript/ 下,解压缩 Ghostscript 字型:% make % make test % su $ make install
$ cd /usr/share/ghostscript/ $ tar xzf ghostscript-fonts-std-x.x.tar.gz $ tar xzf ghostscript-fonts-other-x.x.tar.gz
xxxxxxxx 是你印表机的代号;如果是 uniprint ,$ cd /usr/share/ghostscript/x.xx/examples/ $ gs -sDEVICE=xxxxxxxx -sOutputFile=/dev/lp0 tiger.ps
xxxxxxxx.upp 是 uniprint 驱动程式档名。如果 Ghostscript 可以顺利读到驱动程式,就会印出一只大老虎了。[7] 你可以把这一行设定成 alias ,加在 ~/.bashrc 下:$ cd /usr/share/ghostscript/x.xx/examples/ $ gs @xxxxxxxx.upp -sOutputFile=/dev/lp0 tiger.ps
alias gs="gs -sDEVICE=xxxxxxxx -sOutputFile=/dev/lp0"
可以列印 PostScript 后,要印其她的档案,只要统一转为 PostScript ,就可以印了。 PostScript 的转换程式很多也很琐碎,安装设定都很简单,在这里就不详述了。以下列出几种常见的 xxx2ps PostScript 转换程式:
安装完后,记得要测试转换后的 PostScript 档能不能印。
$ echo "Hello, world" | a2ps -o - | gs - $ html2ps < /usr/local/apache/htdocs/index.html | gs - $ gs mypdf.pdf $ giftopnm < mygif.gif | pnmtops | gs - $ jpegtopnm < myjpeg.jpg | pnmtops | gs - $ pngtopnm < mypng.png | pnmtops | gs - $ bmptoppm < mybmp.bmp | pnmtops | gs - $ tifftopnm < mytiff.tif | pnmtops | gs - $ ...
以后要列印,只要用 PostScript 转换程式转为 PostScript ,就一切 OK 罗。到此,我们已经可以「列印」了。不管要印什么,都通行无阻。
可以列印还不够。印不同的档案,要跑不同的转换程式,把档案格式转来转去。这样太麻烦了。我们需要一个智慧型程式,自动判断档案类型,呼叫要用的转换程式。这就是 filter 列印资料滤镜。 filter 的原理其实很简单,有兴趣的话,看完以下的说明,你也可以自己写一个试试看。
现成的 filter 有很多,比较普遍的如 lpdomatic (LPD-O-Matic)[12] 、 tops 、 magicfilter[13] 、 apsfilter[14] 、 rhs-printfilters[15] …等等。 ifhp 是 LPRng 同一个 team 写的 filter ,我自己用的是 ifhp ,所以以下以 ifhp 来说明:
% tar xzf ifhp-x.x.x.tgz % cd ifhp-x.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man % make % make test % su $ make install
xxxxxxxx.upp 是你下载的 uniprint 驱动程式档名。这样 ifhp 才能从你指定的印表机代号,找到你的印表机该如何设定。[ xxxxxxxx.upp ] status pjl@ pcl@ ps@ text gs_converter= \%s{gs_unidriver} gs_device=xxxxxxxx.upp
\%s{string} 会被代换为之前 string= 设定的字串。列印时, ifhp 会呼叫 /usr/bin/file 判断档案类型,从传回来的结果字串,和这些样式比对,如果符合,就执行后面设定的指令。[17] 如果后面没有指令了,就当成最终转换结果送出。例如:file_output_match = [ *postscript* raw \%s{gs_converter} *text* text [16] *01-* text *pcl* filter \%s{pcl_converter} *pjl* filter \%s{pjl_converter} *html* filter \%s{html_converter} *pdf* raw \%s{pdf_converter} *37)* raw \%s{pdf_converter} *jpeg* filter \%s{jpeg_converter} *gif* filter \%s{gif_converter} *png* filter \%s{png_converter} *pc_bitmap* filter \%s{bmp_converter} *tiff* filter \%s{tiff_converter} *gzip_compressed* filter \%s{gzip_decompress} *data* raw ]
"JPEG image data, JFIF standard" 符合 *jpeg* (不分大小写),於是就执行 jpeg_converter 。你可以依 file 执行传回的结果字串,设计新样式。% file myphoto.jpg myphoto.jpg: JPEG image data, JFIF standard
执行时, ifhp 会用 pipe 输出入重导 (|) ,从标准输入 stdin 传入原始档案,而从标准输出 stdout 取得转换结果。html_converter= /usr/bin/html2ps 2>/dev/null pdf_converter= \%s{gs_converter} jpeg_converter= /usr/bin/jpegtopnm | /usr/bin/pnmtops -noturn[18] gif_converter= /usr/bin/giftopnm | /usr/bin/pnmtops -noturn[19] png_converter= /usr/bin/pngtopnm | /usr/bin/pnmtops -noturn bmp_converter= /usr/bin/bmptoppm | /usr/bin/pnmtops -noturn tiff_converter= /usr/bin/tifftopnm | /usr/bin/pnmtops -noturn
如果印出来没问题, ifhp 就设定好了。[20] 到此,可以告一个段落,我们终於有了一个智慧型的列印程式,可以自动视情况列印各种档案了。你可以把上面那一行设定成 alias ,加在 ~/.bashrc 下:$ /usr/libexec/filters/ifhp -Tdev=/dev/lp0,model=xxxxxxxx < /tmp/myfile
然后喝杯咖啡,休息一下。 ^_*'alias ifhp="/usr/libexec/filters/ifhp -Tdev=/dev/lp0,model=xxxxxxxx"
我们终於有了一个智慧型列印资料滤镜 ifhp ,可以自动视情况分配档案格式的转换工作,再把最终结果送到印表机。只要用 ifhp ,要印什么都可以印了。总算结束了吧?
还没有。列印工作远比想像中复杂。不只要能印,还要能「管理」:同时要印好几个档案的时候,你要让档案排队列印,或是把重要的档案抽出来先印,还要把送错了的档案取消掉,或是在卡纸的时候,暂停列印。更何况, /dev/lp0 的权限是 660 ,我们不可能让每个人都有权限,直接写到 /dev/lp0 去。[21]
所以我们需要列印管理程式 LPRng ,管理所有的列印工作。
% tar xzf LPRng-x.x.x.tgz % cd LPRng-x.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --disable-setuid[22] % make % make test % su $ make install
%P 是指印表机的名称,也就是第一行设定的 lp: 。你可以把印表机名称改成你比较好记的名字,如 HPDJ670C 。 :sd= 设定的是列印伫列存放的目录,如果还没有建好这个目录,要记得去 mkdir 。拥有者是 root ,权限最好和 /tmp 一样是 1777 。# 配合 ifhp filter 和 Ghostscript uniprint 驱动程式的 printcap lp: :lp=/dev/lp0 :sd=/var/spool/lpd/%P :ifhp=model=xxxxxxxx :filter=/usr/libexec/filters/ifhp
如果使用者都是身边的熟人,把权限放松一点,给大家方便。把 "ACCEPT SERVICE=C LPC=lpd,status,printcap" 这一行去掉,改成:# 限制可连线的 IP ,格式是 IP 或 IP/子网路遮罩 REJECT SERVICE=X NOT REMOTEIP=127.0.0.1,192.168.0.0/255.255.0.0 # 限制可连线的网域。 REJECT REMOTEHOST=X NOT REMOTEIP=localhost,*.your.domain
另外,要让管理者可以删掉印坏的文件。找到 "ACCEPT SERVICE=M SERVER REMOTEUSER=root" 那一行:# 给大家方便,让大家自己暂停∕继续 #ACCEPT SERVICE=C LPC=lpd,status,printcap ACCEPT SERVICE=C LPC=lpd,status,printcap,hold,release,stop,start REMOTEGROUP=users
# allow root on server to remove a job ACCEPT SERVICE=M SERVER REMOTEUSER=root ACCEPT SERVICE=M SERVER REMOTEGROUP=lp
checkpc -f 会检查 printcap 的设定,如果有什么问题,例如 :sd= 的目录不存在,会试著自动修正。检查过没问题后,重读 /etc/printcap 档:$ checkpc -f
这时再列印看看 /tmp/myfile :$ lpc reread
如果没有问题,一切就大功告成罗! ^_*'[24]% lpr /tmp/myfile
关於如何利用 lpr 、 lprm 、 lpc 、 lpq …来管理列印工作,请参考 LPRng-HOWTO 的说明。
如果你没有要把这台印表机分享其她 Windows 工作站来用,可以不必看这一段。
存档后,记得要开一个 /var/spool/lpd/samba 的目录,拥有者是 root ,权限是 1777 。[printers] comment = Printers printable = yes browsable = no public = no valid users = @users printing = lprng path = /var/spool/lpd/samba print command = /usr/bin/lpr -P%p -r %s lpq command = /usr/bin/lpq -P%p lprm command = /usr/bin/lprm -P%p %j lppause command = /usr/sbin/lpc hold %p %j lpresume command = /usr/sbin/lpc release %p %j queuepause command = /usr/sbin/lpc -P%p stop queueresume command = /usr/sbin/lpc -P%p start
如果没有问题,重开 samba ,回到 Windows 工作站,从网路上的芳邻中重新整理,看看能不能看得到这台印表机。[26]% /usr/local/samba/bin/testparm
这部份请参考 Windows 的说明,和印表机说明书的安装设定说明。记得要印一张测试页,测试看看。[27]
(回正文)*text* filter \%s{a2ps_converter}
(回正文)jpeg_converter= /usr/bin/imgtops2
exit 0 是因为 gif2ps 会把不严重的警告也以错误值传回, ifhp 会误判为转换失败,就不会印了。 (回正文)gif_converter= /usr/bin/gif2ps; exit 0
执行:#! /bin/sh file=/tmp/myfile ifhp=model=xxxxxxxx cat /dev/null >/tmp/t cat $file | /usr/libexec/filters/ifhp -Tdev=/tmp/t,trace,debug=2,${ifhp} 2> /tmp/trace
仔细看看 /tmp/trace ,找到问题的原因。你可以把 debug= 的值设大一点(如 debug=10 ),以得到更详细的侦错资讯。 (回正文)$ sh -x /tmp/send
检查列印记录。若还是不行,请参考 LPRng HOWTO 的说明。 (回正文)% lpq -L
更进一步的资料请参考下列网址: