第 11 章. 打印

尽管许多人试图消除纸质信息,但将信息付诸纸张仍然是一项至关重要的功能。打印有两个基本组成部分。数据必须传递到打印机,并且必须以打印机能够理解的格式。

11.1. 快速入门

基本打印设置可以快速完成。打印机必须能够打印纯 ASCII 文本。有关打印其他类型文件的信息,请参阅 过滤器

  1. 创建一个目录来存储打印文件。

    # mkdir -p /var/spool/lpd/lp
    # chown daemon:daemon /var/spool/lpd/lp
    # chmod 770 /var/spool/lpd/lp
  2. root 用户身份创建 /etc/printcap,内容如下

    lp:\
    lp=/dev/unlpt0:\  (1)
    sh:\
    mx#0:\
    sd=/var/spool/lpd/lp:\
    lf=/var/log/lpd-errs:
    1此行用于连接到 USB 端口的打印机。

    对于连接到并行端口或“打印机”端口的打印机,请使用

    :lp=/dev/lpt0:\

    对于直接连接到网络的打印机,请使用

    :lp=:rm=network-printer-name:rp=raw:\

    网络打印机名称 替换为网络打印机的 DNS 主机名。

  3. 通过编辑 /etc/rc.conf 并添加以下行来启用 LPD

    lpd_enable="YES"

    启动服务

    # service lpd start
    Starting lpd.
  4. 打印测试

    # printf "1. This printer can print.\n2. This is the second line.\n" | lpr

    如果两行没有从左边界开始,而是“阶梯式”排列,请参阅 防止纯文本打印机上的阶梯式排列

    现在可以使用 lpr 打印文本文件。在命令行中提供文件名,或者将输出直接管道到 lpr

    % lpr textfile.txt
    % ls -lh | lpr

11.2. 打印机连接

打印机可以通过多种方式连接到计算机系统。小型台式打印机通常直接连接到计算机的 USB 端口。较旧的打印机连接到并行端口或“打印机”端口。一些打印机直接连接到网络,使多台计算机可以轻松共享它们。少数打印机使用罕见的串行端口连接。

FreeBSD 可以与所有这些类型的打印机通信。

USB

USB 打印机可以连接到计算机上任何可用的 USB 端口。

当 FreeBSD 检测到 USB 打印机时,将创建两个设备条目:/dev/ulpt0/dev/unlpt0。发送到这两个设备中的任何数据都将转发到打印机。在每次打印作业之后,ulpt0 将重置 USB 端口。重置端口可能会导致某些打印机出现问题,因此通常使用 unlpt0 设备。 unlpt0 根本不重置 USB 端口。

并行 (IEEE-1284)

并行端口设备是 /dev/lpt0。无论是否连接打印机,此设备都会出现,它不会自动检测。

供应商已经从这些“传统”端口中大幅转移,许多计算机不再拥有这些端口。可以使用适配器将并行打印机连接到 USB 端口。使用此类适配器,打印机可以像实际的 USB 打印机一样进行处理。称为 打印服务器 的设备也可以用于将并行打印机直接连接到网络。

串行 (RS-232)

串行端口是另一种传统端口,除了某些特定应用之外,很少用于打印机。电缆、连接器和所需的布线差异很大。

对于内置于主板的串行端口,串行设备名称为 /dev/cuau0/dev/cuau1。也可以使用串行 USB 适配器,这些适配器将显示为 /dev/cuaU0

为了与串行打印机通信,必须知道几个通信参数。最重要的参数是 波特率BPS(每秒位数)和 奇偶校验。这些值各不相同,但典型的串行打印机使用 9600 的波特率且没有奇偶校验。

网络

网络打印机直接连接到本地计算机网络。

必须知道打印机的 DNS 主机名。如果打印机由 DHCP 分配动态地址,则应动态更新 DNS,以便主机名始终具有正确的 IP 地址。网络打印机通常被分配静态 IP 地址以避免此问题。

大多数网络打印机都理解使用 LPD 协议发送的打印作业。还可以指定打印队列名称。一些打印机根据使用哪个队列来处理数据。例如,raw 队列将数据原样打印,而 text 队列会在纯文本中添加回车符。

许多网络打印机也可以打印直接发送到端口 9100 的数据。

11.2.1. 总结

有线网络连接通常最易于设置并提供最快的打印速度。对于直接连接到计算机,USB 因其速度和简便性而更受青睐。并行连接有效,但对电缆长度和速度有限制。串行连接更难配置。不同型号之间的电缆布线有所不同,并且波特率和奇偶校验位等通信参数会增加复杂性。幸运的是,串行打印机很少见。

11.3. 通用页面描述语言

发送到打印机的数据必须使用打印机能够理解的语言。这些语言被称为页面描述语言或 PDL。

Ports Collection 和 FreeBSD 实用程序中的许多应用程序生成 PostScript® 输出。下表显示了可用于将其转换为其他常用 PDL 的实用程序

为了获得最简单的打印效果,请选择支持 PostScript® 的打印机。支持 PCL 的打印机是下一个最佳选择。使用 print/ghostscript9-base,这些打印机可以像原生支持 PostScript® 一样使用。直接支持 PostScript® 或 PCL 的打印机几乎总是支持直接打印纯 ASCII 文本文件。

基于行的打印机(如典型的喷墨打印机)通常不支持 PostScript® 或 PCL。它们通常可以打印纯 ASCII 文本文件。print/ghostscript9-base 支持某些打印机使用的 PDL。但是,在这些打印机上打印整个基于图形的页面通常非常缓慢,因为要传输和打印大量数据。

基于主机的打印机通常更难设置。由于专有 PDL,有些根本无法使用。尽可能避免使用这些打印机。各种型号打印机使用的特定 PDL 可以在 http://www.openprinting.org/printers 上找到。

11.4. 直接打印

对于偶尔打印,可以在没有任何设置的情况下将文件直接发送到打印机设备。例如,可以将名为 sample.txt 的文件发送到 USB 打印机

# cp sample.txt /dev/unlpt0

直接打印到网络打印机取决于打印机的功能,但大多数打印机都接受端口 9100 上的打印作业,并且可以使用 nc(1) 与之通信。要将同一个文件打印到 DNS 主机名为 netlaser 的打印机

# nc netlaser 9100 < sample.txt

11.5. LPD(行打印机守护程序)

在后台打印文件被称为 后台打印。后台打印程序允许用户在打印机缓慢完成打印作业时继续使用计算机上的其他程序。

FreeBSD 包含一个名为 lpd(8) 的后台打印程序。打印作业是使用 lpr(1) 提交的。

11.5.1. 初始设置

创建一个用于存储打印作业的目录,设置所有权,并设置权限以防止其他用户查看这些文件的内容

# mkdir -p /var/spool/lpd/lp
# chown daemon:daemon /var/spool/lpd/lp
# chmod 770 /var/spool/lpd/lp

打印机在 /etc/printcap 中定义。每个打印机的条目都包含一些详细信息,如名称、连接的端口以及各种其他设置。创建 /etc/printcap,内容如下

lp:\				(1)
	:lp=/dev/unlpt0:\	(2)
	:sh:\			(3)
	:mx#0:\			(4)
	:sd=/var/spool/lpd/lp:\	(5)
	:lf=/var/log/lpd-errs:	(6)
1此打印机的名称。 lpr(1) 将打印作业发送到 lp 打印机,除非使用 -P 指定了其他打印机,因此默认打印机应命名为 lp
2打印机连接的设备。用此处显示的连接类型替换此行。
3抑制打印作业开始时打印标题页。
4不限制打印作业的最大大小。
5此打印机的后台处理目录路径。每个打印机使用自己的后台处理目录。
6报告此打印机错误的日志文件。

创建 /etc/printcap 后,使用 chkprintcap(8) 测试其是否存在错误。

# chkprintcap

在继续之前修复任何报告的问题。

/etc/rc.conf 中启用 lpd(8)

lpd_enable="YES"

启动服务

# service lpd start

11.5.2. 使用 lpr(1) 打印

使用 lpr 将文档发送到打印机。要打印的文件可以在命令行中命名,也可以通过管道传递到 lpr。这两个命令是等效的,将 doc.txt 的内容发送到默认打印机

% lpr doc.txt
% cat doc.txt | lpr

可以使用 -P 选择打印机。要打印到名为 laser 的打印机

% lpr -Plaser doc.txt

11.5.3. 过滤器

到目前为止,显示的示例已将文本文件的原始内容直接发送到打印机。只要打印机能够理解这些文件的内容,输出就会正确打印。

有些打印机无法打印纯文本,输入文件甚至可能不是纯文本。

过滤器允许转换或处理文件。典型用法是将一种类型的输入(如纯文本)转换为打印机可以理解的格式,如 PostScript® 或 PCL。过滤器还可以用来提供额外的功能,例如添加页码或突出显示源代码,使其更容易阅读。

这里讨论的过滤器是输入过滤器文本过滤器。这些过滤器将传入文件转换为不同的格式。在创建文件之前,使用 su(1) 成为 root

/etc/printcap 中使用 if= 标识符指定过滤器。要使用 /usr/local/libexec/lf2crlf 作为过滤器,请修改 /etc/printcap,如下所示

lp:\
	:lp=/dev/unlpt0:\
	:sh:\
	:mx#0:\
	:sd=/var/spool/lpd/lp:\
	:if=/usr/local/libexec/lf2crlf:\   (1)
	:lf=/var/log/lpd-errs:
1if= 标识将在传入文本上使用的输入过滤器

printcap 条目中行末的斜杠续行字符显示打印机条目实际上只是一条长行,其中条目由冒号字符分隔。前面的示例可以重写为一条更难读的行

lp:lp=/dev/unlpt0:sh:mx#0:sd=/var/spool/lpd/lp:if=/usr/local/libexec/lf2crlf:lf=/var/log/lpd-errs:

11.5.3.1. 阻止纯文本打印机上的阶梯式打印

典型的 FreeBSD 文本文件在每行末尾只包含一个换行符。这些行会在标准打印机上出现“阶梯式”打印

A printed file looks
                    like the steps of a staircase
                                                 scattered by the wind

过滤器可以将换行符转换为回车符和换行符。回车符使打印机在每行结束时返回到左侧。使用以下内容创建 /usr/local/libexec/lf2crlf

#!/bin/sh
CR=$'\r'
/usr/bin/sed -e "s/$/${CR}/g"

设置权限并使其可执行

# chmod 555 /usr/local/libexec/lf2crlf

修改 /etc/printcap 以使用新的过滤器

:if=/usr/local/libexec/lf2crlf:\

通过打印相同的纯文本文件来测试过滤器。回车符将使每行从页面的左侧开始。

11.5.3.2. 使用 print/enscript 在 PostScript® 打印机上进行精美的纯文本打印

GNUEnscript 将纯文本文件转换为格式优良的 PostScript®,以便在 PostScript® 打印机上打印。它添加了页码,换行长行,并提供了许多其他功能,使打印的文本文件更容易阅读。根据本地纸张尺寸,从 Ports 集合安装 print/enscript-letterprint/enscript-a4

使用以下内容创建 /usr/local/libexec/enscript

#!/bin/sh
/usr/local/bin/enscript -o -

设置权限并使其可执行

# chmod 555 /usr/local/libexec/enscript

修改 /etc/printcap 以使用新的过滤器

:if=/usr/local/libexec/enscript:\

通过打印纯文本文件来测试过滤器。

11.5.3.3. 将 PostScript® 打印到 PCL 打印机

许多程序生成 PostScript® 文档。但是,廉价打印机通常只理解纯文本或 PCL。此过滤器将 PostScript® 文件转换为 PCL,然后再将它们发送到打印机。

从 Ports 集合安装 Ghostscript PostScript® 解释器 print/ghostscript9-base

使用以下内容创建 /usr/local/libexec/ps2pcl

#!/bin/sh
/usr/local/bin/gs -dSAFER -dNOPAUSE -dBATCH -q -sDEVICE=ljet4 -sOutputFile=- -

设置权限并使其可执行

# chmod 555 /usr/local/libexec/ps2pcl

发送到此脚本的 PostScript® 输入将被渲染并转换为 PCL,然后发送到打印机。

修改 /etc/printcap 以使用此新的输入过滤器

:if=/usr/local/libexec/ps2pcl:\

通过向其发送一个小的 PostScript® 程序来测试过滤器

% printf "%%\!PS \n /Helvetica findfont 18 scalefont setfont \
72 432 moveto (PostScript printing successful.) show showpage \004" | lpr

11.5.3.4. 智能过滤器

检测输入类型并自动将其转换为适合打印机的格式的过滤器非常方便。PostScript® 文件的前两个字符通常是 %!。过滤器可以检测这两个字符。PostScript® 文件可以不变地发送到 PostScript® 打印机。文本文件可以使用前面显示的 Enscript 转换为 PostScript®。使用以下内容创建 /usr/local/libexec/psif

#!/bin/sh
#
#  psif - Print PostScript or plain text on a PostScript printer
#
IFS="" read -r first_line
first_two_chars=`expr "$first_line" : '\(..\)'`

case "$first_two_chars" in
%!)
    # %! : PostScript job, print it.
    echo "$first_line" && cat && exit 0
    exit 2
    ;;
*)
    # otherwise, format with enscript
    ( echo "$first_line"; cat ) | /usr/local/bin/enscript -o - && exit 0
    exit 2
    ;;
esac

设置权限并使其可执行

# chmod 555 /usr/local/libexec/psif

修改 /etc/printcap 以使用此新的输入过滤器

:if=/usr/local/libexec/psif:\

通过打印 PostScript® 和纯文本文件来测试过滤器。

11.5.4. 多个队列

/etc/printcap 中的条目实际上是队列的定义。单个打印机可以有多个队列。当与过滤器结合使用时,多个队列可以为用户提供更多对打印作业方式的控制。

例如,考虑办公室中一个网络连接的 PostScript® 激光打印机。大多数用户想要打印纯文本,但一些高级用户希望能够直接打印 PostScript® 文件。可以在 /etc/printcap 中为同一台打印机创建两个条目

textprinter:\
	:lp=9100@officelaser:\
	:sh:\
	:mx#0:\
	:sd=/var/spool/lpd/textprinter:\
	:if=/usr/local/libexec/enscript:\
	:lf=/var/log/lpd-errs:

psprinter:\
	:lp=9100@officelaser:\
	:sh:\
	:mx#0:\
	:sd=/var/spool/lpd/psprinter:\
	:lf=/var/log/lpd-errs:

发送到 textprinter 的文档将由前面示例中显示的 /usr/local/libexec/enscript 过滤器格式化。高级用户可以在 psprinter 上打印 PostScript® 文件,此时不会进行任何过滤。

这种多队列技术可以用来提供对所有类型的打印机功能的直接访问。具有双面打印机的打印机可以使用两个队列,一个用于普通的单面打印,另一个使用过滤器发送命令序列以启用双面打印,然后发送传入文件。

11.5.5. 监视和控制打印

有多种实用程序可用于监视打印作业并检查和控制打印机操作。

11.5.5.1. lpq(1)

lpq(1) 显示用户打印作业的状态。不会显示其他用户的打印作业。

显示当前用户在单个打印机上的待处理作业

% lpq -Plp
Rank   Owner      Job  Files                                 Total Size
1st    jsmith     0    (standard input)                      12792 bytes

显示当前用户在所有打印机上的待处理作业

% lpq -a
lp:
Rank   Owner      Job  Files                                 Total Size
1st    jsmith     1    (standard input)                      27320 bytes

laser:
Rank   Owner      Job  Files                                 Total Size
1st    jsmith     287  (standard input)                      22443 bytes

11.5.5.2. lprm(1)

lprm(1) 用于删除打印作业。普通用户只能删除自己的作业。root 可以删除任何或所有作业。

从打印机中删除所有待处理作业

# lprm -Plp -
dfA002smithy dequeued
cfA002smithy dequeued
dfA003smithy dequeued
cfA003smithy dequeued
dfA004smithy dequeued
cfA004smithy dequeued

从打印机中删除单个作业。 lpq(1) 用于查找作业编号。

% lpq
Rank   Owner      Job  Files                                 Total Size
1st    jsmith     5    (standard input)                      12188 bytes

% lprm -Plp 5
dfA005smithy dequeued
cfA005smithy dequeued

11.5.5.3. lpc(8)

lpc(8) 用于检查和修改打印机状态。lpc 后面跟着一个命令和一个可选的打印机名称。all 可以代替特定的打印机名称,该命令将应用于所有打印机。普通用户可以使用 lpc(8) 查看状态。只有 root 可以使用修改打印机状态的命令。

显示所有打印机的状态

% lpc status all
lp:
	queuing is enabled
	printing is enabled
	1 entry in spool area
	printer idle
laser:
	queuing is enabled
	printing is enabled
	1 entry in spool area
	waiting for laser to come up

阻止打印机接受新作业,然后开始再次接受新作业

# lpc disable lp
lp:
	queuing disabled
# lpc enable lp
lp:
	queuing enabled

停止打印,但继续接受新作业。然后开始再次打印

# lpc stop lp
lp:
	printing disabled
# lpc start lp
lp:
	printing enabled
	daemon started

在某些错误状况后重新启动打印机

# lpc restart lp
lp:
	no daemon to abort
	printing enabled
	daemon restarted

关闭打印队列并禁用打印,并附上消息向用户解释问题

# lpc down lp Repair parts will arrive on Monday
lp:
	printer and queuing disabled
	status message is now: Repair parts will arrive on Monday

重新启用已关闭的打印机

# lpc up lp
lp:
	printing enabled
	daemon started

有关更多命令和选项,请参阅 lpc(8)

11.5.6. 共享打印机

打印机通常在企业和学校中由多个用户共享。提供了一些额外的功能,使共享打印机更加方便。

11.5.6.1. 别名

打印机名称设置在 /etc/printcap 中条目中的第一行。可以在该名称之后添加其他名称或别名。别名用竖线与名称和其他别名分隔

lp|repairsprinter|salesprinter:\

别名可以代替打印机名称使用。例如,销售部门的用户可以使用以下方法打印到他们的打印机

% lpr -Psalesprinter sales-report.txt

维修部门的用户可以使用以下方法打印到他们的打印机

% lpr -Prepairsprinter repairs-report.txt

所有文档都在该单个打印机上打印。当销售部门发展壮大到需要自己的打印机时,可以从共享打印机条目中删除别名,并将其用作新打印机的名称。这两个部门的用户继续使用相同的命令,但销售部门的文档将发送到新打印机。

11.5.6.2. 标题页

对于用户来说,很难在繁忙的共享打印机生成的页面堆栈中找到自己的文档。标题页的创建是为了解决这个问题。在每个打印作业之前都会打印一个带有用户名和文档名的标题页。这些页面有时也称为横幅分隔符页面。

启用标题页的方式取决于打印机是直接连接到计算机(使用 USB、并行或串行电缆),还是通过网络远程连接。

直接连接打印机的标题页可以通过从 /etc/printcap 中的条目中删除 :sh:\(抑制标题)行来启用。这些标题页只使用换行符来表示新行。某些打印机可能需要 /usr/share/examples/printing/hpif 过滤器以防止阶梯式打印。过滤器配置 PCL 打印机在收到换行符时打印回车符和换行符。

网络打印机的标题页必须在打印机本身配置。 /etc/printcap 中的标题页条目将被忽略。设置通常可以通过打印机前面板或可使用 Web 浏览器访问的配置网页获得。

11.5.7. 参考资料

示例文件:/usr/share/examples/printing/.

4.3BSD 行打印机后台程序手册/usr/share/doc/smm/07.lpd/paper.ascii.gz.

手册页:printcap(5)lpd(8)lpr(1)lpc(8)lprm(1)lpq(1).

11.6. 其他打印系统

除了内置的 lpd(8) 之外,还有其他几种打印系统可用。这些系统提供了对其他协议或附加功能的支持。

11.6.1. CUPS(通用 UNIX® 打印系统)

CUPS 是一种流行的打印系统,在许多操作系统上都可用。使用 FreeBSD 上的 CUPS 的文档在单独的文章中:CUPS

11.6.2. HPLIP

惠普提供了一个打印系统,支持他们的大多数喷墨和激光打印机。该端口是 print/hplip。主网页位于 https://developers.hp.com/hp-linux-imaging-and-printing。该端口处理 FreeBSD 上的所有安装细节。配置信息显示在 https://developers.hp.com/hp-linux-imaging-and-printing/install

11.6.3. LPRng

LPRng 被开发为 lpd(8) 的增强替代方案。该端口是 sysutils/LPRng。有关详细信息和文档,请参见 https://lprng.sourceforge.net/.


上次修改于:2024 年 9 月 20 日,作者 Fernando Apesteguía