如何在本地不安装 CUPS 服务器的情况下打印到远程 LPD 打印服务器

如何在本地不安装 CUPS 服务器的情况下打印到远程 LPD 打印服务器

我有一台 Linux (Fedora 22) 机器和两台热敏打印机,每台都连接有 Digitus 打印服务器。全部都在同一个 LAN 上。每台 Digitus 打印服务器都运行 LPD 守护进程,并且每台都配置为仅提供一个队列: lpd://192.168.1.2/queue以及lpd://192.168.1.3/queue

我只是希望能够仅使用 LPR 客户端(没有完整的 CUPS 安装)将文件从 Fedora lpr 到 LPD 服务器。我尝试了cups-client(dnf install cups-client),它安装了lpr二进制​​文件,并将远程打印服务器添加到我的/etc/printcap中,但是Bad file descriptor每当我运行lpr时都会出现错误。

有任何想法吗?

答案1

我找到了一个非常好的解决方案:rlpr。 (这里是任何感兴趣的人的链接。向下滚动到 rlpr 页面底部,尽管所有条目都是旧的宝石)

rlpr 正是我所需要的:它直接与远程 LPD 守护进程对话 LPR 协议,甚至无需在本地声明远程打印机(例如 /etc/printcap):

rlpr --printer=queue@remotehost file_to_print

我下载了 tar.gz、配置、制作并使用了二进制文件(我什至没有安装)。

答案2

使用像 rlpr 这样的仅限客户端的功能时要记住的一件事是,如果它是非交互式批处理过程或类似的生成打印请求的过程,并且客户端系统和打印机/假脱机程序之间存在网络中断,则最多会列出将会丢失,最坏的情况是批处理作业会失败。

这是本地守护程序功能(如 CUPS/LPRng/classic LPD)的原因之一,其中 lpr 客户端实际上与侦听 127.0.0.1:515 或 :631 的本地守护程序通信,并通过该守护程序代理请求:守护程序提供存储转发。

任何网络中断或故障都不可能破坏该过程。客户端成功提交打印请求,该本地守护进程接受该请求,然后 lpd/whatever 守护进程继续尝试将列表转发到其最终目的地,直到成功为止。列表不会丢失,同时批处理作业/任何内容都会成功继续。

而使用 rlpr 时,如果网络出现故障,那么您就不走运了。

如果您使用 lpr.cups 客户端,但使用 -H 将其直接指向远程打印后台处理程序/打印机,这也是一个问题。失败是不可恢复的。

这不是交互式使用的问题,而是自动化流程中需要记住的问题。

答案3

RFC 1179否则编写客户端并不难,大部分工作是错误检查和正确设置输入格式。

#!/usr/bin/perl
# Lobs PostScript at a LPD printer (see RFC 1179). Poorly. Use at own risk,
use strict;
use warnings;
use IO::Socket::INET;
use Sys::Hostname qw(hostname);

my $printer_addr = shift or die "Usage: $0 host [file.ps|-]\n";
my $file         = shift;

my $queue       = "queue";               # may not be needed?
my $client_host = substr hostname(), 0, 31;
my $user        = substr $ENV{USER}, 0, 31;
my $jobnum      = sprintf "%03d", rand 1000;

my $sock = IO::Socket::INET->new(
# if server mandates this, client will need to be run as root,
# or Linux capabilities delved into
#   LocalPort => 721,                    # RFC 1179 sec 3.1
    PeerAddr  => $printer_addr,
    PeerPort  => 515,
    Proto     => 'tcp',
    ReuseAddr => 1,
) or die "$0: could not connect to $printer_addr: $@\n";

# o - Postscript
# f - ASCII
# l - ASCII, leaving control chars
my $control_file = <<"END_CONTROL_FILE";
H$client_host
P$user
odfA$jobnum$client_host
UdfA$jobnum$client_host
END_CONTROL_FILE
my $control_file_size = length $control_file;

my ($data_file_size, $fh);
if (defined $file and $file ne '-') {
    open $fh, '<', $file or die "$0: could not open '$file': $!\n";
    $data_file_size = -s $file;
} else {
    $fh = \*STDIN;
    $data_file_size = 0;
}

sendcmd(sprintf "%c%s\n",    0x02, $queue);

sendcmd(sprintf "%c%u %s\n", 0x02, $control_file_size, "cfA$jobnum$client_host");
$control_file .= "\0";                   # must pad message 
sendcmd($control_file);

sendcmd(sprintf "%c%u %s\n", 0x03, $data_file_size, "dfA$jobnum$client_host");

binmode $fh;
my $buf;
while (1) {
    my $buflen = sysread $fh, $buf, 4096;
    die "sysread() failed: $!\n" if !defined $buflen;
    last if $buflen == 0;                # EOF
    syswrite $sock, $buf, $buflen;
}
syswrite $sock, 0x00, 1 if $data_file_size == 0;

# meh, blocks program when input from STDIN
#my $resp;
#sysread $sock, $resp, 1;
#
#syswrite $sock, 0x00, 1;

sub sendcmd {
    my $cmd = shift;
    my $response;
    syswrite $sock, $cmd, length $cmd;
    sysread $sock, $response, 1;
    chomp $cmd;
    die "$0: unexpected lack of response to '$cmd'\n"
      if !defined $response;
    die sprintf "$0: not-zero response to '$cmd': %vx\n", $response
      if $response ne "\0";
}

答案4

Fedora 使用 CUPS 作为打印服务器,处理本地和远程打印机。据我所知,没有本地软件包可以使用(遗留的、已弃用的)LP 或 LPR 协议,而且已经有一段时间了。 CUPS 是当今事实上的打印标准。搜索开放打印获取有关处理您的特定野兽的建议。

可能幸运的话,可以获取相关客户端和服务器的源代码,并让它们运行。可能不值得,但是嘿,这是你的时间了。

请务必在此处添加您成功(或失败)的经验作为答案。

相关内容