Converting AIX Print Queues to Linux

I spent the last week working on a project to convert all of the forms printing at the Circus from an AIX server to a Linux server. Because the version we are stuck on is not officially supported by the vendor I had to do some reverse engineering to figure out how things work, this article describes some of the scripts I used to understand what the software was doing and how to make it work the way we needed.

The funny thing about any printer project I get into, usage seems to explode. Yesterday we had a water cooler meeting about how to print from a completely different EMR system. I’m not sure we will do it because we need to know patient location but the printing part is easy. Who knew a paperless organization prints so much.

We have about 500 printers on the network and less than 314 forms, my guess would peg us closer to 150 forms, but when I go through the forms directory I get 314.

# ls -1 | cut -d _ -f 1,2 | sort -u | wc
    314     314    3293

Regardless, the number of forms is not the issue. I changed everything I needed programmatically as you will see below. All of the scripts in the post can be downloaded here.

First I needed to get a connection from one of our electronic medical records applications to the new Linux forms print server. I wrote a short script that shows me the arguments passed to the printer as well as the standard input. This allowed me to troubleshoot what was being passed from one server to another and also gave me insight into how the whole process worked.

#!/usr/bin/perl -w
use strict;

# 2010-02-17  Jud Bishop
# Quick hack to see what I am being sent from the port.
# Released under the GNU GPLv2

my $file = "/tmp/print-test.txt";

sleep 5;
unlink $file;

open (NEWFILE, ">$file" ) or die("Error: can't open $file\n$!");

        print NEWFILE "Args:\n";
        for (my $i = 0; $i <= $#ARGV; $i++) {
                print NEWFILE "argv[$i] == $ARGV[$i]\n";
        }

        print NEWFILE "Data:\n";
        while (<STDIN>) {
                print NEWFILE $_;
        }

close NEWFILE or die("Error: can't close $file\n$!");

Once I got the two servers communicating properly it was time to troubleshoot some configuration files that were copied from the AIX server to Linux. I ended up writing the next short script to change some application configuration files that were originally made to work on AIX. This changes the print command from the AIX qprt command to Linux lpd.

# 2010-02-17  Jud Bishop
# This script changes all of the printer configuration channels
# from AIX specific qprt to Linux specific lp commands.
# Released uner the GNU GPLv2

for I in `ls -1`
do
	sed 's/lp -d/lp -d/g' $I > tmp
	if [ $? -eq 0 ]
	then
		mv -f tmp $I
	else
		echo $I "did not complete"
		exit
	fi
done

Now it was time to write a short script to convert the /etc/qconfig printer configuration file from AIX and add the printers on the Linux server. So I wanted to test adding and deleting a printer from cups on the command line. I thought the following command would work.

# lpadmin -p misp1 -E -v socket://misp1.circus.org -m laserjet
# lpadmin: Unable to copy PPD file!

If all else fails read the man page, or in this case the manual on the web. It’s pretty cryptic but they tell you that the -m model has to be from the model directory. Where is the model directory?

# find / -name model
...
/usr/share/cups/model
# ls -1 /usr/share/cups/model/
deskjet2.ppd.gz
epson9.ppd.gz  
laserjet.ppd.gz

So we want the model from /usr/share/cups/model. The following command works:

# lpadmin -p misp1 -E -v socket://misp1.circus.org -m laserjet.ppd.gz

Now it’s time to convert from qconfig to cups. I used the following script to read in qconfig and create the printers. I had to add the sleep because the script got ahead of the lpadmin command. Once I added the sleep it worked and ta-da, 500 printers were created. I realize that printers are added and deleted from the AIX server daily so I had to make sure it would add and delete printers so that we will get them all on go-live day. It’s a rudimentary implementation but it works.

Notes on this script, it was easier than I expected, hence I a have hash instead of just working from the original array. It’s one of those things that I’m not going to go back and clean up for a simple script, sorry.

#!/usr/bin/perl

# 2010-02-18  Jud Bishop
# This script reads in the qconfig file of an AIX server and 
# converts it to a Linux based cups file.  
# I am expecting this to be a quick hack...
# Released under the GNU GPLv2

# /etc/qconfig is the AIX printer configuration file.
#labp4: 
#        device = @hpjd007
#        up = TRUE
#        host = hpjd007.circus.org 
#        s_statfilter = /usr/lib/lpd/bsdshort
#        l_statfilter = /usr/lib/lpd/bsdlong
#        rq = PORT1 
#@hpjd007:
#        backend = /usr/lib/lpd/rembak -T 30
open (FILE,"<etc-qconfig") or die "Error: can't open file $! \n";
        @aix = <FILE>;
close FILE or die "Error: can't close file $! \n";

my %table;
my $j = 0;
my ($que, $host, $port, $trash);
for (my $i = 0; $i <= $#aix; $i++) {
        if ( $j == 0 ){
                ($que, $trash) = split (/:/, $aix[$i]);
        } elsif ( $j == 3) {
                chomp($aix[$i]);
                $aix[$i] =~ s/ //g;
                ($trash, $host) = split (/=/, $aix[$i]);
                if ( $host !~ /circus.org/ )
                {
                        $host = sprintf ("%s.circus.org", $host);
                }
        } elsif ( $j == 6) {
                chomp($aix[$i]);
                ($trash, $port) = split (/=/, $aix[$i]);
        }  
        if ( $j == 6 ) {
                $table{$que} = {'host'=>$host, 'port'=>$port};
        }
        $j++;
        if ( $j == 9 ) {
                $j = 0;
        }
}

# The command to add a printer.
# system  lpadmin -p printer -E -v socket://host.circus.org -m laserjet.ppd.gz
# The command to remove a printer, got to be able to back it out.
# lpadmin -x printer
foreach $key (keys(%table)) {
        print "$key $table{$key}->{host} $table{$key}->{port}\n";

        my $socket = sprintf ("socket://%s", $table{$key}->{host});

        # Swap these two commands if you need to delete.        
        #my @args = ("lpadmin", "-x", "$key");
        my @args = ("lpadmin", "-p", "$key", "-E", "-v", "$socket", "-m", "laserjet.ppd.gz" );

        system(@args) == 0
        or die "system @args failed: $?";
        sleep 1;
}

This entry was posted in Linux. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s