Tuesday, October 16, 2012

AIX A-Z: Managing printing on AIX


IBM has created intuitive commands that assist IBM AIX administrators in configuring and managing print queues easily. The System Management Interface Tool (SMIT) offers a menu-driven interface to manage print queues. However, if you're interested in learning to use the command line for such things, this article outlines the AIX print queue files and provides a few commands for managing them.
Before diving into the printer commands, you need to know the location of the files discussed in this article. Understanding the files and what you're modifying prior to executing the actual commands is important; AIX, like other flavors of UNIX® and Linux®, is not very forgiving if you accidentally delete or modify a file prematurely without making a backup of the original. I'm guilty of this crime, as are most seasoned administrators, but it usually only takes a single (but powerful and sometimes very painful) deletion to learn your lesson.
On AIX, most system configuration files can be found centrally in /etc. The print queue configuration files are no different. Listing 1 shows the location of the printer queue configuration files.

 
# ls –l /etc/qconfig*

-rw-rw-r--    1 root     printq          436 Aug 07 2009  /etc/qconfig
-rw-rw----    1 root     printq         5442 Feb 24 19:54 /etc/qconfig.bin

The /etc/qconfig file contains detailed configuration information on print queues and print devices. The file is structured in stanzas, or a block of parameters and values under a single main keyword. For every queue stanza, at least one device stanza immediately follows.
The /etc/qconfig structure is shown in Listing 2.

 
<queue name>:
<queue parameter> = <queue parameter value>
<device>:
<device parameter> = <device parameter value>

Table 1 shows the parameters and possible values that can be used inside the /etc/qconfig file. These parameters define a print queue.

Parameter
Description
Values
Default
acctfile
Write print accounting information to <acctfile> if it exists.
<filename>
FALSE (no accounting)
device
Name of the device stanza.
<device stanza name>
This field is required, so there is no default value.
discipline
Printing priority order.
fcfs (first come, first served)
fcfs
sjn (shortest jobs first)
up
Queue status.
TRUE (The queue is running.)
TRUE
FALSE (The queue is not running.)
recovery_type
If the queue is down, invoke the recovery_typeaction.
queuedown (Leave the queue down until manual intervention takes place.)
queuedown
runscript <script> (Execute <script>.)
retry -T <min> -R <n> (Attempt to re-enable the queue after <min> minutes. If the queue isn't re-enabled successfully, try again in <min> and repeat <n> times before giving up.)
sendmail <user> (E-mail <user> that the queue is down.)
The parameters listed in Table 2 define a remote print queue.

Parameter
Description
Values
host
Host in which the remote queue is located
<hostname> or <IP>
s_statfilter
Queue status format (short version format)
/usr/lib/lpd/bsdshort (BSD remote system)
/usr/lib/lpd/aixv2short (RT remote system)
/usr/lib/lpd/attshort (AT&T remote system)
l_statfilter
Queue status format (long version format)
/usr/lib/lpd/bsdlong (BSD remote system)
/usr/lib/lpd/aixv2long (RT remote system)
/usr/lib/lpd/attslong (AT&T remote system)
rq
Remote queue name
<queue name>
The parameters shown in Table 3 define a print device.

Parameter
Description
Values
Default
access
Back-end access to <FILE>
WRITE (Write access)
WRITE
BOTH (Read and Write access)
align
Send a form-feed control if the printer was idle.
TRUE (Send form-feed.)
TRUE
FALSE (Don't send form-feed.)
backend
Full path of the back end
<FULL PATH OF FILE>
feed
Advance N pages if the printer goes idle.
<N> (Advance N pages.)
FALSE
FALSE (Don't advance any pages.)
file
Redirect back-end output.
<FILE> (Write to <FILE>.)
FALSE
FALSE (Don't write to file.)
header
Print header page.
NEVER (Don't print header pages.)
NEVER
ALWAYS (Always print header pages.)
GROUP (Print header pages for multiple print jobs by the same user.)
trailer
Print trailer page.
NEVER (Don't print header pages.)
NEVER
ALWAYS (Always print header pages.)
GROUP (Print header pages for multiple print jobs by the same user.)
To make sense of all these parameters, Listing 3 provides an example of a simple print queue and device that could be found in AIX's /etc/qconfig file.

 
pac22_ps:
        device = hp@pac22
hp@pac22:
        file = /var/spool/lpd/pio/@local/dev/hp@pac22#hpJetDirect#9100
        header = never
        trailer = never
        access = both
        backend = /usr/lib/lpd/pio/etc/piojetd pac22 9100

It looks like the queue named pac22_ps is using device hp@pac22. As far as device hp@pac22 itself, header and trailer pages are disabled, the device can both read and write to file /var/spool/lpd/pio/hp@pac22#hpJetDirect#9100, and is using back-end file /usr/lib/lpd/pio/etc/piojetd (JetDirect) on port 9100.
The file /etc/qconfig.bin is a binary version of /etc/qconfig and is used by a command named qdaemon, which schedules printing jobs via the command enq.
Now that you understand the configuration file /etc/qconfig, let's talk about where the actual information is stored for the print queues and devices. Three directories reside under /var/spool/lpd. The first directory is /var/spool/lpd/qdir. When printing a file in AIX, a file is created in /var/spool/lpd/qdir that contains environment information of the user who sent the print job, as well as where to find what is being printed. Here's an example to explain what you may see in a file under /var/spool/lpd/qdir.
Printing can occur very quickly, so in this example, print jobs were sent to a queue that is currently disabled to ensure that you still have the files to look at before they're completely processed. Now, take a look at the print-disabled print queue, send a print job, and look again—but this time, getting a bit more information with the –t switch. Listing 4 shows the print queue.

 
# lpstat -W
Queue                Dev            Status       Job Files              User       Rnk
-------------------- -------------- --------- ------ ------------------ ---------- ---
pac22_ps             hp@pac22       DOWN
                                    QUEUED      1165 STDIN.946314       root        1
                                    QUEUED      1166 STDIN.1110038      root        2
atc04_ps             hp@atc04       READY

# echo "test3" | lp -d pac22_ps
Job number is: 167

# lpstat -t
 Queue   Dev   Status    Job     Name           From           To
                         Submitted        Rnk Pri       Blks  Cp
 ------- ----- --------- ---------        --- ---      ----- ---
 pac22_p hp@pa DOWN
               QUEUED    165     STDIN.946314   root           root
                        03/03/10 13:40:38    1  15          1   1
                               /var/spool/qdaemon/tb_3iEa
               QUEUED    166     STDIN.1110038  root           root
                        03/03/10 13:44:48    2  15          1   1
                               /var/spool/qdaemon/tj3Ybya
               QUEUED    167     STDIN.827498   cormany        cormany
                        03/03/10 13:47:03    3  15          1   1
                               /var/spool/qdaemon/t1ZEgEa
 atc04_p hp@at READY

Good. The print job that I created is there and queued. Now, look to see what files are in /var/spool/lpd/qdir:
# ls -l /var/spool/lpd/qdir
total 24
-rw-rw----  1 root   printq      1663 Mar 03 13:47 n0cormany:pac22_ps$#@!EgEc
-rw-rw----  1 root   printq      1913 Mar 03 13:40 n0root:pac22_ps$#@!3iEc
-rw-rw----  1 root   printq      1919 Mar 03 13:44 n0root:pac22_ps$#@!Ybyc

It's easy in this example to discern which file belongs to the print job I just sent, but what if the print queue has been down for hours and hundreds of print jobs are queued and waiting to print? One method you can use to find which file you need is by looking at the file name listed in lpstat –t. In this example, the file t1ZEgEa was created under /var/spool/qdaemon. By looking at the characters 4 through 6 of the file name (for example, EgE), you can surmise n0cormany:pac22_ps$#@!EgEc is what you want to look at.
Listing 5 shows the messy output.

 
# cat 'n0cormany:pac22_ps$#@!EgEc'

000001167
#@%!: 0 0 15 0 0 1267642023
1 1 3 3
cormany 0
REAL_USER=cormanyLOGIN_USER=rootREAL_GROUP=atcGROUPS=atc,
    support,sshd
    AUDIT_CLASSES=RLIMIT_CPU=9223372036854775807
    RLIMIT_FSIZE=18014398509481984
    RLIMIT_DATA=18014398509481984
    RLIMIT_STACK=8388608
    RLIMIT_CORE=18014398509481984
    RLIMIT_RSS=18014398509481984
    RLIMIT_NOFILE=9223372036854775807
    RLIMIT_THREADS=9223372036854775807
    RLIMIT_NPROC=9223372036854775807
    RLIMIT_CPU_HARD=9223372036854775807
    RLIMIT_FSIZE_HARD=18014398509481984
    RLIMIT_DATA_HARD=18014398509481984
    RLIMIT_STACK_HARD=8388608
    RLIMIT_CORE_HARD=18014398509481984
    RLIMIT_RSS_HARD=18014398509481984
    RLIMIT_NOFILE_HARD=9223372036854775807
    RLIMIT_THREADS_HARD=9223372036854775807
    RLIMIT_NPROC_HARD=9223372036854775807
    UMASK=22
    PAG_DATA=
USRENVIRON:_=/usr/bin/lp
  LANG=en_US
  LOGIN=cormany
  G_BROKEN_FILENAMES=1
  VISUAL=vi
  XREMOTETMPDIR=/home/cormany
  PATH=/usr/bin:/etc:/usr/sbin:/usr/ucb:/bin:/usr/bin/X11:/sbin:
    /usr/java5/jre/bin:/usr/java5/bin:/usr/ushare/bin:/usr/local/bin:.:
  LC__FASTMSG=true
  EDITOR=vi
  HISTFILE=/home/cormany/history_1040542
  LOGNAME=cormany
  MAIL=/usr/spool/mail/cormany
  LOCPATH=/usr/lib/nls/locPS1=#
  USER=cormany
  AUTHSTATE=NIS
  SHELL=/bin/ksh
  ODMDIR=/etc/objrepos
  HISTSIZE=100
  HOME=/home/cormany
  TERM=xterm
  MAILMSG=[YOU HAVE NEW MAIL]
  PWD=/home/cormany
  TZ=America/New_York
  ENV=/home/cormany/.kshrc
  A__z=!
  LOGNAMESYSENVIRON:LOGNAME=cormany
  NAME=cormany
  TTY=/dev/pts/7

This information may look like garbage, but it can be very useful. An administrator can view this file and try to discern why a print job has failed by looking at the user’s environment, which is included in the file.
The second directory is /var/spool/lpd/stat. As its name references, this directory contains status information on the print devices. Each device will have a file in this directory. Unfortunately, the files are not in ASCII format, so there is little to view here, but it’s good to know where these files reside.
The third and final directory in /var/spool/lpd is /var/spool/lpd/pio. This directory contains information on the back end that qdaemon uses. This is where the print queue typically reads and writes its back-end data.
The directory /var/spool/qdaemon is an important directory in the printing process on AIX. It contains a copy of the actual file being printed, as Listing 6 shows.

 
# ls -l /var/spool/qdaemon
total 24
-rw-r-----    1 cormany  printq            6 Mar 03 13:47 t1ZEgEa
-rw-r-----    1 root     printq            5 Mar 03 13:40 tb_3iEa
-rw-r-----    1 root     printq            6 Mar 03 13:44 tj3Ybya
# cat /var/spool/qdaemon/t1ZEgEa
test3

Creating a print queue in AIX using the command line is easy. You do so using the command mkque. Here are a few options that you can use when executing mkque:
  • -a '<attribute> = <value>'. Assign values to the attributes explained earlier in this article.
  • -D. Make this print queue the default queue.
  • -q <queue name>. Name the queue <queue name>.
Now that you know the basics, create a new print queue using the code in Listing 7.

 
# mkque -q AMDC79 -a 'recovery_type = sendmail cormany'

# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               dumm           UNKNOWN

With a new print queue created, attach the queue to a newly created print queue device. By using the command mkquedev, you can create new print queue devices and add an existing queue quickly. Here are a few options that you can use when executing mkquedev:
  • -a '<attribute> = <value>'. Assign values to the attributes explained earlier in this article.
  • -d <queue device name>. Name the queue device <queue device name>.
  • -q <queue name>. Add <queue name> to <queue device name>.
Now that you know the basics, you can create a new print queue device and attach the queue you just created to it. Listing 8 shows the code.

 
# mkquedev -q AMDC79 -d hp@pac22 -a 'header = always' -a 'backend = 
    /usr/lib/lpd/pio/etc/piojetd pac22 9100’

# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       READY

The file /etc/qconfig now contains the new queue and device shown in Listing 9.

 
AMDC79:
        device = hp@pac22
        recovery_type = sendmail cormany
pa@pac22:
        header = always
        backend = /usr/lib/lpd/pio/etc/piojetd pac22 9100

Now you have a new queue and device, and you can begin changing some of the attributes. The commands chque and chquedev allow you to change attributes to a new value.
Here are the options that you can use when executing chque:
  • -a <attribute=value>. Change <attribute> to have a value of <value>.
  • -q <queue>. Query the printer's queue named <queue>.
The options for chquedev are similar:
  • -a <attribute=value>. Change <attribute> to have a value of <value>.
  • -d <device name>. Query the device named <device>.
  • -q <queue>. Query the printer's queue named <queue>.
Start by changing the queue's recovery_type to run a script that fixes the queue if it goes down:
# chque -q AMDC79 -a 'recovery_type = runscript /home/cormany/fix_printer'

Now, change the queue's device attribute header to group and add the attribute trailer:
# chquedev -q AMDC79 -d hp@pac22 -a 'header = group' -a 'trailer = group'

The changes should now be complete. To verify, look in /etc/qconfig:
AMDC79:
        device = hp@pac22
        recovery_type = runscript /home/cormany/fix_printer
hp@pac22:
        trailer = group
        header = group
        backend = /usr/lib/lpd/pio/etc/piojetd pac22 9100

Like most commands in AIX, there are several ways to accomplish the same task. Viewing information from /etc/qconfig is no different. The preferred and safer method of viewing queue and queue device information is to use lsque and lsquedev.
By using lsque, you see the queue information only as follows:
# lsque -q AMDC79
AMDC79:
        device = hp@qaljlab3
        recovery_type = runscript /home/cormany/fix_printer

By using lsquedev on the print queue in the code above, you'll see the device queue information only as shown below:
# lsquedev -q AMDC79 -d hp@pac22
hp@pac22:
        trailer = group
        header = group
        backend = /usr/lib/lpd/pio/etc/piojetd pac22 9100

Another handy option in both lsque and lsquedev is the ability to create colon-delimited output of the queue and queue device. This format of output can be useful if scripting print-management functions. Listing 11 shows the output of lsque and lsquedev.

 
# lsque -q AMDC79 -c
#name:device:discipline:up:acctfile:host:s_statfilter:l_statfilter:rq
AMDC79:hp@pac22:fcfs:TRUE:FALSE::::

# lsquedev -q AMDC79 -d hp@qaljlab3 -c
#name:file:access:feed:header:trailer:backend:align
hp@pac22:FALSE:write:never:group:group:/usr/lib/lpd/pio/etc/piojetd pac22 9100:FALSE

Removing print queues and print queue devices is easy in AIX. IBM has provided the commands rmque and rmquedev to handle such a task.
To remove the print queue and device previously created in this article, simply execute the code in Listing 12.

 
# rmquedev -q AMDC79 -d hp@pac22
# rmque -q AMDC79

# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY

There are several ways to terminate print jobs in AIX. You could use cancellprm, or qcan among many other commands. This article focuses on just cancel.
The command cancel is straightforward. You can specify either an individual print job number, a group of print job numbers, or the entire queue. Take a look at the queue AMDC79 again. It looks like the print jobs are starting to back up in the disabled queue. The first example only terminates the first print job, 1169 (see Listing 13).

 
# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       DOWN
                                    QUEUED      1169 STDIN.1134828      root        1   1
                                    QUEUED      1171 STDIN.1134838      root        1   2
                                    QUEUED      1172 STDIN.1134840      root        1   3
                                    QUEUED      1173 STDIN.1134842      root        1   4
                                    QUEUED      1174 STDIN.1134844      root        1   5
                                    QUEUED      1175 STDIN.1134846      root        1   6
                                    QUEUED      1176 STDIN.1134592      root        1   7

First, verify the variable PRINTER is set to AMDC79. Then, select the print job you want to terminate (1169) and cancel it. Listing 14 shows the code.

 
# echo $PRINTER
AMDC79
# cancel 1169
# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       DOWN
                                    QUEUED      1171 STDIN.1134838      root        1   2
                                    QUEUED      1172 STDIN.1134840      root        1   3
                                    QUEUED      1173 STDIN.1134842      root        1   4
                                    QUEUED      1174 STDIN.1134844      root        1   5
                                    QUEUED      1175 STDIN.1134846      root        1   6
                                    QUEUED      1176 STDIN.1134592      root        1   7

This is good; the first print job was removed, but the queue is still down. Now, remove jobs 1171, 1173, and 1176. Listing 15 shows the code.

 
# cancel 1171 1173 1176
# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       DOWN
                                    QUEUED      1172 STDIN.1134840      root        1   3
                                    QUEUED      1174 STDIN.1134844      root        1   5
                                    QUEUED      1175 STDIN.1134846      root        1   6

From there, you can terminate the rest of them. Listing 16 shows the code.

 
# cancel AMDC79
# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       DOWN

All the print jobs have been removed from print queue AMDC79, and the support staff says the printer has been fixed. It's time to see if the printer is working again. AIX offers the commands disable and enable to accomplish these tasks.
Listing 17 shows the code for enabling a print queue.

 
# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       DOWN

# enable AMDC79

# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       READY

To re-enable the print queue, simply type enable <print queue>.</print>.
Easy, eh? But wait—the department has received word that the print queue is back up, and now they're sending hundreds of jobs to it. That's great, right? Next phone call you receive is from the support staff saying that there's another issue they didn't see with the printer. Now, you have hundreds of jobs coming through the print queue, and you need to terminate the jobs and disable the printer immediately! Don't panic: disable can do the job for you. By supplying the switch –c to disable all print jobs in the queue, the jobs are removed and the queue is disabled. Whew, that was a close one! Listing 18 shows the code.

 
# disable –c AMDC79
# lpstat -W
Queue                Dev            Status       Job Files              User     Blks Rnk
-------------------- -------------- --------- ------ ------------------ -------- ---- ---
pac22_ps             hp@pac22       READY
atc04_pcl            hp@atc04       READY
AMDC79               hp@pac22       DOWN

This article has talked about adding, removing, and modifying queues, and throughout I've used the standard lpstat command that most seasoned UNIX users know. But note that there are a lot of other commands in the AIX arsenal of utilities. To view the status of a print queue, you could use lpstatqchklpq, or qstatus. Because lpstat is so widely used, let's take a look at another command. The command qchk can be useful while looking at print queue status information.
Here are a few options to think about when using qchk:
  • -# <print job number>. View the status of a specific print job.
  • -A. Look at all print queues.
  • -L. View the output in long format.
  • -P <printer>. View the status of <printer>.
  • -q. View the status of the default printer.
  • -u <user>. View the status of jobs sent by <user>.
  • -W. View the output, showing longer names of queues, devices, and so on.
  • -w <seconds>. Refresh output every <seconds> seconds until the queue is empty.
As a reminder regarding the –q switch displaying the default printer, in AIX the default printer is the queue first in /etc/qconfig.
One handy usage of qchk is to watch print jobs sent by a user or to view a specific print job. For example, a user named Xander has sent a few jobs to a print queue and claims he isn't getting his printouts when another user named Paul has gotten his earlier in the day. To quickly and easily find all print jobs sent by Xander, you could use qchk, as shown in Listing 19.

 
# qchk -u xander
Queue   Dev   Status    Job Files              User         PP %   Blks Rnk
------- ----- --------- --- ------------------ ---------- ---- -- ----- ---
pac22_p hp@pa DOWN
              QUEUED    191 tmp1238            xander                 4   1
              QUEUED    192 tmp1323            xander                 4   1
              QUEUED    193 tmp1347            xander                 4   1
              QUEUED    194 tmp1789            xander                 4   1
              QUEUED    195 tmp9831            xander                 4   1

Found them! As Xander said, none of his print jobs have gone through. It looks like the printer queue is down and some troubleshooting is needed. After a quick phone call, you find out that the printer ran out of paper. After the paper has been replenished and the queue has been re-enabled, all of Xander's print jobs have printed successfully. Now, verify that Xander isn't waiting on any other print jobs:
# qchk -u xander
Queue   Dev   Status    Job Files              User         PP %   Blks Rnk
------- ----- --------- --- ------------------ ---------- ---- -- ----- ---
pac22_p hp@pa READY

Nice work. Another possible disaster adverted. Just to be on the safe side, you decide to watch the busy queue for a while but don't want to keep retyping the commands or pressing Escape K. Here's a nice way to watch the queue and let the output refresh on its own. In this example, the queue output refreshes every 5 seconds until the queue has been completely emptied:
# qchk -P pac22_ps -w 5

After reading this article, you should have a better understanding of how to manage print queues and print queue devices in AIX, including how to create them and how to modify or manage them. Knowing more about how the printers and the queues are set up on your system is important. A lot of people don't realize how many settings are in a queue that can be changed easily. You may be able to make someone's day by modifying their printer to suit their needs. Good luck!