Advertisement: Support SunWorld, click here!
|
|
|
|
Set up a print server with Solaris
Find out how to print multiple content types with lpadmin -- a proven methodology
Summary
Setting up a print server that handles multiple content types may not
seem like a difficult task -- and it isn't, as long as third-party software figures
into the equation. The difficulties arise when you decide to go
strictly with lpadmin. Unix sysadmins Errol Fouquet and Robert Krumm
guide you through this process with a proven methodology for setting up
a print server that can successfully handle plain text, PostScript, and
printable binary (pcl, rtl) content types. (2,900 words)
By Errol Fouquet and Robert Krumm
s
Unix system administrators contracted out by our employer, one of
the many services we provide to our customers is printing and plotting
support. One particular customer has a fairly complex printing
environment, which includes 8 36-inch HP plotters, 1 24-inch HP
plotter, approximately 20 HP DeskJet 1600c plotters, and approximately
20 HP 3si/4si/5si printers. All the devices run LPD, have PostScript
drivers, and are accessed as network printers using TCP/IP. Printer
network cards are evenly divided between HP JetDirect and XCD XJet
cards.
We run Zeh Graphic Systems's ZPS plotting software on a Sun Ultra
Enterprise 450 supporting several applications that output many graphic
formats. We also support LPD from a few other applications, and user
printing from Netscape, as well as user printing at the command line.
The print clients in our environment are mostly Sun servers and
workstations numbering close to 200. We also have one Windows NT server running
Citrix Winframe, which is also a print client.
Apart from applications, which plot through Zeh, and, therefore, use
our Ultra 450 as a spooler, all other print requests are transmitted
from the client directly to the network printer. Functionally, this
works fine, printing all the content types we need, including text,
PostScript, and printable binary (pcl and rtl). The problem is that the
setup is an administration nightmare. Often, a huge, unacceptable
binary file, like a GIF or JPEG, would be printing out reams of garbage,
and we would have no easily available method of determining the source
of the request. We would know only that a workstation or server
somewhere in the building was sending a bad job to the printer.
Unfortunately, banner pages weren't an option, as the user community
didn't want to waste paper (ironic, huh?).
We did manage to write a shell script that would rsh over to all the
machines in the building and report the activity to a given printer.
With this information we could execute the Cancel command. But this was
horribly slow and inefficient.
The customer's own technical-computing strategy indicated that the
solution was to implement a print server for the Unix environment, but
it failed to offer details for this configuration. In addition, a recent
NOMAN (network operations management) assessment, conducted by Sprint
Paranet, also identified implementing a print server to meet the
customer's printing needs.
We knew that a print server was the right solution, and if we could
just set it up, all print requests could be managed from a single
machine, greatly simplifying the entire process. As it turned out this
wound up being much more difficult than we anticipated.
Attempt 1: Trial and error
Initially, we wanted to set up standard Solaris print spooling. We
designated a test machine, called nolsn099 (an Ultra-1 running Solaris
2.6), as the test print server, and we began several tests. The printer
we began testing with was an HP 1600c, called no1316p in our NIS/DNS
environment.
After each server setup, the client machine (an Ultra-1 running Solaris
2.5.1) was set up to access the printer/plotter with the command
lpadmin -p no1316p -s nolsn099!no1316p
| Server setup 1 |
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS \
-I PostScript -v /dev/null -i /usr/lib/lp/model/netstandard |
| Result: Client machine was able to print PostScript and binary (pcl, rtl) files fine, but text files would staircase. |
| Server setup 2 |
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown \
-I any -v /dev/null -i /usr/lib/lp/model/netstandard |
| Result: Client machine was able to print text files fine, but PostScript, rtl, and pcl files printed garbage. |
| Server setup 3 |
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS -I text \
-v /dev/null -i /usr/lib/lp/model/netstandard
|
| Result: Client machine was able to print text and PostScript files fine, but rtl and pcl files printed garbage. |
| Server setup 4 |
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown \
-I PostScript,text,simple -v /dev/null \
-i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown \
-I any,PostScript,simple -v /dev/null \
-i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS \
-I any -v /dev/null -i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T unknown \
-I text,simple -v /dev/null
-i /usr/lib/lp/model/netstandard
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T hplaser \
-I text,simple -v /dev/null
-i /usr/lib/lp/model/netstandard
|
| Result: All of these resulted in client being able to print PostScript, pcl, and rtl, but the text files would staircase. |
| Server setup 5 |
lpadmin -p no1316p -o protocol=bsd,dest=no1316p -T PS \
-I any -v /dev/null -i /usr/lib/lp/model/netstandard
|
| Result: This allowed for PostScript and text files to be printed fine, but this printed garbage for pcl and rtl files. |
As you can see, we tried several combinations, but were unsuccessful in
printing all three desired formats. The man page for lpadmin suggests
that you also can have a list for the -T option. We decided that what
we really needed was a -T unknown,PS option, but
unfortunately, lpadmin doesn't allow "unknown" to be coupled with any
other terminfo type.
We concluded that with the standard options available to Solaris lpadmin, we would only be able to set up a printer to handle:
- Text only
- Text and PostScript
- PostScript and printable binary (pcl and rtl)
Our next step was to log a call with Sun's software support. We were
fortunate to get a very helpful support person on the phone, who gave
us what seemed to be a solution. Although he admitted that it was
something of a hack, he was sure that it would work. The solution
involved setting up two queues for each printer on the print
server and then employing double spooling. The first device would
function as a filter and then pipe its output to the network printer.
(We decided to adopt a convention of creating a printername and a
printername-r for each device we configured, so we have a no1316p and a
no1316p-r.)
Here are the steps:
Step 1. On the server, set up the filter device
$ lpadmin -p no1316p -v /dev/null -i /usr/lib/lp/model/standard
$ enable no1316p
$ accept no1316p
Step 2. Edit the newly created interface script (/etc/lp/interfaces/no1316p)
Look for the case statement that starts case $TERM
in
For the * ) condition, comment out the line
that refers to FILTER=${LPCAT}
Insert the line FILTER=/bin/unix2dos | lp -s -d no1316p-r
Step 3. Set up the network printer (no1316p-r)
$ lpadmin -p no1316p-r -o protocol=bsd,dest=no1316p -v /dev/null \
-i /usr/lib/lp/model/netstandard
$ enable no1316p-r
$ accept no1316p-r
Note: Without specifying the -T or -I options, the defaults
"unknown" and "any" are used.
When we first set this up, it seemed like a winner. The dos2unix
command fixed the staircasing of text files, and we were able to print
PostScript, pcl, and rtl files. We were almost ready to celebrate when
we noticed that the quality of the pcl and rtl files was extremely
poor. The dos2unix command was corrupting the binary format!
We got back on the phone with Sun. This time we set up a conference
call with several Sun engineers to report our needs and findings. They
suggested using an lpadmin command (one we'd already tried) to set up
the printer. When we told them how this caused the text files to
staircase, two of the engineers groaned knowingly. They promised to
investigate. In the meantime, we resumed our own quest to find a
solution.
Attempt 2: Red tape
Next, we tried using Hewlett-Packard's JetAdmin software, Sun's recommended
solution for network printing to HPs. We set up a test machine to use as a print
server, then set up the JetAdmin software. It worked great. We were
able to print all three file types without error. We were able to set up
clients to spool through this server fine, and the software gave us the
information we needed to manage unwanted jobs. We had found our
solution! Wrong. We were told that replacing the XCD cards was not an
option.
We still hadn't heard back from Sun, so we chose to revisit the
"double spooling" solution.
Attempt 3: Double spooling revisited
We decided that double spooling had brought us too close to abandon it
completely. Only the limitations of unix2dos stood in the way of
success. If we could examine the input file and execute only the
unix2dos on nonbinary files, we would have our solution. We wrote a
simple Perl script (unix2dos.pl) to do just that:
#!/opt/bin/perl
# open standard input
open(FOO, "-");
# test if binary
if ( -B FOO) {
while (<FOO>) {
print $_;
}
}
# if not binary.. perform unix2dos filtering
else {
while (<FOO>) {
s/\n/\r\n/; print;
}
}
close(FOO);
We then replaced the line in the interface file as follows:
FILTER=/opt/utils/unix2dos.pl | lp -s -d no1316p-r
That clinched it. We were able to print all three formats without any
problems. Or at least that's what we thought. Unfortunately, because of
the double spooling, the print jobs in the no1316p-r queue no longer
had meaningful names or owners. For example, when a client printed a
file, like /etc/passwd, and we executed lpq -Pno1316p on
the print server, we would see something like this:
$ lpq -Pno1316p
Rank Owner Job File(s) Total Size
active dlister 313 /etc/passwd 522 bytes
But after no1316p filtered the job and piped it to lp -s -dno1316p-r,
and we executed lpq -Pno1316p-r on the
server, we'd see something like this:
$ lpq -Pno1316p-r
Rank Owner Job File(s) Total Size
active lp 1629 1629-1 536 bytes
Without properly designated filenames and owners, users couldn't track
their files in the print queue, and we couldn't delete jobs from the
queue upon request.
So we contacted Sun support again. We sent a detailed e-mail to our
account rep, copying the two engineers from the conference call, and
explaining the progress we had made and how this new obstacle was
posing a real problem to print management. The response we got in
return was a bit discouraging, to say the least: "This mail describes
one of the many reasons that we don't recommend or support double
spooling and/or requeueing jobs."
We were on our own.
Attempt 4: Finding a compromise
Because we were successful in spooling all three file types, the last
thing we needed was meaningful lpq info for our network printer queue.
We knew that when the print job was queued through the filtering queue
(no1316p, for instance), the original filename and user name was
available. We had to figure out a way of preserving this information
and associating it with the job queued on the actual network printer
queue (no1316p-r, for instance).
We knew that when a job was sent through the filtering queue, the lp
subsystem would return the information we were interested in. So it
stood to reason that we should be able to harness this info from
environment variables. As it turns out, the variable we were
interested in can be harnessed in the interface script of the filtering
queue: ${request_id},
${user_name},${files}, and
${flist}. But we still faced the problem of associating
this information with the lpq of the actual network printer queue.
What we needed was a means of logging the requests coming into the
filtering queue, and a method of mapping entries in the network printer
queue back to the original information.
The strategy we eventually adopted filtered the input to a temporary
file, which had the original ${request_id} in the name.
We then piped to an lp of this temporary file. The lpq info of the
network printer queue now included the original
${request_id} in the form of the filename. That left only
the log file. We further modified the interface script of the
filtering queue to include the following logic immediately before the
if [ -z "${FILTER}" ]:
# write current request_id user_name and flist to logfile
# if the flist variable is null, we are printing a single file,
# therefore echo ${files}
# else echo ${flist}
if [ "$flist" = "" ];
then
echo "${request_id} ${user_name} ${files}" \
$gt; $gt; /var/spool/lp/save_dir/logs/request.log
else
echo "${request_id} ${user_name} ${flist}" \
$gt; $gt; /var/spool/lp/save_dir/logs/request.log
fi
We incorporated the creation of the temporary file into the unix2dos.pl
script shown earlier. The new script is called lp.pl:
#!/opt/bin/perl
# open standard input
open(FOO, "-");
# create temp file for writing
open(OUT, ">/var/spool/lp/save_dir/tmp/$ARGV[0].$$");
# if input stream is binary do not filter
if ( -B FOO) {
while () {
print OUT $_;
}
}
# else filter the line unix2dos style
else {
while () {
s/\n/\r\n/; print OUT;
}
}
close(FOO);
close(OUT);
# send print request
system("/bin/lp -s -d $ARGV[1] /var/spool/lp/save_dir/tmp/$ARGV[0].$$");
Next, we passed lp.pl two arguments: ${request_id}, and
network printer. The script then created a filtered
temporary file named ${request_id}."pid of process" and
executed an lp of this temporary file.
Then, we replaced the line in the interface script of filtering queue that read
FILTER=/opt/utils/unix2dos.pl | lp -s -d no1316p-r
with
FILTER="/var/spool/lp/save_dir/sbin/lp.pl ${request_id} no1316p-r"
Let's take a break and summarize what's happening up to this point:
- An lp job is sent from a client machine by a user (dlister):
lp -d no1316p /var/adm/messages
- The job is received by the print server, which processes the
request through the filtering queue
- The filtering queue logs the current job number (${request_id}),
user (dlister), and the filename (/var/adm/messages)
- The input is sent to the lp.pl script, which creates the temporary
file and then executes an lp using the network printer queue
At this point, if we perform an lpq on the network printer, the output
will look something like this:
$ lpq -Pno1316p-r
Rank Owner Job File(s) Total Size
active lp 1629 /var/spool/lp/save_dir/tmp/no1316p-1625.2974 536 bytes
Now, all we need is a script that will index into our log file, find
no1316p-1625, and return the original owner and filename. To serve this
need we wrote lpq.ksh:
#!/bin/ksh
typeset -i N
typeset -i N2
# set N2 equal to the default number of fields per log file entry
N2=3
if [ $# -ne 1 ]
then
echo "usage: $0 network_printer_queue"
exit 1
fi
echo "Rank Owner Job File(s) Total Size"
/usr/ucb/lpq -P $1 | grep bytes | while read line
do
RANK=`echo $line | awk '{print $1}'`
JOB=`echo $line | awk '{print $3}'`
SIZE=`echo $line | awk '{print $5}'`
TEMP=`echo $line | awk '{print $4}'`
GREPSTUFF=`basename $TEMP | awk -F. '{print $1}'`
OWNER=`grep -w $GREPSTUFF /var/spool/lp/save_dir/logs/request.log \
| awk '{print $2}'`
# count the number of fields in the log file: 3 means a single file
# printed more than
# 3 means that several files were sent at once.
N=`grep -w $GREPSTUFF /var/spool/lp/save_dir/logs/request.log \
| awk '{print NF}'`
if [ $N -gt 3 ]; then
FILE=`grep -w $GREPSTUFF /var/spool/lp/save_dir/logs/request.log \
| awk "{print \\$$N2}"`
echo "$RANK $OWNER $JOB $FILE $SIZE bytes"
N2=N2+1;
else
N2=3
FILE=`grep -w $GREPSTUFF /var/spool/lp/save_dir/logs/request.log \
| awk '{print $3}'`
echo "$RANK $OWNER $JOB $FILE $SIZE bytes"
fi
done
This script takes a single argument: the name of the network printer
queue. In our scenario, we simply enter $ lpq.ksh no1316p-r to display
the following output:
Rank Owner Job File(s) Total Size
active dlister 1629 /var/adm/messages 536 bytes
Using this script, we were able to give our end users the information
they needed to track their print jobs, and the printing support staff
could better manage jobs on the print server.
Cleanup
Finally, we needed some means of deleting the temporary files we were
creating in /var/spool/lp/save_dir/tmp. I noticed that once a job
had successfully completed through the lp subsystem, an
entry, in the form of T filename, appeared in the file /var/spool/lp/logs/requests.
To clean up these temp files up we wrote a script called cleanup.ksh:
#!/bin/ksh
cd /var/spool/lp/save_dir/tmp
unalias ls
# our temp files are all begin with "no"
if [ -f no* ];
then
for i in `ls no*`
do
grep "^T $i" /var/spool/lp/logs/requests > /dev/null 2>&1
if [ $? -eq 0 ];
then
rm -f $i
fi
done
fi
We set up a cron job on the print server to run this script once every hour.
Conclusion
While we admit that this solution could use further refinement, we
accomplished what we set out to do:
- We are spooling through a central server
- All three content types (text, PostScript, pcl/rtl) are handled without error, using a single printer name
- We are able to track the print request through the entire process
- We are able to produce meaningful lpq information
- We have centralized and simplified our printing environment
- We have accomplished our goals without any added expense
In addition, we believe that the modifications described in this
article could be incorporated into the printing subsystem of Solaris
2.6, eliminating the need for third-party software and hardware solutions.
Sun would simply need to add a native filter for the lp subsystem,
which provides the logic of our handy unix2dos Perl script, to
eliminate the double spooling (officially unsupported by Sun) we are
doing now.
Also this month in SunWorld
Features:
- How to prepare your IT staff for mainframe to Unix migration
- Set up a print/plot server with Solaris
- Emergence of the 'unoperating' system
- Who's backing me up?
News & Views:
- Serious FTP
- Explosions in the Valley
- Scripting with C
- Career advice from the experts
- Expanding your server-side toolkit
- Letters to the Editor
- New Product Briefs (April 1, 1999)
- The Internet Files: News on Internet standards and struggles
- Sunspots: Sun deals and product news
- IDC: Linux to outpace all contenders through 2003
- Sun, AOL outline alliance plans
- Up-to-the-minute news on Sun's rivals
- Linux not ready for the bug leagues?
- If Tru64 doesn't move them, maybe Linux will
- Java driven by the cutting edge
- New Product Briefs (April 9, 1999)
- The wait is on for IA-64
- Interview: "Java and Jini will be in everything"
- SuSE set to release updated Linux version
- Hewlett-Packard and Microsoft team on instant networking
- New Product Briefs (April 15, 1999)
- COMDEX: Ignore the Linux hype, Torvalds urges
- New Product Briefs (April 23, 1999)
- NT looking great on paper
- Sun, HP challenged in Japan's server market
- IDC: European IT services market to top $129 Billion by 2003
Tech Expertise:
- Setting up Sendmail on a firewall
- A primer on signals, Part 1
- Building a reliable NT server, Part 4
- Using bc, Part 1
- The power of /proc
- Monitor your Web server
Advertisement: Support SunWorld, click here!
|
![]() |
Resources and Related Links |
| |
Additional SunWorld articles on printing in Unix Additional SunWorld resources
| |
![]() |
Tell Us What You Thought of This Story
|
| |
-Very worth reading
-Worth reading
-Not worth reading
|
-Too long
-Just right
-Too short
|
-Too technical
-Just right
-Not technical enough
|
|
Comments:
|
|
|
Name:
|
|
|
Email:
|
|
|
Company Name:
|
|
| |
If you have technical problems with this magazine, contact
webmaster@xxxxxxxxxxxx
URL: http://www.sunworld.com/swol-04-1999/swol-04-printserver.html
Last modified: Thursday, March 30, 2000
|