我有一台 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 是当今事实上的打印标准。搜索开放打印获取有关处理您的特定野兽的建议。
你可能幸运的话,可以获取相关客户端和服务器的源代码,并让它们运行。可能不值得,但是嘿,这是你的时间了。
请务必在此处添加您成功(或失败)的经验作为答案。