We're using LPRng 3.7.4 on many Solaris 2.6 boxen, with ifhp 3.4.4 (if
that matters).
Problem the first: lprm seems to not remove the jobs properly: it
leaves around various hf files. But only on occasion; not always. I
haven't discovered the situation under which the hf files remain, but
it makes the queue (from the view of lpq) seem deceptively full, and
an lpc flush doesn't correct the problem. lprm -P<offendingqueue> all
corrects the problem, but that's clearly not the best solution.
The second problem (and the major one): We have several clusters, each
with two printers, one of which is nearly invariably broken or offline
or something. We're using a loadshare queue (for example, hudsonlp)
to service both the printers (hudsonlp1 and hudsonlp2. Original, I
know). The problem with the standard loadshare chooser is that it
doesn't care whether a printer is responding on the network or not,
and so will place the jobs in the queue no matter what happens,
thereby filling up the queue. The printers are checked once a day for
problems, but with the amount and size of the things our users print,
the queue would fill up quickly.
The solution I devised was to write a chooser that connects on the
network port of each printer passed in via stdin and selects based on
that. The chooser notifies us if *no* printers are available, and
then removes the job from the queue (but only sometimes not
completely; see above). The chooser script itself is attached.
The problem, then, is that LPRng seems to not pass any printer that's
currently printing a job to the chooser routine as a valid printer,
when, in fact, it is. And when one printer in the cluster is down,
and the other is handling all the jobs, we end up with lots of bogus
notices about the printers being down. I think this is buggy behavior
by LPRng; perhaps I'm making some incorrect assumptions about the
behavior of the loadshare queue aspect of LPRng.
Any suggestions?
KH
Below are the printcap entries for one of the groups of printers on the
server:
---
# hudson printers
hudsonlp:server:tc=.general,.spool,.chooser:sv=hudsonlp1,hudsonlp2
hudsonlp1:server:tc=.general,.spool,.xerox_n32-acpub:ss=hudsonlp
hudsonlp2:server:tc=.general,.spool,.xerox_n32-acpub:ss=hudsonlp
# generic stuff
.general
:lpd_bounce
:mx=0
:mc=0
# set up default spool dir
.spool
:sd=/var/spool/lp/%P
.filter
:filter=/usr/pkg/ifhp/sun4x_56/libexec/filters/ifhp
.chooser
:chooser=/afs/acpub/share/etc/lpd.chooser
# Xerox DocuPrint N32
.xerox_n32-acpub
:rm=%P.acpub.duke.edu
:tc=.xerox_n32
.xerox_n32
:tc=.filter
:ifhp=model=postscript
---
And on the client:
---
# hudson printers
hudsonlp|hudsonlp1|hudsonlp2:client:tc=.general,.remote
# generic stuff
.general
:force_localhost@
:mx=0
:mc=0
# set up default remote printer
.remote
:[EMAIL PROTECTED]
---
The lpd.conf is as distributed (ie, with everything commented out).
#!/usr/local/bin/perl
# chooses a printer based on whether they're up or not...
# $Id: lpd.chooser,v 1.19 2001/02/26 21:05:19 kph Exp $
use IO::Socket;
use POSIX;
$SERVICE = "printer";
$PROTOCOL = "tcp";
$TIMEOUT = 15;
$DOMAIN = "acpub.duke.edu";
$maintainer = "kph\@oit.duke.edu";
$disable_command = "/usr/pkg/LPRng/sun4x_56/sbin/lpc disable ";
$remove_command = "/usr/pkg/LPRng/sun4x_56/bin/lprm -P";
# get list of printers.
@printers = <STDIN>;
chomp(@printers);
# parse args for job
foreach $arg (@ARGV) {
if ($arg =~ /^-j(\d+)$/) {
$job = $2;
}
}
# parse the printcap entries for the available printers
foreach $printer (@printers) {
# split the environment variable into foo=bar or baz or bam@.
@tmp = split(/\s+/, $ENV{$printer});
foreach $line (@tmp) {
# split each foo=bar into $keyword and $value pairs.
($keyword, $value) = split(/=/, $line);
# if not of the form foo=bar, then if bam@, $value = 0, else
# $value = 1.
if ($value eq "") {
if ($keyword =~ s/\@$//) {
$value = 0;
} else {
$value = 1;
}
}
# set the appropriate value in the appropriate place.
$printcap->{$printer}{$keyword} = $value;
}
}
# check on the status of each printer. connectable, number of jobs in queue.
foreach $printer (@printers) {
(undef, undef, $remoteport, $remoteproto) =
getservbyname($SERVICE, $PROTOCOL);
$remotehost = $printer . "." . $DOMAIN;
$connected = 0;
$socket = IO::Socket::INET->new(PeerAddr => $remotehost,
PeerPort => $remoteport,
Proto => $remoteproto,
Timeout => $TIMEOUT,
Type => SOCK_STREAM)
and $connectable_printers{$printer} = -1, $connected = 1;
# get rid of $socket if it's around.
if ($socket) {
undef $socket;
}
# more important is the connectable status; if we can't connect,
# don't bother checking the queue size. otherwise, get the spooldir
# and check the number of files in it. who cares about
# the printer if it has no spool dir?
if ($connected == 1) {
if ($printcap->{$printer}{"spooldir"} ne ""
and opendir(SPOOL, $printcap->{$printer}{"spooldir"})
and @entries = readdir(SPOOL)
and closedir(SPOOL))
{
$connectable_printers{$printer} = scalar(@entries);
} else {
$connectable_printers{$printer} = -1;
}
}
}
# now, find the connectable printer with the minimum number of jobs.
@ideal_printers = ();
$minjobs = -1;
foreach $con_pr (sort(keys(%connectable_printers))) {
# -1 means it didn't have a spool dir.
next if ($connectable_printers{$con_pr} == -1);
if ($minjobs == -1 or
$connectable_printers{$con_pr} < $minjobs) {
$minjobs = $connectable_printers{$con_pr};
@ideal_printers = ($con_pr);
} elsif ($connectable_printers{$con_pr} == $minjobs) {
push(@ideal_printers, $con_pr);
}
}
if (scalar(@ideal_printers) < 1) {
# ERROR!
open(NOTIFY, "|/usr/local/bin/zwrite -q -d -c lp");
print(NOTIFY "No printers found for $ENV{'PRINTER'}!\n");
# print(ZGRAM "\nARGS:\n");
# foreach $arg (@ARGV) {
# print(ZGRAM "$arg\n");
# }
# print(ZGRAM "\nENV:\n");
# foreach $var (sort(keys(%ENV))) {
# print(ZGRAM "$var => $ENV{$var}\n");
# }
# print(ZGRAM "\nprinters:\n");
# foreach $printer (@printers) {
# print(ZGRAM "$printer\n");
# }
print(NOTIFY "\nPlease disable or fix the printers.\n");
print(NOTIFY "The command to disable is $disable_command $ENV{'PRINTER'}.\n");
# $retval = system($remove_command . $ENV{'PRINTER'} . " $job");
if ($retval == 0) {
print(NOTIFY "\nSuccessfully removed offending job.\n");
} else {
print(NOTIFY "\nRemoval of offending job failed! There will be a zombie
job.\n");
}
print(NOTIFY "\nHave a nice day!\n\nYour friend,\nLPRng");
close(NOTIFY);
# system($disable_command . $ENV{"PRINTER"});
exit(1);
}
if (scalar(@ideal_printers) == 1) {
print("$ideal_printers[0]\n");
} else {
srand(time() + $$);
$random = int(rand(@ideal_printers));
print("$ideal_printers[$random]\n");
}
exit(0);
--
Karsten Huneycutt A casual stroll through a lunatic
[EMAIL PROTECTED] asylum shows that faith does not
http://www.duke.edu/~kph prove anything --Nietzsche
--
Karsten Huneycutt A casual stroll through a lunatic
[EMAIL PROTECTED] asylum shows that faith does not
http://www.duke.edu/~kph prove anything --Nietzsche