第22章:打印
在学习了这么多章节的文本操作之后,是时候把这些文本放在纸上了。本章中,我们将学习用来打印文件和控制打印机操作的命令行工具。我们不会学习如何配置打印,因为这是随着各个发行版不同而变化的,而且通常在安装时会自动设置好。注意,本章中我们需要一台配置良好的、可工作的打印机以供练习。
我们将讨论下列命令:
pr
转换文本文件供打印lpr
打印文件a2ps
为 PostScript 打印机调整文件格式lpstat
显示打印机状态信息lpq
显示打印机序列状态lprm
取消打印任务
打印简史
要完整地理解类 Unix 操作系统的打印特性,我们必须要学了解一点历史。类 Unix 系统上的打印要回溯到操作系统的开始阶段。那时候,打印机及其用法,和今天的很不一样。
昏暗时代的打印
和计算机一样,打印机在前 PC 时代是庞大且昂贵和中心化的。典型的 1980 年代的计算机用户,工作在连接着远程计算机的终端前面。打印机则位于计算机附近,且在计算机操作者的监视之中。
当打印机还是昂贵且中心化的时候,常常是在 Unix 的早期,常见的情况是多个用户共享一台打印机。要识别打印任务属于哪个特定用户,在每个打印任务的开端会有一张标题页(banner page),显示用户的姓名。随后,计算机支持人员会将一天的打印任务装载在一个手推车上,分发给各个用户。
基于字符的打印机
八十年代的打印机技术区别于今天的,有两个方面。首先,那个时代的打印机几乎全都是撞击式打印机(impact printers)。撞击式打印机使用的机械机制是对着纸张撞击一根绸带,以便在纸上形成字符印迹。那时流行的两个技术是菊花轮打印(daisy-wheel)和点阵打印(dot-matrix)。
其次,早期打印机更重要的特性是,打印机使用一套固化在设备中的固定字符集。例如,一台菊花轮打印机仅能打印铸在菊花轮花瓣中的字符。这使得打印机看起来更像高速打字机。如大多数打字机一样,它们使用等宽字体。意思是,每个字符的宽度是相等的。在页面的固定位置完成打印,页面上的可打印区域包含固定数目的字符。大多数打印机在水平方向每英寸中打印 10 个字符(CPI characters per inch),垂直方向每英寸打印 6 行(LPI line per inch)。使用该方案,一页美国信纸有 85 字符宽和 66 行高。考虑到每边的小边距,80 个字符被认为是打印行的最大宽度。这就是为何终端显示器(和我们的终端模拟器)正常情况下 80 字符宽的原因。使用等宽字体和 80 字符宽的终端,提供了一种所见即所得(What You See Is What You Get WYSIWYG)的打印效果。
数据以包含字符的简单的字节流被传送到打字机样式的打印机上供打印。例如,要打印一个 a,就传输 ASCII 码 97。另外,低数值的 ASCII 控制码提供的是移动打印机卷轴和纸张的意义,如使用回车符(carriage return)、换行符(line feed)、换页符(form feed)等等。使用控制符,可以达到某些受限制的字体效果,如粗体字,是通过打印一个字符后退格,再打印一次该字符,在纸上就得到了更深的印迹。如果使用 nroff
渲染一个手册页,用 cat -A
检验输出,我们确实可以见证此效果。
^H
(Ctrl-h)字符是用来制造粗体效果的退格键。同样的,我们可以用退格键和下划线组合序列来制造下划线。
图形打印机
图形用户界面的发展导致打印机技术的巨大改变。当计算机转换到更多的基于图形的显示时,打印也从基于字符转换到图形技术。低成本激光打印机的出现促进了这一点,该打印机不是打印固定字符,而是可以在页面的可打印区域中的任何位置打印小点。这使得打印比例字体(和那些排字工所用的一样)甚至图形和高质量图表成为可能。
然而,从基于字符的方案转移到图形方案展现出一个可怕的技术挑战。因为:使用基于字符的打印机填充一页纸所需的字节数是可以通过下列算式得出的(假设每页 60 行、每行 80 字):
60 x 80 = 4,800 字节
比较一下,一个每英寸 300 点(DPI dot per inch)的激光打印机(假设每页可打印区域是 8 x 10 英寸)需要的字节数是:
(8 x 300) x (10 x 300) / 8 = 900,000 字节
很多缓慢的网络直接不能处理这近 1 兆打印到激光打印机上一张纸的数据,所以很明显,需要一个更聪明的发明。
这发明的结果就是页面描述语言(PDL Page description language)。页面描述语言是一种描述页面内容的编程语言。基本地,它会说「到这个位置,用 10 点的 Helvetica 画一个字符 'a',到这个位置……」直到页面上的所有都被描述清楚。第一个重要的 PDL 是来自 Adobe 系统公司的 PostScript,直到今天还在广泛应用。PostScript 语言是为排版和其它类型的图形图像量身定制的完整的编程语言。其内建支持 35 种标准高品质字体,还有在运行时接受额外字体定义的能力。最初,对 PostScript 的支持是内建在打印机自身中的。这解决了传输数据的问题。典型的 PostScript 程序对比简单字节流的基于字符的打印机,显得非常冗长,而其所需表示一张完整页面的字节数则远小于彼。
一台 PostScript 打印机以一个 PostScript 程序为输入。打印机包含其自身的处理器和内存(通常使打印机成为比它附带的计算机更强大的计算机),执行一个被成为 PostScript 解释器的特定程序,因此形成可以被传输到纸上的比特样式(点)。将某些东西渲染成大位模式(位图 bitmap)的过程的通用名称是光栅图像处理器(RIP raster image processor)。
很多年过去了,计算机和网络都变得更快速了。这就允许 RIP 从打印机转移到主机,作为回报,高质量的打印机可以更廉价了。
今天的很多打印机还能接受基于字符的文本流,但是很多低成本的打印机则不能。它们依赖于主机 RIP 提供比特流供点打印。还有一些 PostScript 打印机。
用 Linux 打印
现代 Linux 系统采用两个软件套装执行并管理打印。第一个是常用 Unix 打印系统(CUPS)提供打印驱动和打印任务管理,第二个 Ghostscript,一个 PostScript 解释器,和 RIP 一样。
CUPS 通过创建并维护打印序列(print queues)来管理打印机。如我们在早期历史的课程中所讨论的,Unix 打印最初设计为管理中心化的打印机,共享给多个用户。因为打印机天然就比输送给它的计算机慢,打印系统需要有途径管理多个打印任务,保持事务井井有条。CUPS 还有能识别不同数据类型的能力(在合理范围内)和可以转换文件到可打印形式的能力。
为打印准备文件
作为命令行用户,我们最感兴趣的就是打印文本,尽管它当然还可能打印其它数据格式。
pr - 为打印转换文本文件
上一章中我们接触到了一点儿 pr
。现在将要研究其用于与打印相关联的众多选项。在打印的历史中,我们看到了基于字符打印机是使用等宽字体的,导致了固定的每行字符数和固定的每页行数。pr
用来调整文本以适应特定纸型,同时可选页眉和边距。表 22-1 总结了最常用的选项。
表 22-1:常用 pr
选项
选项
描述
+first[:last]
从 first
页开始输出页面序列,以可选的 last
页结束。
-columns
将页面内容组织为 comlumn
数目的栏位。
-a
默认情况下多栏输出是垂直方向列出。通过加 -a
(横跨)选项,则水平分栏。
-d
双倍空格输出。
-D "format"
用 format
格式显示页眉上的日期。可以查看 date
命令的手册页以获取格式字符串的描述。
-f
使用换页符而非回车符来分隔页面。
-h "header"
在页眉中部,使用 "header"
而非正在处理的文件名。
-l length
将页面长度设置为 length
。默认值为 66(美国信纸每英寸 6 行)。
-n
编行号。
-o offset
创建一个宽为 offset
字符的左边距。
-w width
设置页面宽度为 width
。默认值为 72。
pr
常被用在管道命令中作为一种过滤器。下面这个例子中,我们制作一个 /usr/bin
目录的清单,用 pr
格式化为三栏的分页输出:
将打印任务送达打印机
CUPS 打印套件支持两种模式的打印,都是历史上用在类 Unix 系统上的。第一种叫伯克利或者 LPD(用在 Unix 伯克利软件发行版),使用 lpr
程序,第二种叫 SysV(来自 System V 版本的 Unix),使用 lp
程序。两个程序粗略看来就是一回事。选择哪种,取决于个人喜好。
lpr - 打印文件(伯克利风格)
lpr
程序可以用来将文件发送到打印机。也可以用在管道命令中,接收标准输入。例如,要打印之前的多列目录列表,可以如下操作:
报告会被发送到系统默认的打印机。要发送到另一台打印机,需要用 -P
选项:
这里的 printer_name
是所需打印机的名称。要查看系统所能识别的打印机清单,用如下命令:
提示:许多 Linux 发行版允许你定义一台「打印机」以输出 PDF 文件,而不是打印到物理打印机。这对试验打印命令非常方便。检查你的打印机配置程序,查看其是否支持这项配置。在某些发行版中,你可能需要安装额外的软件包(如
cups-pdf
)以激活该功能。
表 22-2 描述了 lpr
的常见选项。
表 22-2:常见 lpr
选项
选项
描述
# number
设置打印份数。
-p
在每页打印带阴影的页眉,包含日期、时间、任务名称和页码。这被称为「美化打印」选项,可以用在打印文本文件时。
-P printer
指定用于输出的打印机名称。如果没有指定,则使用系统默认打印机。
-r
在打印后删除文件。该选项对在制作临时打印输出文件的程序很有用。
lp - 打印文件(System V 风格)
和 lpr
一样,lp
可以接收文件或标准输入以打印。区别于 lpr
的是其支持一套不同的(有些更复杂的)选项。表 22-3 描述了常见选项。
表 22-3:常见 lp
选项
选项
描述
-d printer
设置目标(打印机)为 printer
。如果没有指定 d
选项,则使用系统默认打印机。
-n number
设置打印份数。
-o landscape
设置横向输出。
-o fitplot
缩放文件以适应页面。当打印如 JPEG 图像文件时有用。
-o scaling=number
缩放文件到 number
。值为 100 则布满页面。少于 100 则减小,大于 100 会导致文件打印在多页上。
-o cpi=number
设置每英寸字符数。默认是 10。
-o lpi=number
设置每英寸行数。默认是 6。
-o page-bottom=points
-o page-left=points
-o page-right=points
-o page-top=points
设置页面边距。值的单位是点(points),一种印刷测量单位。每英寸为 72 点。
-p pages
指定页面列表。pages
可以是逗号分隔的列表,也可以是一个序列,例如,1,3,5,7-10
。
再来制作一次目录清单,这次使用 12 CPI 和 8 LPI,同时有半英寸的左边距。注意,考虑到新的页面尺寸,我们必须调整 pr
选项。
这个管道命令制作了一个四栏列表,使用了比默认值更小的字体。增加每英寸字符数允许我们适应页面上更多的栏。
另一个选项: a2ps
a2ps
程序(在大多数软件仓库中可用)很有意思。我们可以从它的名称中推测其为一个转换格式的程序,不过还不止于此。它得名于 "ASCII to PostScript",用来预备文本文件以供 PostScript 打印机打印。很多年过去了,程序的能力也在成长,现在它的名字意味着 "Anything to PostScript"。看它的名字可能是个格式转换程序,但是实际上它是个打印程序。它会将其默认输出到系统默认打印机而非标准输出。程序的默认行为是个「美观打印机」,意味着它改进了输出的显示。我们使用程序来创建一个 PostScript 文件到桌面上。
我们用 pr
筛选文本流,用 -t
选项(忽略页眉页脚),随后使用 a2ps
,指定一个输出文件(-o
选项)、每页 66 行(-L
选项),以匹配 pr
的输出分页。要是我们用合适的文件查看器打开结果文件,会看到如下图所示:
可以看到,默认的输出布局是「拼页」格式。使得每张纸上都打印两页内容。a2ps
同时还应用了漂亮的页眉页脚。
a2ps
有很多选项。表 22-4 提供了一个概览。
表 22-4:a2ps
选项
选项
描述
--center-title=text
设置页面居中标题为 text
。
--columns=number
将页面整理为 number
列。默认为 2。
--footer=text
设置页脚文字为 text
。
--guess
报告作为参数给出的文件类型。 由于 a2ps
尝试转换和格式化所有类型的数据,因此该选项对于预测给定特定文件时 a2ps
将执行的操作非常有用。
--left-footer=text
设置左页面的页脚为 text
。
--left-title=text
设置左页面的页眉为 text
。
--line-numbers=interval
设置每隔 interval
行编行号。
--list=defaults
显示默认设置。
--pages=range
打印序列中的页面。
--right-footer=text
设置右页面的页脚为 text
。
--right-title=text
设置右页面的页眉为 text
。
--rows=number
将页面整理为 number
行。默认为 1。
-B
不显示页眉。
-b text
设置页眉为 text
。
-f size
使用 size
大小的字体。
-l number
设置每行字数为 number
。这和 -L
选项(下面一条)可以用来和其它程序,如 pr
一起制作文件分页,正确地适应页面。
-L number
设置每页行数为 number
。
-M name
使用媒体 name
。如 A4
。
-n number
设置每页输出的份数为 number
。
-o file
将输出发送到 file
。如果 file
被指定为 -
,则使用标准输出。
-P printer
使用 printer
打印机。如果没有指定,则使用系统默认打印机。
-R
纵向输出。
-r
横向输出。
-T number
设置制表符的位置为 number
字符。
-u text
设置页面水印为 text
。
这仅仅是个概览。a2ps
还有更多的选项。
注意:还有一个输出格式程序,用来将文本转换为 PostScript。名为
enscript
,它可以执行同样的格式和打印技巧,但是和a2ps
不同的是,它仅仅接收文本输入。
监视和控制打印任务
因为 Unix 打印系统是涉及为处理多用户的多任务的,所以 CUPS 也是如此。每个打印机有个打印序列(print queue),任务会停在那里,直到它们被假脱机到打印机。CUPS 提供了几个命令行程序用以管理打印机状态和打印序列。和 lpr
及 lp
程序一样,这些管理程序是与伯克利和 System V 打印系统相应的。
lpstat - 显示打印系统状态
lpstat
程序对确定系统上的打印机的名称和可用性很有用。例如,如果我们的系统有一台物理打印机(名为 printer)和一台 PDF 虚拟打印机(名为 PDF),我们可以这样去检测它们的状态:
更进一步,可以确定打印系统配置更细节的描述,如下:
本例中,我们看到 "printer" 是系统默认打印机,还有一台使用因特网打印协议(Internet Printing Protocol ipp://)挂载在系统的名为 "print-server" 的网络打印机。
表 22-5 列出了常用选项。
表 22-5:常用 lpstat
选项
选项
描述
-a [printer...]
显示 printer
打印机的打印机序列状态。注意这是打印机序列接收任务的能力的状态,不是物理打印机的状态。若不指定打印机,则列出所有打印序列。
-d
显示系统默认打印机的名称。
-p [printer...]
显示指定打印机 printer
的状态。如果没有指定打印机,则显示全部。
-r
显示打印服务器的状态。
-s
显示状态概览。
-t
显示一份完整的状态报告。
lpq - 显示打印机队列状态
要查看打印机序列的状态,就要用到 lpq
程序。这允许我们查看序列的状态及其打印任务。这里是一个对名为 "printer" 的系统默认打印机的空序列的示例。
如果我们没有指定打印机(用 -P
选项),则显示系统默认打印机。如果我们发送了一个任务到打印机,然后再看序列,可以看到已经被列出了。
lprm / cancel - 取消打印任务
CUPS 提供两个程序用来结束打印任务并将其从打印序列中移除。一个是伯克利风格的(lprm
),一个是 System V(cancel
)。两者之间区别在于所支持的选项略有不同,不过基本上是完成同一件事。使用早先的打印任务作为示例,我们可以按下例所示,停止任务,移除序列:
每个命令对于移除某个特定用户的所有任务、或者特定打印的所有任务、或者多个任务编号的任务,都各有其选项。它们各自的手册页中有详细的说明。
总结
本章中,我们看到了过去的打印机如何影响类 Unix 机器上的打印系统的设计,以及命令行上有多少控制是可用的,不仅仅是控制打印任务的计划和执行,而且还有各种输出选项。
扩展阅读
伯克利和 System V 打印系统
Last updated
Was this helpful?