思科系统公司 Linux 打印系统

作者:Damian Ivereigh

在您的办公室里,您可以打印到最近的打印机,还是必须使用专为您的桌面机器设置的打印机? 如果您想将作业发送到另一个部门或另一个办公室的打印机,您可以像使用本地打印机一样轻松地做到吗? 在大多数大型公司中,答案是否定的。

系统管理员很少愿意处理打印问题,而且也很少有人可以求助。 出于绝望,您决心自己解决问题,却被告知:“我的同事尝试过这样做,结果导致打印中断了一周。 不要碰它。” 简而言之,打印已成为一个潘多拉魔盒,没有人愿意打开。 它周围的民间传说和巫术比现代计算的任何其他领域都多。

在本文中,我将描述大型企业环境中打印的常见问题以及解决这些问题的一般方法。 然后,我将详细介绍我是如何在思科解决具体问题的。 通过使用几乎完全可以从互联网上下载的软件,我创建了一个高度可见、任务关键型、容错的打印系统,每天被全球超过 10,000 人使用。

简而言之,该解决方案依赖于多个 Linux 服务器,这些服务器通过相互通信,有效地作为一个单一的“分布式机器”工作。 这种方法为许多固有问题提供了一种解决方案,这些问题不仅存在于打印系统中,而且更普遍地存在于大型企业网络中的任何网络资源(例如,邮件、磁盘空间等)。

分布式机器听起来可能很复杂,但几乎没有涉及什么魔法。 正如我们将看到的,“魔法”来自于应用传统的 UNIX 方法,将许多小碎片组合成一个远大于其各部分总和的整体。

打印策略

首先,让我们谈谈人们在企业环境中打印时面临的一些常见问题。 打印机基于机械部件,其速度和可靠性不如向其发送作业的计算机; 因此,需要队列和频繁的状态更新。

尽管供应商正在努力创建标准(例如,打印机工作组 [PWG] 的工作),但目前的标准化很差,打印机制造商正在对其机器进行编程,以便与尽可能多的不同标准(或仿真)进行通信。 这些仿真很少能很好地工作,或者允许用户良好地控制打印机。

从本质上讲,组织打印主要有两种策略:直接客户端到打印机或通过中央打印服务器。

1. 直接客户端到打印机

客户端直接连接到打印机,并在发送打印作业时完全控制它。 任何打印机状态都直接发送回客户端。 打印机完成后,客户端断开连接,然后打印机可供另一个客户端使用。

1a. 优点

此方法更适用于小型办公室。 每个人的机器都是独立于其他人的机器设置的——无需考虑任何更大的问题。 由于每个用户都是隔离的,因此问题通常只影响单个用户。 只要他的打印机不发生故障,个别用户就可以继续打印,而无需考虑其他人可能遇到的问题。

每个用户直接控制自己的队列。 他可以使用操作系统提供的任何工具取消自己机器上的作业。

1b. 缺点

使用直接客户端到打印机系统,执行任何全局更改都很困难。 如果打印机的 IP 地址发生更改,工程师必须追踪并重新配置许多客户端机器。

每台客户端机器都必须竞争打印机。 如果打印机在客户端尝试打印时已经繁忙,则客户端必须不断重试,直到打印机空闲为止。

提供有序队列很困难。 由于所有客户端都以随机顺序获得打印机的控制权,因此无法保证任何特定客户端的作业何时开始打印,或者作业将以任何特定顺序打印。 客户端几乎不可能知道其他客户端正在等待打印机。

客户端只能打印到支持其协议的打印机。 例如,Apple Macintosh 只能与支持 AppleTalk 的打印机通信。

追踪和取消未知作业也不容易。 例如,如果打印机正忙于打印一份 2,000 页的文件,则发送客户端不明显,要实际停止打印作业,系统管理员必须获得该客户端机器上的适当权限。

对一种协议的修复可能会破坏其他协议。 服务技术人员往往是自己领域的专家,他们很容易破坏其他协议的功能。 例如,工程师可能会重置打印机以解决 Novell 打印问题,并在此过程中破坏 TCP/IP 设置(反正他也不理解 TCP/IP 设置)。

某些打印机无法在不同协议之间良好切换。 有些打印机,尤其是较旧的打印机,甚至在 TCP/IP 和 AppleTalk 之间切换时,已知会完全崩溃(需要重新启动)。

2. 中央打印服务器

客户端将其打印作业发送到中央打印服务器并断开连接。 打印服务器接收作业并将其添加到指定打印机的队列中。 然后,打印服务器连接到打印机并发送作业。 任何状态都发送到打印服务器,而不是客户端。

2a. 优点

由于打印服务器具有很大的存储容量,因此它可以随时接收作业,而无需考虑打印机正在做什么。 客户端机器可以发送作业,然后继续处理另一个作业。

作业通过中央队列,队列按接收顺序打印作业。 每个用户都应该能够(在操作系统允许的情况下)通过查看此打印服务器队列来查看打印机上所有等待打印的作业。

系统管理员可以终止打印服务器上的任何作业,而无需考虑其来源。

如果打印机发生故障,则很容易将所有来自故障打印机的作业重新路由到正常工作的打印机。

任何打印机更改都可以在中央打印服务器上单独进行,因为这是唯一直接与打印机通信的机器。

2b. 缺点

中央打印服务器系统更加复杂。 它需要系统管理员来设置打印服务器并保持其运行。

如果打印服务器崩溃,则所有打印都会停止,除非有良好的备份打印服务器可用。

用户没有队列控制权。 诸如打印作业取消之类的琐碎任务落在了系统管理员的肩上,如果用户不再具有像直接客户端到打印机情况那样自己执行这些任务的权限或技能。

常用打印系统

大多数大型公司都对中央服务器方法进行了半心半意的尝试。 当实施多个“中央”服务器时,真正的问题就开始了。 UNIX 系统管理员设置了 UNIX 打印服务器,Windows 人员设置了 NT 服务器,并且一些客户端完全跳过服务器,直接连接到打印机。 所有作业都在一台打印机上汇合,混乱随之而来。

您现在遇到了中央服务器方法的所有问题,再加上客户端到打印机方法的所有问题,以及为了凑趣而额外添加的一些问题。 打印机更改必须由多个系统管理员在多个服务器上实施,从而导致多个潜在错误。 多台机器(现在是服务器而不是客户端)竞争同一台打印机,没有有序的排队,我们仍然不知道那份 2,000 页的文件来自哪里。

更糟糕的是,每个环境对同一台打印机都有不同的名称,这使得追踪打印机更加困难。 当用户遇到问题时,他很可能不知道他试图从哪个环境打印。 他会打电话给错误的系统管理员,而系统管理员在他的环境中找不到用户的打印机名称。 系统管理员会建议用户致电另一个组,该组会将用户传递给另一个组,依此类推。 五个系统管理员之后,用户又回到了第一个系统管理员。 总之,这对每个人来说都是一次令人沮丧的经历。 这种情况开始在思科发生。

理想的打印系统

在处理这些问题几个月后,我决定找到一种更好的方法。 我坐下来详细描述了我认为的“理想打印系统”。 它必须具有服务器方法的优点,同时减轻一些缺点。

  • 多协议:服务器必须能够与客户端发送和打印机接收的所有不同协议进行通信。

  • 超可靠:使用冗余来消除大多数中央服务器方法中固有的单点故障。

  • 单点排队:无论作业来自何处或采用何种路由,特定打印机的所有作业都必须落入由一台机器处理的单个队列中。

  • 可扩展且灵活:思科是一家不断发展的公司。 任何系统都必须能够很好地扩展并允许频繁的重组。

  • 集中、分散和远程可管理:思科在全球设有办事处,其中一些办事处拥有本地专业知识,而另一些则没有。

  • 便宜:该系统必须是小型办公室可以负担得起的,并且可以扩展以供总部使用。

  • 队列管理下放给用户:系统管理员没有时间; 用户想要控制权。

  • 避免重复:任何手动复制的信息都容易出错。 即使将 IP 地址输入到打印机和打印服务器中也应被视为重复。

  • 易于管理:无论为了冗余或容量添加多少服务器,这些服务器的管理都必须保持简单。

思科的初始配置

当我开始在思科工作时,打印变得难以管理(参见图 1)。 虽然思科在这方面并不比大多数公司更糟糕,但他们依赖打印来完成其制造流程。 他们知道系统高效运行非常重要。 因此,我被聘请来维护和改进现有的 UNIX 打印系统,该系统使用了两台小型基于 SunOS 的打印服务器。

尽管这两台服务器绝不控制思科的全部打印,但由于我是一名专职的打印系统管理员,因此人们普遍认为我控制了打印。

图 1. 思科的原始打印配置

公司的大型 UNIX 服务器有时打印到一台打印服务器,有时打印到另一台打印服务器。 UNIX 工作站通过打印服务器打印或直接打印到打印机。 Apple Macintosh(在桌面上广泛使用)始终直接打印。 大多数打印机仅识别 AppleTalk,因此使用 Gatorbox(来自 Caiman Systems)将 UNIX 打印作业转换为 AppleTalk。

Caiman Systems 已经倒闭,Gatorbox 间歇性崩溃。 我的前任已经开始在一些 Hewlett-Packard (HP) 打印机上启用 TCP/IP 协议,以便 UNIX 打印服务器可以直接与它们通信。 这样做需要将 IP 地址插入到每台打印机中(通过前面板),或者在每台打印服务器中设置 bootptab 条目,以便打印机可以使用 BOOTP 协议找到其 IP 地址(请参阅词汇表)。

理论上,一台打印服务器是主服务器,另一台是备份服务器。 但是,这两台服务器的配置差异很大。 设置的重复是手动的,即必须在两台机器上配置打印队列。 一些中央 UNIX 服务器排队到“主”打印服务器,另一些排队到“备份”打印服务器。 一些打印机设置为在某些中央 UNIX 服务器上打印,而另一些则没有。 我花了很多时间追踪打印问题,但最终发现它们通常归结为配置不正确。

思科从未直接指示我设计新的打印系统。 他们只是要求我确保打印工作正常。 他们相信我会做任何我认为必要的事情。 我改进它的动机仅仅是因为我发现重复性的任务很无聊且没有成就感。 我发现最令人沮丧的事情莫过于治疗症状,而忽略疾病。 我从未决定完全抛弃旧系统,我只是慢慢地改进它——解决当下最大的问题。

消除客户端系统中的重复

每台打印机都需要在每台 UNIX 服务器(LPR 客户端)上单独设置。 这意味着大量的手工工作,无论是在设置新的 UNIX 服务器还是创建新的打印机时。 我查看了客户端 LPR 系统,意识到它有一个非常简单的功能:只需将打印作业转发到打印服务器。

这是打印机“foo”的典型 /etc/printcap 条目,它将作业直接发送到打印服务器“prntsrv”

foo:\
    :mx#0:\
    :sh:\
    :sd=/var/spool/lpd/foo:\
    :lf=/var/spool/lpd/foo/log:\
    :lp=/var/spool/lpd/foo/.null:\
    :rm=prntsrv:\
    :rp=foo:

使用不同的打印机时,唯一更改的项目是单词 foo

我获取了 LPR 源代码,并将在 /etc/printcap 中查找特定打印机条目的例程替换为伪造条目的例程。 如果 LPR 请求打印机“bar”,我的例程将返回一个类似于上面的 printcap 条目,但用 bar 代替 foo。 另一个变量是打印服务器的名称,该名称是在我为整个系统创建的主配置文件中查找的。 还有一些其他事情要做,例如创建假脱机目录,但这基本上是例程所做的全部工作。

LPR 代码的其余部分像以前一样继续执行,没有意识到任何事情已经改变。 由于我没有触及代码的其余部分,因此我的错误很少。 我消除了大量的信息重复来源,现在我可以确定公司的所有打印机都可以在所有中央 UNIX 服务器上使用,并且打印作业已发送到正确的打印服务器。

请注意,客户端也将接受不存在的打印机的打印作业(它不知道区别),并将其发送到打印服务器。 打印服务器将拒绝该作业,但不会说明原因(协议不允许)。 客户端会不断重试 48 小时,然后最终拒绝该作业并通过电子邮件发送给用户。 这不是理想的情况,但在思科是可以接受的。

消除打印服务器中的重复

接下来,我解决了每个打印服务器中的重复问题。 几个文件用于控制打印机:/etc/printcap 和 /etc/bootptab,以及每台打印机使用的一些设置文件。 每个文件都以不同的格式包含相同的信息。

在 /etc/printcap 文件中设置了三种不同的与各种打印机通信的方式

  • JetDirect,用于使用其 TCP/IP JetDirect 接口的 HP 打印机

  • 原始 TCP,用于连接到 TCP/IP 到串行转换器的串行打印机

  • LPR 协议,用于 EtherTalk 打印机(连接到 Gatorbox)或不受我控制的远程打印服务器

为了消除重复,我需要一个主配置文件,我可以从中生成三种协议所需的各种配置文件。 主配置文件包含任何协议所需的所有信息,例如名称、IP 地址、以太网硬件地址、远程服务器和远程打印机名称。 我创建了一个脚本 mkprint,它生成了所有其他配置文件,创建了假脱机目录等等。

这种方法不仅比手动编辑单个文件更简单,而且更不容易出错。 例如,由于提供给 LPR 系统的 IP 地址与提供给 BOOTP 系统的 IP 地址相同,因此它们必须匹配。 我不可能弄错它们。

Netatalk

正如我之前提到的,Gatorbox 引起了很多问题。 通常,Gatorbox 上的单个打印队列会停止接收打印作业,并且需要有人登录到 Gatorbox 并重新启动它。 它们存在严重的“内存泄漏”问题,这会导致它们耗尽内存并崩溃,需要有人亲自走到盒子并按下重置按钮。

我首先研究了 Columbia AppleTalk 协议 (CAP),然后研究了 Netatalk,作为让打印服务器直接使用 EtherTalk 的可能方法。 两者似乎都工作良好,但 Netatalk 正在更积极地开发,并且通过使用内核级驱动程序,机器上的负载更小。

通过安装 Netatalk 并修改 mkprint 系统以允许这种新型打印机,我可以从循环中删除 Gatorbox。 另一个重复项已被删除。

PC 和 Web

思科开始引入桌面 PC,尽管当时我没有意识到,但这标志着从 Macintosh 转向 PC 的重大推动的开始。 管理 PC 的桌面技术组引入了 NT 服务器作为 PC 打印服务器,我开始接到电话,要求终止我的服务器上不存在的打印作业。

我与桌面技术组建立了一些联系,并建议他们将来自其 NT 服务器的打印作业重定向到我的打印服务器,而不是直接连接到打印机。 现在我可以查看和取消所有打印作业。 但是,NT 服务器对 LPR 协议的实现很差。 例如,一旦它发送了打印作业,它就认为该作业已打印,并且用户无法从他们的 PC 上看到他们自己的作业或总打印队列。

为了缓解这种视觉反馈的缺失,我创建了一个简单的网页,该网页要求输入打印机名称,然后通过使用 lpq 命令的输出来显示打印队列。 页面的所有其他信息都是通过再次扩展 mkprint 生成的。

图 2. 理想的打印系统

现在我拥有了一个更加整洁的打印系统,所有作业都遵循从客户端到打印机的明确路径。 理想的打印系统已经成型(参见图 2)。

位置代码

思科决定扩展其在北卡罗来纳州研究三角园区 (RTP) 的设施,以包括一个完整的数据处理中心。 在那里放置一台打印服务器以减少跨 WAN 链路的打印流量似乎是明智的。

我为这台 RTP 打印服务器创建了我圣何塞打印服务器之一的完整副本。 认识到多台服务器即将到来的可管理性问题以及服务器故障(故障转移)时快速备份的要求,我决定根据物理位置将打印机组织成更易于管理的组。 我将这些组称为“位置代码”或“loccode”。 我将每个 loccode 打印机组分配给一台服务器,该服务器实际向这些打印机发送作业。 接收这些打印机作业的任何其他服务器都只会将作业转发到指定的服务器。 该系统的优点是,在服务器发生故障时,我现在可以将这些 loccode(及其关联的打印机)快速移动到另一台可操作的服务器,从而提供故障转移能力。

我为实施此系统而采取的步骤非常简单直接。 我首先使用 rcp 将主配置文件复制到每台打印服务器。 然后我修改了 mkprint,以便在创建 /etc/printcap 条目时记录 loccode 及其关联的服务器。 对于每台打印机,它都会提取其 loccode 并找出其分配的服务器。 如果该服务器是 mkprint 正在运行的服务器,则 mkprint 继续像以前一样创建 printcap 条目; 否则,它会创建一个条目,该条目只是将打印作业转发到相应的服务器。

例如,假设打印机 foo 的 loccode 为 SJK2(圣何塞,K 楼,2 楼),并且该 loccode 在列表中分配给服务器“print-sj”。 服务器“print-sj”上此打印机的 printcap 条目将与以前相同

foo:\
    :mx#0:\
    :sh:\
    :sd=/var/spool/lpd/foo:\
    :lf=/var/spool/lpd/foo/log:\
    :lp=/var/spool/lpd/foo/.null:\
    :if=/usr/local/atalk/ifpap:\
    :of=/usr/local/atalk/ofpap:

但是,任何其他打印服务器上的条目都将是

foo:\
    :mx#0:\
    :sh:\
    :sd=/var/spool/lpd/foo:\
    :lf=/var/spool/lpd/foo/log:\
    :lp=/var/spool/lpd/foo/.null:\
    :rm=print-sj:\
    :rp=foo:
最后两行告诉 lpd 程序将作业转发到 print-sj 打印服务器。

因此,作业落在哪个打印服务器上并不重要; 它将自动转发到“正确”的打印服务器。 使用此方案,打印机不可能从多个打印服务器接收作业。 这立即提供了先前作为理想打印系统一部分提到的单点排队。

我编写了一个名为 allmkprint 的简单脚本,该脚本将复制主配置文件并使用 rsh 在所有打印服务器上运行 mkprint。 我扩展了 Web 界面,使其也能够意识到是否被请求访问驻留在不同打印服务器上的打印机,并将用户的浏览器转发到该打印服务器。

现在,当服务器崩溃时,我只需将所有 loccode 移动到另一台打印服务器并运行 allmkprint——一个简单的故障转移系统就位了。

Samba

每次安装新打印机时,我不仅必须在我的 UNIX 打印服务器上创建队列,而且桌面技术组还必须在其 NT 服务器上创建单独的队列。 更糟糕的是,PC 上的驱动程序必须与 NT 下使用的驱动程序仔细匹配。

我研究了 Samba,并对其使用与 NT 相同的协议向 PC 提供相同服务的能力印象深刻。 从本质上讲,可以使 UNIX 机器伪装成 NT 服务器。 Samba 也非常可配置——以至于很容易被大量选择弄糊涂。

考虑到可能会遭到拒绝以及关于 NT 与 UNIX 的激烈争论,我向桌面技术组提出了接管 PC 打印的想法。 他们的回应是:“真的吗? 您将为我们接管设置和管理这些令人讨厌的打印机? 嘿,一切都归您了!”

但是,Samba 协议 (SMB) 有一个严重的限制:浏览(允许用户获取可用打印机列表)是使用单个 UDP 数据包完成的,因此限制为大约 8KB 的打印机名称和描述。 在我们的环境中,这转化为每台服务器大约 50 个打印机名称。 但是,我发现 Samba 能够根据 PC 认为服务器被称为的名称使用不同的配置文件。 例如,假设对于一台物理服务器,我在 Microsoft 版本的 DNS WINS 中注册了两个伪服务器名称 pserver1 和 pserver2。 PC 将看到两台服务器 pserver1 和 pserver2,它们都指向同一台物理 Samba 服务器。 Samba 服务器将根据 PC 认为它正在与哪个伪服务器通信来选择不同的配置文件并服务于不同的打印机集。 这使我们能够通过将打印机分成较小的组来有效地突破 8KB 障碍。

打印本身很简单。 Samba 配置文件指定了在接收到打印作业时要运行的程序或脚本。 通常,这是一个简单的 lpr 命令。 PC 队列显示是通过转换 lpq 命令的输出来完成的。

打印服务器当然可以与所有不同的打印机协议通信。 将 Samba 接收来自任何 PC 的作业的能力添加到此,现在任何 PC 都可以将作业发送到任何打印机——甚至是 AppleTalk 打印机。

服务组

我可以只将伪服务器名称与 loccode 关联; 但是,我发现这缺乏我需要的灵活性。 由于 PC 打印机路径(以“\伪服务器\打印机名称”的形式)在人们的 PC 中是固定的,因此我发现,如果我将打印机从一个 loccode 移动到另一个 loccode,人们将不得不在他们的 PC 上重新安装打印机。 当我进行管理更改(例如拆分 loccode 或将两个 loccode 连接在一起)时,这会导致问题; 在这种情况下,我希望能够在不涉及用户的情况下进行这些更改。

实现此目的的唯一方法是将伪服务器名称与另一个分组(而不是 loccode)直接关联:“服务组”或“sgroup”。 我可以将 loccode 与一个或多个 sgroup 关联。 相反,每个 sgroup 可以具有多个与之关联的 loccode。 用数据库术语来说,loccode 和 sgroup 具有多对多的关系。 sgroup 概念允许我拆分、连接或移动 loccode,而无需更改客户端 PC。

有关 sgroup 和 loccode 的更多信息,以及如何使用它们的示例,请参阅“Loccode 和 Sgroup”侧边栏。

进入 Linux

Samba 以及所有这些该死的 sgroup 开始给打印服务器带来相当大的负载。 我们已将圣何塞总部的打印服务器升级为两台 Sun SPARC 20; 但是,PC 使用量的增长很快就给这两台服务器带来了压力。 更糟糕的是,Windows 95 在请求打印机队列列表时有一个非常短的超时时间(少于三秒)。 如果超时,则打印机在 PC 上标记为“脱机”,并且用户需要进入设置并将打印机重新联机。 此功能产生了太多的呼叫。

我现在引入了几台 Red Hat Linux 机器作为 Samba 打印服务器。 服务器是 HP XM4:120MHz Pentium,配备 32MB RAM 和 1GB 硬盘。 这些与思科用作标准桌面机器的 PC 相同。

我没有将整个打印系统从 SunOS 移植到 Linux,所以我无法将它们用作最终打印服务器——该任务留给两台 SPARC 20 之一。 Linux 打印服务器将使用 Samba 接收来自 PC 的打印作业,然后将它们转发到 SPARC 打印服务器。 由于我之前解释的 sgroup 和 loccode 系统,这是可能的。

简单分布式数据库 (SDDB)

由于思科的增长以及大量的日常打印管理,我允许工程师访问以编辑主配置文件。 但是,这正在造成问题。 由于该文件是用 vi 编辑的,因此没有锁定,并且我开始遇到人们覆盖彼此更改的问题。 此外,文件变得如此之大,以至于 mkprint 程序需要花费大量时间才能运行。 我需要将此配置数据放入数据库中。

我编写了我认为会是“简单分布式数据库”(SDDB)的东西。 我很快发现前两个词是自相矛盾的。 它实际上更像是一个“网络目录”而不是数据库——它执行的功能类似于 Sun 的 NIS(黄页)。

NIS 维护单独的域,每个域都有一个主服务器和多个副本服务器。 虽然每个 NIS 服务器都可以存储多个域的数据,但数据永远不会合并。 客户端必须“绑定”或附加到特定服务器上的特定域,并且只能查询该域中的数据。

SDDB 也维护单独的域,每个域都有自己的主服务器和副本服务器。 每个主服务器接收其自身域的记录更新,并将这些更改传播到所有域中的所有其他服务器。 来自每个域的数据在每台服务器上合并到单个连续数据库中——原始域存储在每个记录上。 因此,当客户端查询数据时,它是跨所有域执行的。

记录以“字段=值”的可变长度列表形式保存。 仅存储定义的值,并且可以随时添加新值。

索引保存在内存中,使用“红黑”树算法。 所有创建和比较都由用户提供的函数完成,因此索引非常灵活。 SDDB 允许多个索引,并且可以检测和拒绝重复条目,这与 NIS 不同,后者在每个文件或表上仅允许一个索引。

SDDB 服务器是完全无状态的(即,它们不存储客户端请求之间的任何信息),并使用快速 UDP 协议来执行所有事务。 修改序列号(类似于修改时间)保存在每个记录上,以便主服务器可以确定哪些记录已更新并且需要传播到其他服务器。 由于仅传输修改后的数据,因此传播延迟可以非常短——目前约为 30 秒。

SDDB 具有 C 和 shell 脚本的 API。 因此,您可以使用脚本来查询、更新或删除数据库中的记录。 数据库不与打印系统绑定——它可以用于存储任何类型的面向记录的数据。

SDDB 的效果

我在每台打印服务器上安装了 SDDB,并将所有主配置数据转换为 SDDB 记录。 SDDB 现在可以为 mkprint 提供配置数据,mkprint 生成配置文件(/etc/printcap 等)。 我用 C 重写了 mkprint(它最初是用 shell 和 awk 脚本编写的),这极大地提高了它的速度。 它不再需要使用 rcp,因为数据已经存在于本地服务器上。 我重写了 Web (CGI) 程序,以便它们不再依赖 mkprint 的输出,而是直接从 SDDB 接收其信息。

我为 SDDB 编写了一个前端,称为 pradmin,专为打印系统设计。 它使用一个简单的命令行界面,类似于思科路由器界面。 现在,多个用户可以同时更新数据库,而无需担心冲突。

随着越来越多的程序开始依赖 SDDB 及其包含的数据,SDDB 成为连接所有打印服务器的粘合剂。单次更新会影响许多服务器,这些服务器将协同运作。每台打印服务器都知道思科的每台打印机,并据此采取行动。“分布式机器”已初具雏形。

Linux 走向应用

思科开始了收购小型公司的热潮,尤其是在旧金山湾区,因此是时候开始安装更多的打印服务器了。Linux 机器是最佳选择,因为它们价格便宜。一台 Linux 打印服务器的成本不到 2000 美元,不到其商业竞争对手 Sun 的 SPARC 5 的三分之一。

我移植并重写了其余的程序,这些程序在那之前只能在 SunOS 上运行。现在,Linux 机器可以执行打印服务器的全部功能。

一台打印服务器安装在斯科茨谷几英里外的路上。除了一些初期问题外,它运行良好。然后我们运了一台到澳大利亚悉尼。我预先配置了 IP 地址,因此悉尼的系统管理员唯一要做的就是连接电源和网络。它完美地运行了。SDDB 服务器启动,复制了数据,我运行了 mkprint,一切就绪。

rdist

rdist 是一种工具,允许在服务器之间镜像目录。这可以通过执行精确镜像(包括删除文件)或仅添加到已存在的目录并替换它们来完成。

使用此工具,我们可以将目录结构放在主分发服务器上,并使其自动镜像到所有其他服务器。这是又一个巨大的节省时间的方法,因为我们管理的服务器数量增加了。我们甚至将 /etc/passwd 和 /etc/group 文件包括在使用 rdist 更新的文件中。

设置新服务器变得非常简单:安装一个原生的 Red Hat 发行版,然后在上面 rdist 打印系统。

新的 Web 内容

我对网页进行了另一次修改。我添加了停止和启动打印队列以及删除打印作业和发送测试页面的功能。

我发现,在使用 SNMP 时,我可以显示 HP 打印机的前面板显示,这极大地帮助解决了诸如“墨粉用尽”之类的常见问题。

Web 界面成为诊断打印机问题的首选工具,并向所有人开放。它允许用户解决许多自己的打印机问题,而无需致电我们。

故障转移

正如我之前提到的,loccodes 提供了一个基本的故障转移程序。但是,如果要更新所有 loccode 和 sgroup 记录以指示发生故障时的新服务器,这将是一项艰巨的任务。幸运的是,我从未需要使用它。

我在 loccode 和 sgroup 记录中添加了一个备份服务器字段,并创建了一个名为 pserver 的新 SDDB 表。其中详细说明了服务器的状态(“up”或“down”),以及其他信息。我修改了 mkprint,以便在创建配置文件时,它将检查每个 loccode 和 sgroup 记录上指定的 primary 服务器的状态。如果服务器被标记为“down”,mkprint 将指示 LPR 使用备份服务器。

现在,故障转移仅仅是在 SDDB 中将死掉的服务器标记为“down”,然后在所有服务器上重新运行 mkprint。

LPR 的后端

mkprint 系统的唯一问题是,对 SDDB 记录的任何更新都不会立即反映在打印服务器中。我是否可以使各种程序绕过其配置文件并直接读取 SDDB?

我打开了 LPR 代码,并再次替换了读取 /etc/printcap 文件的例程。然而,这一次,它们读取 SDDB 记录并相应地创建了一个内存中的 printcap 条目,使用了与 mkprint 相同的算法。然后我对 BOOTP 做了同样的事情。它不再需要读取 /etc/bootptab,而是直接从 SDDB 读取其信息。

现在,每当 SDDB 中进行更改时,打印队列都会立即创建,并且 BOOTP 服务器可以立即为 BOOTP 请求提供服务。故障转移甚至不需要运行 mkprint。Samba 是唯一剩下的没有直接从 SDDB 读取其信息的程序。

Linux 接管

在圣何塞总部数据中心发生极端停电以及由于容量问题导致普遍性能下降之后,打印系统的可见性提高了。突然,管理人员意识到,如果没有打印系统,任何东西都无法打印,生产线也停止了。命令下达“立即将打印系统的容量增加一倍”。我得到了一位助手 Ben Woodard (bwoodard@cisco.com),以提供急需的额外人手。虽然最初受雇于思科担任 MS Windows 支持热线技术员,但在几个月内,我已将他转变为 Linux 的忠实粉丝。

我们在圣何塞总部的数据中心安装了十台新的 Linux 服务器。Linux 打印服务器遍布世界各地

  • 圣何塞总部 13 台

  • 硅谷周边 3 台

  • 欧洲 4 台

  • 北卡罗来纳州 RTP 2 台

  • 日本东京 2 台

  • 澳大利亚悉尼 1 台

1997 年 8 月 1 日,我们淘汰了 SPARC 20 和其他 Axil 机器。我们现在完全依赖 Linux 服务器——找不到一行商业代码。我们拥有(或至少可以访问)我们正在运行的每个程序的源代码。

未来

我们最近开始更换思科分支机构的打印功能。到目前为止,他们一直使用本地 NT 服务器(及其相关问题)来管理他们的打印机。虽然分支机构只有我们 5% 的打印机,但它们占我们呼叫量的约 50%。我们已经(截至 1998 年 2 月)向这些分支机构部署了 30 台 Linux 服务器,还有更多服务器正在路上——目前总共有大约 200 个分支机构。

随着我们扩展系统以满足打印客户端的需求,仍有大量工作要做。我们心中有以下目标

  • 改进 SNMP 功能。启用陷阱,以便打印机在出现问题时告诉我们。

  • 使用 Java 创建打印队列。打印队列的创建仍然需要乐于登录系统并运行 pradmin(打印机队列管理程序)的人员。为什么不允许任何拥有浏览器和正确授权的人员创建队列?

  • 用 LPRng 甚至互联网打印协议 (IPP) 的实现替换 LPR 程序。LPR 正在显现其老旧,并且没有提供许多功能(例如,发送诸如双面打印之类的打印选项)。

  • 使用 SNMP 从打印机中提取页面计数。我们应该能够安排工程师定期维护访问。

  • 实施 DHCP 服务器。许多打印机现在支持 DHCP 以及 BOOTP。DHCP 服务器将使我们能够避免为打印机分配 IP 地址。

  • 致力于 SDDB,使其可用作通用的网络目录服务。我也需要为其取一个新的名字。

结论

使用常规 UNIX 工具和 SDDB,我们创建了一个分布式机器,以物理上分离的服务器的形式遍布世界各地,具有多重功能。这样做没有任何神奇之处。它仅仅是通过以面向未来的通用方式解决问题来实现的。Linux 已被证明完全有能力在这个大型“关键任务”环境中独当一面。没有什么可以阻止多台 Linux 服务器提供“大型系统”的功能和可管理性。

有关更多信息或下载本文讨论的代码的源代码,请访问 http://www.tpp.org/CiscoPrint/。

Linux Print System at Cisco Systems, Inc.
Damian Ivereigh 担任 Unix 系统管理员和工程师已有 12 年。他最初是英国人,但在美国居住了 4 年,其中过去 3 年在思科工作。他的业余爱好是洞穴探险和激流皮划艇。欢迎您通过 damian@cisco.com 提出意见。
加载 Disqus 评论