Taming the Horrors of Printers and Printing, Part 2
Whoa! I'm speechless. Judging from the response I received on the last article in this series, printing is very much the evil beast that I made it out to be last week. Thanks, everyone, for the feedback.
This time around, I'd like to continue down the nuts-and-bolts track of printer administration. I know I promised fancy, cool GUI tools to do some of these things, and I promise we'll get there--eventually. For now, I'd like to spend just a bit more time on how all this stuff works under the surface.
In a moment, I'm going to jump head first into your Linux tools for control of print jobs, queues, etc. Before doing that, I'd like to follow up on something from the last article: setting up remote print queues. Specifically, setting up a print queue to an HP JetDirect adapter.
An increasingly common feature of IT shops these days is the Hewlett-Packard JetDirect printer adapter. The Windows and Novell connectivity gets hyped, but rest easy, true believers--getting a Linux system to print to one of those neat little boxes is no big deal. Last week, I gave you the following example. It was a printer locally referred to as "faraway" to access a remote queue called "lptest". For a refresher, here's what it looked like.
faraway: :sd=/var/spool/lpd/faraway: :mx#0: :sh: :rm=farlinux: :rp=lptest:
If you are using an HP JetDirect adapter, I'll assume you have configured either the printer or the stand-alone server with an IP address. This can be done with the included JetAdmin software (for a stand-alone server) or from the control panel in the case of printers that have JetDirect cards built in.
The next thing to do is define the print queue. Let's say my adapter had an IP address of 192.168.1.225 and a host name of "hpjd1". To create a queue on my Linux system, I would use this printcap entry:
jdqueue1: :sd=/var/spool/lpd/jdqueue1: :mx#0: :sh: :rm=hpjd1: :rp=text:
For text-only printing, this is all there is to it. Notice the remote printer name is "text". JetDirect cards and adapters have two recognized printer names; the other is "raw". If your output is always PCL or Postscript, then you should use "raw" as the remote printer name.
Now, say you had one of those new, super-cool, 3-port HP JetDirect adapters; what then? Glad you asked. These cards recognize six different printer names. They are "text1", "text2" and "text3". For raw, or postscript output, try "raw1", "raw2" and (you guessed it) "raw3".
All right; so now you can set up local and remote printers, and send jobs to them. Now we'll look at what you can do to take control and affect those jobs.
The master control program for printers is lpc, a small, interactive command-line program. In its simplest form, you type this:
The system replies with a quiet little prompt:
If I type status here, I will get the status (strangely enough) of all printers configured on that machine. Here's what the output looks like on my system:
lpc> status lp: queuing is disabled printing is disabled no entries no daemon present colour: queuing is enabled printing is enabled no entries no daemon present lptest: queuing is enabled printing is enabled no entries no daemon present
Now, for reasons I don't want to go into, my main printer "lp" is having problems, and I don't want the system to continue trying to print to it while I am trying to fix it. At the lpc> prompt, I type the following. The format is as follows.
down lp "You should not have bothered with this printer."
What this will do is take down the printer and stop jobs from getting to it. Notice the message that follows down lp. This will print a message to anyone who queries the status of the print queue from their computer (I am assuming a remote user here, but they could be local as well). So, not knowing what my system administrator has done, I still send a job to the printer. I then decide to see where in the queue my job sits, so I use lpq to find out. As you might have guessed, lpq reports on the status of queued jobs. You invoke it like this:
# lpq -Pprinter_name
Remember, also, that if you specify a PRINTER environment variable (as I mentioned last week), you don't have to specify the printer. In other words, PRINTER=lptest ; export PRINTER means you can just type lpq. Here's what happens when I check the status of my job after my system administrator (okay, it's really me) downs the printer:
mycomputer.salmar.com: waiting for queue to be enabled on scigate Rank Owner Job Files Total Size 1st root 16 /etc/profile 546 bytes Warning: lp is down: "You should not have bothered with this printer" Warning: lp queue is turned off no entries
Well, dang! I suppose I'll have to use another printer. I could also remove the job from the queue. You do this with the lprm command. To get rid of this job, I would type the following:
# lprm -Plptest 16
I didn't really want that job, anyway.
Let's talk a little bit more about filters. In my office, I have a small HP LaserJet 5L. It's the one I've been using for all these examples. If you've spent any time whatsoever with Linux (or other Unices/Unixes), you know that most applications print using the postscript format. Unfortunately, my printer doesn't print postscript. Luckily, I do happen to have a little package called ghostscript on my system.
I won't spend a long time (not today, anyway) talking about ghostscript, except to tell you it is a powerful tool, and one that makes a great print filter to boot. If I try to print a postscript file to my printer, it comes out as strange text, which just happens to be a kind of code--code written in the Postscript language. Looking at the first 10 lines of a postscript file on my system, I see this:
# head contact.ps %!PS-Adobe-PS %%BoundingBox: 54 72 558 720 %%Creator: Mozilla (NetScape) HTML->PS %%DocumentData: Clean7Bit %%Orientation: Portrait %%Pages: 1 %%PageOrder: Ascend %%Title: Registrant Name Change Agreement %%EndComments %%BeginProlog
This is also what it looks like if I just send it to my printer without a filter of some kind that can interpret postscript. Different Linux distributions offer different alternative filters, but all should have ghostscript in common.
Here's an example. I'll send my contact.ps file to the printer, but pass it through a ghostscript filter beforehand.
# cat contactm.ps | gs -q -dNOPAUSE -sDEVICE=ljet4 -r300 -sPAPERSIZE=letter -sOutputFile=- - | lpr
The -q means that ghostscript should perform its work quietly. Normally, ghostscript would put out a lot of "this is what I am currently doing" information, not what we want for a print job. The -dNOPAUSE> tells ghostscript to process all pages without pausing to ask for directions. The first -s flag you see specifies the printer type. The ljet4 definition covers a whole range of LaserJet printers that can do 600 dpi resolution. This brings us to the -r flag, where I define a 300 dpi resolution. This Netscape-generated page (remember, you can print to a file when using Netscape) doesn't need a 600 dpi resolution. Ghostscript also allows me to specify paper size, important for those of us in North America who hold firmly (if not wisely) to the 8-1/2 by 11-inch letter size format. Finally, I specify standard out as my output file. Notice the last hyphen in that line. It means that ghostscript is taking the input through its standard in. The last thing I do is fire it to the printer.
The great thing about ghostscript is its extensive printer support. Check out the Ghostscript printer support page if you want to see the latest and greatest list of support.
Scroll down the list, and click on "printer compatibility".
Armed with this, I could use essentially the same line to create a filter for printing. Always keep in mind that the filter lives on the local printcap definition, not the remote. Remember my dosfilter from last week? Here's a refresher:
#!/bin/bash echo -ne \\033&k2G cat echo -ne \\f
There was only one real active line in (other than the staircase effect change), and that was a simple cat. That line would be the ghostscript line from above, minus the | lpr at the end of it.
#!/bin/bash gs -q -dNOPAUSE -sDEVICE=ljet4 -r300 -sPAPERSIZE=letter -sOutputFile=- - echo -ne \\f
Very cool and very powerful. As an added bonus, you can even use ghostscript as a desktop X viewer for postscript files and documents, simply by typing gs followed by the file you want to see.
# gs contact.ps
There you have it. Another week of me rambling far too long. I look forward to exploring this topic when next we meet here at Sysadmin's Corner. Until then, "Print lightly and carry a big toner cartridge."