11.5.LPD(行式打印机程序) ========================== 在后台打印文件被称为 *打印后台处理服务* 打印队列。打印后台处理服务程序允许用户继续使用计算机上的其他程序,而不必等待打印机慢慢完成打印任务。 FreeBSD 包括一个叫做 `lpd(8) `__ 的打印后台处理服务。打印任务是用 `lpr(1) `__ 来提交的。 11.5.1.初始设置 --------------- 需要创建用于存储打印任务的目录,设置权限,防止其他用户查看这些文件的内容: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # mkdir -p /var/spool/lpd/lp # chown daemon:daemon /var/spool/lpd/lp # chmod 770 /var/spool/lpd/lp 打印机是在 **/etc/printcap** 中定义的。每台打印机的条目包括名称、所连接的端口和其他各种设置等细节。用这些内容创建 **/etc/printcap**\ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session lp:\ ① :lp=/dev/unlpt0:\ ② :sh:\ ③ :mx#0:\ ④ :sd=/var/spool/lpd/lp:\ ⑤ :lf=/var/log/lpd-errs: ⑥ ① 该打印机的名称。\ `lpr(1) `__ 将打印任务发送到 lp 打印机,除非用 -P 指定其他打印机,所以默认的打印机应该被命名为 ``lp``\ 。 ② 打印机所连接的设备。可以用合适的连接类型来替换这一行。 ③ 在打印任务开始时不打印标题页。 ④ 不限制打印任务的最大尺寸。 ⑤ 访问该打印机的打印队列目录的路径。每台打印机都有自己的打印队列目录。 ⑥ 该打印机上的错误情况的日志文件位置。 创建 **/etc/printcap** 后,使用 `chkprintcap(8) `__ 来进行测试,以排除潜在的错误: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # chkprintcap 在继续下一步之前先解决出现的错误。 在 **/etc/rc.conf** 启用\ `lpd(8) `__ : .. raw:: latex \diilbookstyleinputcell .. code:: shell-session lpd_enable="YES" 启动打印服务: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # service lpd start 11.5.2.通过 `lpr `__ 进行打印 -------------------------------------------------------------------------------------------------- 文件通过 ``lpr`` 被发送到打印机。需要打印的文件可以用命令行的方式来命名并被传送到 ``lpr``\ 。下面这两条命令效果相同,都是把 **doc.txt** 的内容发送到默认打印机打印: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % lpr doc.txt % cat doc.txt | lpr 可以用 -P 来指定打印机。如要将分件发送到名为 *laser* 的打印机打印: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % lpr -Plaser doc.txt 11.5.3.过滤器 ------------- 之前的例子都是把文本文件的内容直接发送到打印机打印。只要打印机识别那些文件的内容,就可以正确进行打印。 一些打印机不能打印纯文本格式,提交打印机的文件可能根本不是纯文本格式。 *过滤器* 可以转换或处理这些文件。一种常用的情况是把发送进来的文件,如纯文本格式,转换到打印机可以识别的形式,如 PostScript® 或 PCL。过滤器还能提供额外的功能,比如添加页号或突出显示源代码部分来更便于阅读。 这里要讨论的过滤器是 *输入过滤器* 和 *字符过滤器* 这些过滤器把收到的文件转换为不同格式。在创建文件之前需要先使用 `su(1) `__ 切换到 ``root`` 用户。 过滤器可以通过 ``if=identifier`` 在 **/etc/printcap** 中进行定义。如要使用 **/usr/local/libexec/lf2crlf** 作为过滤器,修改 **/etc/printcap** 如下: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session lp:\ :lp=/dev/unlpt0:\ :sh:\ :mx#0:\ :sd=/var/spool/lpd/lp:\ :if=/usr/local/libexec/lf2crlf:\ ① :lf=/var/log/lpd-errs: ① ``if=`` 指定的输入过滤器会作用于所有接收到的文本 **技巧** **printcap** 中定义的打印机也可以用被反斜杠和冒号等字符分隔的 *一长行* 来定义,之前的例子可以用下面单独一行来说明,尽管有些难以阅读: .. code:: shell-session 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 文本文件在每行末尾只包含一个换行字符,就会在标准的打印机上出现如下阶梯状打印结果: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session A printed file looks like the steps of a staircase scattered by the wind 过滤器可以把新行的字符转换为回车符和新行。回车符让打印机在打印每一行后回到下一行的最左方。创建 **/usr/local/libexec/lf2crlf** 并增加如下内容: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session #!/bin/sh CR=$'\r' /usr/bin/sed -e "s/$/${CR}/g" 设置相关可执行权限: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # chmod 555 /usr/local/libexec/lf2crlf 修改 **/etc/printcap** 使用新过滤器: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session :if=/usr/local/libexec/lf2crlf:\ 再次打印同样的纯文本格式文件来进行测试。顺利的话回车符就会让每行从页面的最左方开始。 11.5.3.2.用 `print/enscript `__ 让 PostScript® 打印机打出漂亮的纯文本字体 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GNUEnscript 可以让支持 PostScript® 的打印机把纯文本格式文件转换为排版优美的 PostScript® 进行打印。它还增加了页码,自动换行和其它许多特性,让打印出来的文本更易于阅读。根据纸张尺寸大小,从 ports 安装 `print/enscript-letter `__ 或者 `print/enscript-a4 `__\ 。 创建 **/usr/local/libexec/enscript** 并添加以下内容: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session #!/bin/sh /usr/local/bin/enscript -o - 设置权限为可执行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # chmod 555 /usr/local/libexec/enscript 更改 **/etc/printcap** 来使用新过滤器: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session :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 \*\* 并添加以下内容: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session #!/bin/sh /usr/local/bin/gs -dSAFER -dNOPAUSE -dBATCH -q -sDEVICE=ljet4 -sOutputFile=- - 设置权限为可执行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # chmod 555 /usr/local/libexec/ps2pcl PostScript® 格式的内容经过该脚本处理后会被转换为 PCL 格式再发送到打印机。 修改 **/etc/printcap** 来使用这个新的过滤器: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session :if=/usr/local/libexec/ps2pcl:\ 发送少量 PostScript® 格式内容来进行测试: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % 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** 并添加以下内容: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session #!/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 设置文件权限为可执行: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # chmod 555 /usr/local/libexec/psif 修改 **/etc/printcap** 来使用新过滤器: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session :if=/usr/local/libexec/psif:\ 打印 PostScript® 格式的纯文本文件来测试过滤器。 11.5.3.5.其它智能过滤器 ~~~~~~~~~~~~~~~~~~~~~~~ 编写一个能识别许多不同类型的输入并正确进行格式转换是非常有挑战的。ports 中的 `print/apsfilter `__ 是一种智能而且神奇的过滤器,它可以识别十几种文件格式类型并自动把它们转换为能被打印机理解的 PDL 打印描述语言。更多详细内容请参考 http://www.apsfilter.org\ 。 11.5.4.多打印队列配置 --------------------- **/etc/printcap** 中的内容严格来说就是各种打印机 *队列* 定义。可以为单台打印机增加许多队列定义,当与过滤器同时使用时,这些不同的队列为用户提供了更多的控制来完成打印任务。 举个例子,在某个办公室有一台联网的 PostScript® 激光打印机。大多数用户想打印纯文本格式,但有些更高级的用户希望能直接打印 PostScript® 格式的文件,那么可以在 **/etc/printcap:** 中为这两类群体创建两种打印队列: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session 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) `__ 显示用户打印任务的状态。其它用户的打印任务不会显示。 下例显示当前用户在单台打印机上还未完成的打印任务: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % lpq -Plp Rank Owner Job Files Total Size 1st jsmith 0 (standard input) 12792 bytes 下例显示当前用户在所有打印机上的任务状态: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % 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`` 用户可以删除任何或所有的打印任务。 删除某台打印机上所有未完成的打印任务: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # lprm -Plp - dfA002smithy dequeued cfA002smithy dequeued dfA003smithy dequeued cfA003smithy dequeued dfA004smithy dequeued cfA004smithy dequeued 删除某台打印机上单项打印任务。可以用 `lpq(1) `__ 来查找打印任务编号。 .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % 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`` 用户才可以使用修改打印机状态的命令。 显示所有打印机的状态: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % 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 阻止打印机接收新打印任务,然后又开始重新接收新打印任务: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # lpc disable lp lp: queuing disabled # lpc enable lp lp: queuing enabled 停止打印,但可以继续接收新打印任务。然后开始继续打印: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # lpc stop lp lp: printing disabled # lpc start lp lp: printing enabled daemon started 在出现一些出错情况后重新启动打印机: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # lpc restart lp lp: no daemon to abort printing enabled daemon restarted 关闭打印队列并使打印机不可用,并将相关信息告知所有用户: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # lpc down lp Repair parts will arrive on Monday lp: printer and queuing disabled status message is now: Repair parts will arrive on Monday 重新恢复被设置为不可用的打印机: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session # lpc up lp lp: printing enabled daemon started 更多命令和参数选项请参考 `lpc(8) `__\ 。 11.5.6.共享打印机 ----------------- 在公司和学校中打印机经常被设置为不同用户共同使用。有些额外功能可以让共享打印机变得更加方便。 11.5.6.1.别名 ~~~~~~~~~~~~~ 打印机名称可以在 **/etc/printcap** 中第一行配置里进行设置。额外的名称,或 *别名* 可以添加到打印机名称之后。用 ``|`` 来区隔打印机名称以及不同的别名(可以有多个别名): .. raw:: latex \diilbookstyleinputcell .. code:: shell-session lp|repairsprinter|salesprinter:\ 在使用打印机名称的地方都可以用别名来替代。例如,销售部门的用户可以如下别名来进行打印: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % lpr -Psalesprinter sales-report.txt 维修部门的用户也可以使用如下别名来进行打印: .. raw:: latex \diilbookstyleinputcell .. code:: shell-session % lpr -Prepairsprinter repairs-report.txt 所有的文档都在同一台打印机上打印。当销售部门足够扩展到需要他们自己的打印机时,可以把别名从共享打印机配置里删除并把同样的名字用于新的打印机。在两个部门的用户们可以使用之前的命令继续打印,但销售部门的文档就会发送到新打印机进行打印。 11.5.6.2.报头页 ~~~~~~~~~~~~~~~ 在从一台任务繁忙的共享打印机上的一堆纸张中找到自己的打印文档对用户们来说不是一件容易得事情。报头页就是用来解决这个问题的方法。在每项打印任务之前,用户名和文档名称会被打印在报头部分。这些页面有时也被称为 *横幅页* 或 *分隔页*\ 。 根据打印机连接到计算机的方式不同(USB 连接,并口连接,串口连接或网络连接等),报头页的设置也有所不同。 直接连接打印机的报头页功能可以通过删除 **/etc/printcap** 中 **:sh:\\**\ (不用报头)这一配置行来启用。这些报头页只使用换行字符来进行换行。有些打印机还需要 **/usr/share/examples/printing/hpif** 过滤器来防止出现楼梯状的打印文本。当需要换行打印时,过滤器控制 PCL 格式打印机可以同时正常打印回车和换行字符。 网络打印机报头页设置必须在打印机上进行。\ **/etc/printcap** 的报头页配置不会起作用。通常这种设置可以在打印机上的控制面板或网页版设置页面上进行。 11.5.7.其它参考 --------------- 示例文档: **/usr/share/examples/printing/**\ 。 *4.3BSD 行式打印机队列手册*\ ,\ **/usr/share/doc/smm/07.lpd/paper.ascii.gz**\ 。 手册页面:\ `printercap(5) `__, `lpd(8) `__\ ,\ `lpr(1) `__\ ,\ `lpc(8) `__\ ,\ `lprm(1) `__\ ,\ `lpq(1) `__\ 。