Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 71 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
71
Dung lượng
416,76 KB
Nội dung
403 If you have worked in a large systems environment for very long you already know how frustrating it can be to keep the printer farm happy. In my contracting days I worked in several shops that consistently had problems with the printers. In most cases, the print queues went down because of network timeouts and extended device waits. In this kind of environment you have two choices: keep answering the calls from the help desk or write a shell script to monitor the printer queues and reenable the queues as they drop offline. I prefer the second method. Like every other Systems Administrator, I like to be proactive in my approach to solving the little problems as well as the big ones. The shop I remember the best was a hospital. This hospital has more than 30 satellite clin- ics around town and only one 100MB/Sec pipe coming in to the hospital from the out- side world. Most of the clinics have between three and five printers, with at least one printer active most of the day. When I came on board, the first problem I encountered was the huge volume of calls to the help desk about printer problems. What caught my eye was the fact that all of the calls came from the clinics, not from inside the hospital. I knew immediately that a shell script was in order! In this chapter we are going to look at two methods of bringing up the print queues, enabling individual queues and bring- ing up the whole lot. Because Unix flavors vary on handling printers and queues, we first will look at the differences between the Unix flavors. Print Queue Hell: Keeping the Printers Printing CHAPTER 16 System V versus BSD Printer Subsystems Depending on the Unix flavor, the commands vary to control the printers and queues because some use the System V subsystem and others use BSD. With AIX you have an ever more confusing situation beginning with AIX 5L. Starting with this release, AIX now supports both the “classic” AIX printer subsystem and the System V printer ser- vice. Another problem is that some commands do not provide the full print queue name if the queue name exceeds seven characters. I have come up with some ways to get around the long queue names, and on most systems you do not have to worry about long queue names too much if you want to control all of the printers at once. In this book we are covering AIX, HP-UX, Linux, and Solaris. For no other reason that I can think of, let’s cover the printer systems in alphabetical order. AIX Print Control Commands AIX is the most interesting of the bunch with its new support for the System V printer service starting with AIX 5L. Although the AIX classic printer subsystem will still be supported for many years, the move seems to be going to System V for printing service. Classic AIX Printer Subsystem Most AIX Systems Administrators still prefer to use the classic AIX printer subsystem. This is the primary printing that I have supported for years. With the AIX printer sub- system you do not have the detailed control that the System V service offers. For exam- ple, you do not control forms and user priorities at a granular level, and you cannot manage the printers independently of the print queues easily. With this printer sub- system anyone can print on any printer, and the print queue is either UP, allowing you to print, or DOWN, disabling all printing. The shell scripts we are going to write for the classic AIX printer subsystem work at the print queue level. The two commands we are going to use are lpstat and enq -A. Both commands pro- duce the same output, but some administrators seem to like one over the over. As I stated earlier, we need to be aware that sometimes print queues are created with queue names longer than seven characters, which is the default that can be displayed with both of these commands. I guess IBM noticed this little problem and added the -W switch to give a wide character output. Look at Listings 16.1 and 16.2 to see the different outputs. # lpstat Queue Dev Status Job Files User PP % Blks Cp Rnk hp4 lp0 READY hp4-ps lp0 READY hp4-gl lp0 READY yogi_hp lp0 DOWN yogi_hp lp0 DOWN Listing 16.1 Output using lpstat or enq -A. 404 Chapter 16 # lpstat -W Queue Dev Status Job Files User PP % Blks Cp Rnk hp4 lp0 READY hp4-ps lp0 READY hp4-gl lp0 READY yogi_hp4_1 lp0 DOWN yogi_hp4_1ps lp0 DOWN Listing 16.2 Output using lpstat -W or enq -AW. As you can see in Listing 16.1, the long queue names are cut off at the seventh char- acter when using the lpstat or enq -A commands. By adding the -W switch to these commands we see the entire long queue name. This is important because you cannot control a print queue if you do not have the exact, and full, queue name. There are two methods to script using either lpstat -W or enq -AW. One method is to loop through each queue that is reported DOWN; the other is to use one long com- pound command. We are first going to look at the looping method. A little for loop can be used to extract out the queue names of the printers in a DOWN state. The list used for the for loop comes from either of the following command statements: lpstat -W | tail +3 | grep DOWN | awk ‘{print $1}’ or enq -AW | tail +3 | grep DOWN | awk ‘{print $1}’ Both of the previous statements produce the same output. Notice that tail +3 is the second command in pipe, just after the lpstat and enq commands. We use tail +3 in this statement to remove the two lines of header information. This method is much cleaner than trying to grep out some unique character in both of the header lines. Notice that the number of lines, specified by +3, is one larger than the actual num- ber of lines that we want to remove. Using the tail command this way, we are telling tail to start listing at the third line, so two lines are removed at the top of the output. The third command in the pipe is where we grep for DOWN, looking for disabled printers, as shown in Listing 16.2. The output from this stage of the command is only the lines of the enq and lpstat output that contains the word DOWN. Using these lines as input for the next command in the pipe, we are ready to extract the actual queue name(s) of the disabled printers, as shown in the output here. yogi_hp4_1 lp0 DOWN yogi_hp4_1ps lp0 DOWN Print Queue Hell: Keeping the Printers Printing 405 The awk command, as we use it, is used to extract the field that we want to work with, which is the first field, the queue name. Using the previous output as input to our awk statement we extract out the first field using the following syntax: command | awk ‘{print $1}’ You can extract any valid field using awk as well as different fields at the same time. For example, if we want to extract fields 1 and 3, specified by $1 and $3, the following awk statement will take care of the task. command | awk ‘{print $1, $3}’ Notice that I added a comma between $1 and $3. If the comma is omitted, then there will not be a space between the two strings. Instead the output will be two strings appended together without a space. For our for loop we can first send the lpstat and enq command output to a file and process the file in a loop, or we can use command substitution to add the statement directly into the for loop to create the list of objects to loop through. Let’s look at our for loop structure. for Q in $( enq -AW | tail +3 | grep DOWN | awk ‘{print $1}’ ) do # Do something here. done Using this loop command statement, the for loop will loop through yogi_hp4_1 and yogi_hp4_1ps print queue names, which is equivalent to the following for loop structure: for Q in yogi_hp4_1 yogi_hp4_1ps do # Do something here. done Because we never know which queues may be down, we need to parse through the output of the actual queue names of the printers in a disabled state. The shell script in its entirety is shown in Listing 16.3. #!/bin/ksh # # SCRIPT: enable_AIX_classic.ksh # # AUTHOR: Randy Michael # DATE: 03/14/2002 # REV: 1.1.P Listing 16.3 For loop to enable “classic” AIX print queues. 406 Chapter 16 # # PLATFORM: AIX Only # # PURPOSE: This script is used to enable print queues on AIX systems. # # REV LIST: # # set -x # Uncomment to debug this script # set -n # Uncomment to check syntax without any execution # for Q in $( enq -AW | tail +3 | grep DOWN | awk ‘{print $1}’) do enable $Q (( $? == 0 )) || echo “\n$Q print queue FAILED to enable.\n” done Listing 16.3 For loop to enable “classic” AIX print queues. (continued) Inside the for loop we attempt to enable each print queue individually. If the return code of the enable command is not zero we echo an error message indicating that the queue could not be enabled. Notice the highlighted lines in Listing 16.3. We use the mathematical test, specified by the double parentheses, (( math test )). Using this math test you normally do not add a dollar sign, $, in front of a numeric variable. When the variable is produced by the system, such as $?, the dollar sign is required. Testing for equality also requires using the double equal signs, ==, because the single equal sign, =, is meant as an assignment, not a test. After the test to check for a zero return code, we use a logical OR, specified by the double pipes, ||. This logical OR will execute the next command only if the return code of the enable $Q command is nonzero, which means that the command failed. There is also a logical AND that is used by placing double ampersands, &&, in a com- mand statement. A logical AND does just the opposite; it would execute the succeeding command if the test is true, instead of false. Both the logical OR and logical AND are used as replacements for if then else statements. We can also accomplish this task by using a single compound command statement. Just as we used command substitution in the for loop, we can use command substitu- tion to produce command parameters. For example, we can use our for loop command to create command parameters to the enable command. To see this more clearly, look at the following two commands. enable $(enq -AW | tail +3 | grep DOWN | awk ‘{print $1}’) 2>/dev/null or enable $(lpstat -W | tail +3 | grep DOWN | awk ‘{print $1}’) 2>/dev/null Print Queue Hell: Keeping the Printers Printing 407 Both of the previous compound command statements produce the same result, enabling all of the print queues on the system. The only problem with using this tech- nique is that if you execute this command and all of the printers are already enabled, then you will get the following output from standard error: usage: enable PrinterName Enables or activates printers. As you can see, I sent this output to the bit bucket by adding 2>/dev/null to the end of the statement, but the return code is still nonzero if all of the printers are already enabled. This should not be a problem unless you want to create some notification that a printer failed to enable. In our for loop in Listing 16.3 we used the return code from the enable command to produce notification. I will leave the technique that you use up to you. If you do not want to see any output, then you could add the single com- pound statement as a cron table entry or use the for loop technique in a shell script to redirect the failure notification to a log file. If you use a log file you may want to add a date stamp. System V Printing on AIX Beginning with AIX 5L, IBM supports System V printing. I find that Solaris has the closest command usage and output. With only a few differences between AIX and Solaris System V printing in the output produced, you could use the shell scripts inter- changeably. Because people tend to read only the parts of a technical book that they need to, I will devote this entire section to AIX System V printing. To switch your AIX system from the “classic” AIX printer subsystem to System V printing, refer to your AIX reference manual. This section expects that you are already running System V printing. Like Solaris, AIX uses the System V lpc (line printer control) command to control the printers and print queues. The nice thing about this print service is that you can con- trol the queues and the printers independently. The main commands that we are inter- ested in for AIX queuing and printing include the following options and parameters to the lpc command, as shown in Table 16.1. Table 16.1 AIX lpc Command Options LPC COMMAND COMMAND RESULT disable (printer[@host] | all) Disables queuing stop (printer[@host] | all) Disables printing down (printer[@host] | all) Disables printing and queuing enable (printer[@host] | all) Enables queuing start (printer[@host] | all) Enables printing up (printer[@host] | all) Enables printing and queuing 408 Chapter 16 As you can see in Table 16.1, the granularity of printer control is excellent, which gives us several options when creating shell scripts. To control all of the printing and queuing at one time you really do not need a shell script. The following two commands can start and stop all printing and queuing on all print queues at the same time. lpc down all # Disable all printing and queuing lpc up all # Enable all printing and queuing To keep all of the printers printing and queuing you only need the lpc up all com- mand entered into a cron table. I placed an entry in my root cron table to execute this lpc command every 10 minutes, as shown here: 5,15,25,35,45,55 * * * * /usr/sbin/lpc up all >/dev/null 2>&1 This cron table entry enables all printing and queuing on all printers on the 5s, 24 hours a day, 7 days a week. With AIX System V printing, the data we are interested in is separated on three lines of output when we use the lpc status all command to mon- itor the printer service. The same command executed on AIX , Linux, and Solaris is shown here. AIX SYSTEM V OUTPUT # lpc status all hp4V: queueing is enabled printing is disabled 5 entries in spool area LINUX SYSTEM V OUTPUT # lpc status Printer Printing Spooling Jobs Server Subserver Redirect Status/(Debug) hp4@localhost enabled disabled 0 none none SOLARIS SYSTEM V OUTPUT # lpc status all bambam_hp4: queueing is enabled printing is enabled no entries Of these three outputs Linux is the one that differs. With the data we are interested in for AIX residing on three separate lines for each print queue, we need a different Print Queue Hell: Keeping the Printers Printing 409 strategy to get the exact data the we want. First notice that at the beginning of each stanza a queue name has a colon, :, appended to the name of the queue. Because this character occurs only in the queue name, we can use the colon character as a tag for a grep statement. Following the queue name entry, the next two lines contain the data that we are interested in pertaining to the status of the queuing and printing. Because we have some unique tag for each entry, it is easy to extract the lines of data that we are interested in by using an extended grep, or egrep, statement, as shown here: lpc status all | egrep ‘:|printing|queueing’ | while read LINE The egrep command works the same way as the grep command except that you can specify multiple patterns to match. Each pattern is separated by a pipe without any spaces! If you add spaces on either side of the search pattern, the egrep statement will fail to make a match. The entire list of patterns is then enclosed within single forward tic marks, ’pattern1|pattern2|pattern3’. The output produced has the queue name on the first line, the printing status on the second line, and the queuing status on the third line. The last part of the previous command is where the output is piped to a while loop. On each read the entire line of data is loaded into the variable LINE. Inside of the while loop we use the following case statement to assign the data to the appropriate variable. case $LINE in *:) Q=$(echo $LINE | cut -d ‘:’ -f1) ;; printing*) PSTATUS=$(echo $LINE | awk ‘{print $3}’) ;; queueing*) QSTATUS=$(echo $LINE | awk ‘{print $3}’) ;; esac Notice that if $LINE begins with *: then we load the Q variable. If $LINE begins with printing* we load the PSTATUS variable with the third field, which should be either enabled or disabled. We do the same thing in loading the QSTATUS variable with the third field of the value that the $LINE variable points to. The trick in this script is how to load and process three lines of data and then load and process three more lines of data, and so on. The most intuitive approach is to have a loop counter. Each time the loop counter reaches three we process the data and reset the loop counter back to zero. Take a look at the entire script in Listing 16.4 to see how this loop count works. Pay close attention to the bold type. 410 Chapter 16 #!/bin/ksh # # SCRIPT: print_UP_SYSV_AIX.ksh # # AUTHOR: Randy Michael # DATE: 03/14/2002 # REV: 1.1.P # # PLATFORM: AIX System V Printing # # PURPOSE: This script is used to enable printing and queuing separately # on each print queue on AIX and Solaris systems. # # REV LIST: # # set -x # Uncomment to debug this script # set -n # Uncomment to check syntax without any execution # ################################################# LOOP=0 # Loop Counter - To grab three lines at a time lpc status all | egrep ‘:|printing|queueing’ | while read LINE do # Load three unique lines at a time case $LINE in *:) Q=$(echo $LINE | cut -d ‘:’ -f1) ;; printing*) PSTATUS=$(echo $LINE | awk ‘{print $3}’) ;; queueing*) QSTATUS=$(echo $LINE | awk ‘{print $3}’) ;; esac # Increment the LOOP counter (( LOOP = LOOP + 1 )) if ((LOOP == 3)) # Do we have all three lines of data? then # Check printing status case $PSTATUS in Listing 16.4 print_UP_AIX.ksh shell script listing. (continues) Print Queue Hell: Keeping the Printers Printing 411 disabled) lpc start $Q >/dev/null (($? == 0)) && echo “\n$Q printing re-started\n” ;; enabled|*) : # No-Op - Do Nothing ;; esac # Check queuing status case $QSTATUS in disabled) lpc enable $Q >/dev/null (($? == 0)) && echo “\n$Q queueing re-enabled\n” ;; enabled|*) : # No-Op - Do Nothing ;; esac LOOP=0 # Reset the loop counter to zero fi done Listing 16.4 print_UP_AIX.ksh shell script listing. (continued) Notice that we grab three lines at a time. The reason that I say that we are grabbing three lines at a time is because I use the case statement to specify unique tags for each line of data. I know that the queue name will have a colon, :, as a suffix. I know that the printing status line will begin with printing*, and I know that the queuing line will begin with queueing*. We load only one variable on each loop iteration. So, to get three pieces of data (queue name, printing status, and queuing status), we need to go through the while loop three times for each printer queue. Once we pass the initial case statement, we increment the LOOP counter by one. If the $LOOP variable is equal to 3 then we have all of the data that we need to process a single printer queue. After processing the data for this printer queue, we reset the LOOP variable to zero, 0, and start gathering data for the next printer queue. Sounds simple enough? This same technique works for any fixed set of lines of data in command output or in a file. The only changes that are needed to use this method include creating unique tags for the data you are interested in and setting the $LOOP equality statement to reflect the number of lines in each set of data. More System V Printer Commands We have been looking at only the lpc command thus far. We also need to look at two command parameters to the lpstat command in this section. The -a parameter lists the status of queuing, and the -p command parameter lists the status of printing. The nice thing about these two command options is that the output for each queue is on a sin- gle line, which makes the data easier to parse through. See Table 16.2. 412 Chapter 16 [...]... accepting requests since May 07 07: 02 2002 yogi_hp4_1ps accepting requests since May 07 07: 02 2002 long_queue not accepting requests since Tue May 7 07: 02:23 EDT 2002 s_q_nam not accepting requests since Tue May 7 07: 02:23 EDT 2002 - # lpstat -p printer long_queue disabled since Tue May 7 07: 02:01 EDT 2002 available stopped by user printer s_q_nam disabled since Tue May 7 07: 02:01 EDT 2002 available stopped... accepting requests since May 07 07: 02 2002 yogi_hp4_1ps accepting requests since May 07 07: 02 2002 Listing 16.12 lpstat -a and lpstat -p command output (continues) 429 430 Chapter 16 long_queue not accepting requests since Tue May s_q_nam not accepting requests since Tue May 7 07: 02:23 EDT 2002 - 7 07: 02:23 EDT 2002 - # lpstat -p printer long_queue disabled since Tue May 7 07: 02:01 EDT 2002 available... long_queue disabled since Tue May 7 07: 02:01 EDT 2002 available stopped by user printer s_q_nam disabled since Tue May 7 07: 02:01 EDT 2002 available stopped by user printer hp4 unknown state enabled since May 07 07: 30 2002 available printer yogi_hp4_1ps unknown state enabled since May 07 07: 30 2002 available Listing 16.12 lpstat -a and lpstat -p command output (continued) Notice in Listing 16.12 that the... | awk ‘{print $3}’) fi done Listing 16 .7 print_UP_HP-UX.ksh shell script listing Print Queue Hell: Keeping the Printers Printing I want to point out a nice little trick in the shell script in Listing 16 .7 In both of the if then fi statements, notice that we execute a command inside parentheses What this technique allows us to do is execute a command in a sub -shell and use the command’s resulting return... 2002 available stopped by user printer s_q_nam disabled since Tue May 7 07: 02:01 EDT 2002 available stopped by user printer hp4 unknown state enabled since May 07 07: 30 2002 available printer yogi_hp4_1ps unknown state enabled since May 07 07: 30 2002 available Listing 16.5 lpstat -a and lpstat -p command output Notice in Listing 16.5 that the output from each command option has a unique set of status... queuing_only_UP_Linux.ksh shell script listing Notice that the only thing that was changed this time is the first case statement structure was removed from the script and the name of the shell script was changed Print Queue Hell: Keeping the Printers Printing You could also modify the shell script in Listing 16.8 to add a command-line parameter to let you control queuing and printing individually from the same shell. .. Now we need to combine the shell scripts for each of the different Unix flavors so that one script does it all Please do not think that taking several shell scripts, making functions out of them, and combining the new functions into a new script are difficult tasks To make one script out of this chapter we are going to take the best of our scripts and extract the code For each shell script we make a new... always want to enable printing and queuing at the same time We can break up the shell script in Listing 16.8 and pull out the individual case statements to start either printing or queuing Because printing is controlled by array element 2 we can extract the first case statement to create a new shell script Let’s call this shell script printing_only_UP_Linux.ksh You can see the modifications in Listing... the logging out to the main body of the shell script This means that you can capture all of the output data of the function to save to a log file, use the tee command to view the data while logging at the same time, or just point it to the bit bucket by redirection to /dev/null Other Options to Consider As usual, we can always improve on a shell script, and these shell scripts are no exception Some options... command, as shown in Table 16.4 As you can see in Table 16.4, the granularity of printer control is excellent, which gives several options when creating shell scripts To control all of the printing and queuing at one time you really do not need a shell script The following two commands can start and stop all printing and queuing on all print queues at the same time lpc down all # Disable all printing . May 07 07: 02 2002 yogi_hp4_1ps accepting requests since May 07 07: 02 2002 long_queue not accepting requests since Tue May 7 07: 02:23 EDT 2002 - s_q_nam not accepting requests since Tue May 7 07: 02:23. May 7 07: 02:01 EDT 2002. available. stopped by user printer s_q_nam disabled since Tue May 7 07: 02:01 EDT 2002. available. stopped by user printer hp4 unknown state. enabled since May 07 07: 30. ‘{print $3}’) fi done Listing 16 .7 print_UP_HP-UX.ksh shell script listing. 416 Chapter 16 I want to point out a nice little trick in the shell script in Listing 16 .7. In both of the if then fi statements,