打印
-
- 1、打印简史
- 2、Linux的打印功能
- 3、准备文件打印
- 4、将打印作业发送至打印机
-
- [4.1、 lpr---以Berkeley风格打印文件](#4.1、 lpr—以Berkeley风格打印文件)
- [4.2、lp---以System V风格打印文件](#4.2、lp—以System V风格打印文件)
- 4.3、a2ps---在PostScript打印机上打印文件
- 5、监控打印作业
-
- [5.1、 lpstat---显示打印系统状态](#5.1、 lpstat—显示打印系统状态)
- 5.2、lpq---显示打印队列状态
- 5.3、lprm/cancel---取消打印作业
1、打印简史
要想充分理解类UNIX系统中的打印特性,我们必须先了解一些历史知识。说起类UNIX系统的打印功能,那得追溯到系统诞生之初了。那时候,打印机及其用法和如今可是大相径庭。
1.1、"黑暗"时代
就像计算机一样,早期的打印机同样体积庞大、价格昂贵,而且还是集中式的。在20世纪80年代,典型的计算机用户都是在连接着远程计算机的终端上工作的。打印机则位于计算机附近,由计算机操作员看管。
当打印机既贵还集中的时候(就像在UNIX早期),大家共享打印机自然就是常事了。为了分辨出打印作业属于哪个用户,通常会在每个打印作业前面打印出一张显示用户名的标题页(banner page)。然后,计算机操作员会把当天的打印作业装进手推车,配送给各个用户。
1.2、基于字符的打印机
20世纪80年代的打印机技术与当今相比有很大的不同。第一,当时的打印机基本上都是击打式打印机(impactprinter)。这种打印机采取机械装置击打色带,从而在纸张上留下字符印迹。菊花轮式(daisy-wheel)打印和点阵式(dot-matrix)打印都是那时候流行的打印技术。
第二,也是更重要的一点,早期打印机使用的是设备自带的固定字符集合。例如,菊花轮式打印机只能打印实际模制在菊花轮花瓣中的字符。这使打印机就像是一台高速打字机。和大多数打字机一样,当时的打印机使用的也是等宽(固定宽度)字体,这意味着每个字符都有相同的宽 度。打印机在纸张的固定位置进行打印,打印区域包含的字符数量是固定的。多数打印机在水平方向上每英寸1打印10个字符(Characters Per Inch,CPI),垂直方向上每英寸打印6行数(Lines Per Inch,LPI)。按照这种方式,一张美式信纸可容纳85字符宽、66行高的内容。考虑到每页还要留有少许页边距,每行最多打印80个字符。这就解释了为什么终端(以及终端仿真器)显示宽度只有80个字符。使用等宽字体和宽度为80个字符的终端能够提供所见即所得(What-You-See-Is-What-You-Get,WYSIWYG,读作whizzy-wig)的打印效果。
要发送至打字机类打印机的数据是简单的字节流,其中包含要打印的字符。例如,要打印a,那就发送该字符的ASCII编码97。此外,回车符、换行符、换页符等低编码值的ASCII控制代码提供了移动打印机滑架和纸张的方法。利用ASCII控制代码,能够实现有限的字体效果。例如粗体,可以先让打印机打印一个字符,然后退格,接着再打印一次,以此在纸面上获得更深的打印效果。如果我们使用nroff渲染手册页并通过cat -A检查输出,就能看到实际的实现过程。
bash
[me@linuxbox ~]$ zcat /usr/share/man/man1/ls.1.gz | nroff -man | cat -A | head
LS(1) User Commands LS(1)
$
$
$
N^HNA^HAM^HME^HE$
ls - list directory contents$
$
S^HSY^HYN^HNO^HOP^HPS^HSI^HIS^HS$
l^Hls^Hs [_^HO_^HP_^HT_^HI_^HO_^HN]... [_^HF_^HI_^HL_^HE]...$
^H(Ctrl-H)代表退格符,用于产生粗体效果。与此类似,我们也可以从中看到退格符/下画线序列形成的下画线效果。
1.3、图形化打印机
GUI的发展引发了打印机技术的重大转变。由于计算机日趋采用图形化显示,基于字符的打印技术也转向了图形化技术。低成本的激光打印机的出现推动了这一转变,激光打印机能够在纸张可打印区域内的任意位置打印一个个细小的点,而不再打印固定的字符,这样就可以打印比例字体(类似于排字机使用的),甚至照片和高质量图表。
但是,从基于字符的方式转向图形化方式面临着艰巨的技术挑战。原因在于,在使用基于字符的打印机时,填充一页纸所需要字节数可以用如下方法计算(假定一页有60行,每行包含80个字符):
60×80 = 4800B
相比之下,一台每英寸像素点数(Dots Per Inch,DPI)为300的激光打印机(假设每页纸的可打印区域为8×10英寸)需要的字节数为:
(8×300) × (10×300)/8 = 900 000B
因为多数慢速计算机网络根本无法处理激光打印机打印一整页纸所需要的近1MB数据,所以还需要想一个聪明的法子来解决这个问题。
页面描述语言(Page Description Language,PDL)应运而生。这是一种描述页面内容的编程语言。其描述方式基本上可以表达为"到这个位置,使用10点大小的黑体(Helvetica)绘制字符a,再到这个位置......",直到描述完页面中的所有内容。第一个主流的PDL是Adobe Systems的PostScript,它如今仍被广泛使用。PostScript是专为排版和其他类型的图形图像量身定制的完备的编程语言。除了内置的35种标准的高质量字体之外,还能够在运行时(runtime)接受额外的字体。打印机一开始就内建了PostScript支持,这解决了数据传输问题。尽管相较于基于字符的打印机的简单字节流,PostScript程序显得过于烦琐,但比起描述整个页面所需的数据量,它可就小得太多了。
PostScript打印机能够接受PostScript程序作为输入。这种打印机自带处理器和存储器(经常使打印机成了一台比所连接的计算机还要强大的"计算机"),执行称作PostScript解释器的特殊程序。解释器读入PostScript程序,将渲染后的结果存入打印机内存,形成向纸张传送的位(点)模式。将事物渲染成大型的位模式(也称为位图)的工具,通常叫作光栅图像处理器(Raster Image Processor,RIP)。
随着计算机和网络的速度越来越快,RIP也从打印机转移到了主机,高质量的打印机也因此变得便宜多了。
很多打印机如今仍可以接受字符流,不过不少打印机已经不接受了。它们依赖于主机的RIP提供比特流,按照点进行打印。
2、Linux的打印功能
现代Linux系统采用两种软件套件(suite)来执行和管理打印。一种是通用UNIX打印系统(Common UNIXPrinting System,CUPS),提供了打印驱动和打印作业管理;另一种是Ghostscript(PostScript解释器),用作RIP。
CUPS通过创建和维护打印队列来管理打印机。我们在22.1节说过,UNIX的打印功能最初用来管理由多个用户共享的集中式打印机。因为打印机本身的速度比为其传入数据的计算机要慢,打印系统需要采用某种方式来调度多个打印作业,保持一切井井有条。CUPS还能够识别不同类型的数据(在合理范围内),将文件转换成可打印的形式。
3、准备文件打印
pr---转换要打印的文本文件
第21章简单地介绍了pr,现在我们要研究其用于打印操作时的一些选项。在22.1节中,我们了解了基于字符的打印机如何使用等宽字体使每行(水平方向)的字符数(列数)和每页(垂直方向)的行数固定。pr可用于调整文本以适应特定纸张的大小,包括可选的页眉和页边距。下表总结了常用的pr选项。

pr经常作为管道中的过滤器。在这个例子中,我们生成/usr/bin的内容列表并使用pr将其格式化为分页的3列打印内容:
bash
[me@linuxbox ~]$ ls /usr/bin | pr -3 -w 65 | head
2016-02-18 14:00 Page 1
[ apturl bsd-write
411toppm ar bsh
a2p arecord btcflash
a2ps arecordmidi bug-buddy
a2ps-lpr-wrapper ark buildhash
4、将打印作业发送至打印机
CUPS支持以前类UNIX系统上的两种打印方法。一种叫作Berkeley或LPD(在UNIX的Berkeley软件发行版中使用),用的是lpr命令;另一种叫作SysV(源于UNIX的System V版本),用的是lp命令。这两个命令做的事大致相同,用户可依据个人喜好选择。
4.1、 lpr---以Berkeley风格打印文件
lpr可以将文件发送至打印机。因为能够接受标准输入,所以它也可用在管道中。例如,要想打印之前多列显示的目录内容,可以这样做:
bash
[me@linuxbox ~]$ ls /usr/bin | pr -3 | lpr
待打印内容会被发送至系统的默认打印机。要想将文件发送到其他打印机,可以使用-P选项:
bash
[me@linuxbox ~]$ lpstat -a
下表描述了一些常用的lpr选项。

4.2、lp---以System V风格打印文件
和lpr一样,lp也可以接受文件或标准输入进行打印。不同于lpr的地方在于,lp支持不同(且略有些复杂)的选项集。下表描述了常用的lp选项。

我们再次生成目录内容列表,这次按照12CPI、8LPI、1.5英寸左页边距来打印。注意,必须调整pr选项以适应新的页面大小:
bash
[me@linuxbox ~]$ ls /usr/bin | pr -4 -w 90 -l 88 | lp -o page-left=36 -o cpi=12
-o lpi=8
该管道使用了比默认规格更小的字体生成了一个4列列表。每英寸所增加的字符数使一页纸中能够容纳更多的列。
4.3、a2ps---在PostScript打印机上打印文件
a2ps(大多数发行版仓库中能找到)是一个很有意思的命令。从命令名可以看出它是一个格式转换程序,但其功能远不止如此。该名称的原意是从ASII到PostScript(ASCII to PostScript),用于准备要在PostScript打印机上打印的文本文件。然而,随着时间的推移,a2ps的功能不断壮大,其名称的含义也变成了从任何事物到PostScript(Anything to PostScript)。单看名称,a2ps仍旧是一个格式转换程序,但其实已经变成了打印程序。它会将默认输出发送至系统默认的打印机,而非标准输出。程序默认采用"优质打印"模式,也就是说会增强输出的视觉效果。我们可以用该程序在桌面上创建一个PostScript文件。
bash
[me@linuxbox ~]$ ls /usr/bin | pr -3 -t | a2ps -o ~/Desktop/ls.ps -L 66
[stdin (plain): 11 pages on 6 sheets]
[Total: 11 pages on 6 sheets] saved into the file '/home/me/Desktop/ls.ps'
这里,我们使用pr的-t选项(忽略页眉和页脚)过滤数据流,然后使用a2ps指定打印文件(-o选项)以及每页包含66行(-L选项),以此匹配pr的分页打印。如果我们选用合适的文件浏览器查看输出文件,可以看到下图所示的a2ps打印效果。

如我们所见,默认的打印布局是"双幅"(two-up)格式,也就是在一张纸上打印两页内容。a2ps还在其中添加了漂亮的页眉和页脚。
a2ps包含大量选项,如表所示。

以上只是对a2ps选项的概括,更多的选项尚未列出。
5、监控打印作业
UNIX打印系统用于处理来自多个用户的多个打印作业,CUPS也是如此。每台打印机都有一个打印队列,打印作业排列在其中,等待被送至打印机打印。CUPS提供了多个命令行程序来管理打印机状态和打印队列。就像lpr和lp,这些管理程序都以Berkeley和System V打印系统的相应程序为原型。
5.1、 lpstat---显示打印系统状态
lpstat可以确定系统中打印机的名称和可用性。例如,如果系统配备了一台物理打印机(名为printer)和一台PDF虚拟打印机(名为PDF),我们可以像下面这样检查其状态:
bash
[me@linuxbox ~]$ lpstat -a
PDF accepting requests since Mon 08 Dec 2017 03:05:59 PM EST
printer accepting requests since Tue 24 Feb 2018 08:43:22 AM EST
而且,我们还能确定更详细的打印系统配置信息:
bash
[me@linuxbox ~]$ lpstat -s
system default destination: printer
device for PDF: cups-pdf:/
device for printer: ipp://print-server:631/printers/printer
在这个例子中,我们看到printer是系统的默认打印机,它还是一台通过互联网打印协议(Internet PrintingProtocol,IPP)连接在系统printer-server上的网络打印机。
下表描述了一些常用的lpstat选项。

5.2、lpq---显示打印队列状态
lpq可以显示打印队列状态。我们以此了解队列状况以及其中包含的打印作业。下面的例子显示了系统默认打印机 printer的空队列:
bash
[me@linuxbox ~]$ lpq
printer is ready
no entries
如果未指定打印机(使用-P选项),则显示系统默认打印机的打印队列状态。如果向打印机发送一份作业,然后查看打印队列,就可以看到该作业。
bash
[me@linuxbox ~]$ ls *.txt | pr -3 | lp
request id is printer-603 (1 file(s))
[me@linuxbox ~]$ lpq
printer is ready and printing
Rank Owner Job File(s) Total Size
active me 603 (stdin) 1024 bytes
5.3、lprm/cancel---取消打印作业
CUPS提供了两个可用于终止打印作业并将其从打印队列中删除(取消打印作业)的程序。一个是Berkeley风格的lprm,另一个是System V风格的cancel。两者在支持的选项方面略有不同,但基本功能一样。以前文的打印作业为例,可以按照下列方式取消该打印作业:
bash
[me@linuxbox ~]$ cancel 603
[me@linuxbox ~]$ lpq
printer is ready
no entries
这两个命令都有对应的选项,可以按照特定用户、特定打印机、特定作业参数来取消打印作业。它们的细节参见各个命令的手册页。