Gestor de Impresión 2.1

Introducción

Se trata de un sistema para dar servicio a varias impresoras en varias sedes y que desde cualquiera de elles se pueda imprimir el trabajo enviado desde otra, ejemplo un alumno hace un documento y lo envia a imprimir en la sede de ICAI, pero no tiene tiempo y decide 2h mas tarde irse a ICADE he imprimirlo alli.Una descripción de lo que hace el trabajo desde que lo envia , hasta que lo imprime, da mas detalles de que compone el sistema completo; El alumno entra en sesion en el pc, los scripts de inicio le conectan la impresora con un controlador generico postscript de nivel 2(las pruebas se han hecho con la Apple Laser 660/12 PS), el alumno manda un trabajo a imprimir, que es recogido en el servidor por smb, guardando su información en una base de datos y el archivo postscript nivel 2 (PS) en su disco.Cuando el alumno va a recoger su documento en el cliente-X, se valida con su usuario y contraseña, el servidor comprueba los trabajos pendientes en la base de datos para ese usuario, mostrando la lista de trabajos imprimibles, el alumno selecciona el trabajo o trabajos que quiera imprimir, el servidor busca el archivo (en la ruta del archivo indica en que sede esta el archivo) y se lo manda a la impresora seleccionada.

Sistema

El sistema consta de varios elementos el principal es el servidor central en el que reside la base de datos , los sistemas servodor satelite que guardan los trabajos de las sedes y los clientes-X desde los que el alumno decide que y donde imprime. Acontinuacion se describe con detalle cada uno de los elementos que componen el sistema total.

Servidor Central

En esta maquina se almacena la base de datos central (postgres), el acceso desde maquinas windows a linux(samba),las impresoras del sistema central (cups) y el interfaz web para la sede central(apache/php) es el sistema central y a el se conectan todos los servidores satelites, los clientes windows de la sede central y los clientes-X de la sede central.

SO

El sistema central esta montado con una GNU/Linux debian sid con una instalación base con los siguiente spaquetes adicionales: Apache-ssl Php4 Postgres Samba Winbind Cups Kerberos NFS Libdb_perl_pg Perl Ssh Kernel 2.6-test9

Validación

La validación de los clientes para acceder a las impresoras se realiza contra el directorio activo con samba. Para ello hay que configurar kerberos en el realm del dominio para ello ejecutamos: dpkg-reconfigure krb4-config nos preguntara el realm, en nuestro caso alumnosupco.es No contienen entradas en nuestro DNS Los servidores de nuestro realm “hecate.alumnosupco.es menthe.alumnosupco.es priapus.alumnosupco.es anius.alumnosupco.es” El servidor central en nuestro caso “hecate .alumnosupco.es”

Configuración de los modulos pam para que validen samba contra kerberos:

/etc/pam.d/samba
auth            required                pam_unix.so nullok
auth            sufficient              pam_winbind.so  #(es suficiente que la clave se valide en el realm kerbedos con winbind)
account         sufficient              pam_winbind.so  #(es suficiente que exista el usuario en el winbind (domino win2k))
account         required                pam_unix.so
session         required                pam_unix.so
password                required                pam_unix.so

Configuración de Samba para validar contra el ADS

Lo que hace es validar contra el ADS por kerberos, el problema es que no existen todos los usuarios en el sistema asi que se utiliza winbind para crear ususarios virtuales los parámetros “idmap uid” y “idmap uid” dan el rango de identificadores de usuario y grupo que se asignan a estos usuarios virtuales, ha de ser lo suficiente mente grande para que cada usuario del dominio tenga el suyo.

# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         compat winbind          (busca las claves en el winbind)
group:          compat winbind          (busca los grupos en el winbind)
shadow:         compat

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

/etc/samba/smb.conf

global?
    workgroup = alumnos
    server string = %h server (Samba %v)
    load printers = yes
    printcap = /etc/printcap.cups
    printing = lprng
    invalid users = root
    log file = /var/log/samba/log.%m
    max log size = 1000
    syslog = 0
#
#       Validación contra el ADS
#
    realm = ALUMNOS             #(realm del ADS)
    security = ADS              #(seguridad ADS)
    encrypt passwords = true            #(claves encriptadas)
    password server = SERVIDOR  #(servidor donde valida las claves)
#
#
    socket options = TCP_NODELAY
    dns proxy = no
    passwd program = /usr/bin/passwd %u
    passwd chat = Enter\snew\sUNIX\spassword: %n\n Retype\snew\sUNIX\spassword: %n\n .
    message command = /bin/sh -c '/usr/bin/linpopup "%f" "%m" %s; rm %s' &
    obey pam restrictions = yes
#
#       Configuracion winbind
#
    idmap uid = 10000-200000            #(rango de identificadores de usuario)
    idmap gid = 10000-200000            #(rango de identificadores de grupo)
#

    printer admin = ALUMNOS\ivan
   create mask = 0775
    unix charset = UTF-8
printers?
   comment = All Printers
   browseable = yes
   path = /tmp/local
   printable = yes
   print command = /etc/samba/printcmd.pl %p %s %m %U "%J"   2> /tmp/logsmb
   public = yes
print$?
    path = /etc/samba/print
    browseable = yes
    read only = yes
    write list = ALUMNOS\ivan
    guest ok = yes
admin?
    path = /etc/samba
    browseable = no
    valid users = alumnos\ivan
validar?
    read only = yes
    browseable = no
    path = /home/null

tras esto hay que añadir al dominio al equipo con “net join -U administrador” y ejecitar “kinit USUARIO@DOMINIO” para inicializar kerberos

Otra opcion para la validacion es cambiar en el smb.conf ADS por DOMAIN, en este caso no hace falta configurar kerberos

Base de Datos

La base de datos elegida ha sido postgres. Contiene las liguientes tablas:

trabajos_en_cola
trabajos_impresos
ultimos_impresos
impresora_clientex
impresoras
sedes
aulas

Los trabajos se guardan inicialmente en trabajos_en_cola una vez son impresos pasan a ultimos_impresos (donde se guardan los 10 ultimos) y a trabajos_impresos.


Validación

para hacer las consultas contra la base de datos se hace con usuario y contraseña para ello hay que modificar el fichero /etc/postgres/pg_hba.conf

local   all         postgres                                        ident sameuser
local   all         all                                             md5
host    all         all         127.0.0.1         255.255.255.255   md5
host    all         all         0.0.0.0           0.0.0.0   reject

Mantenimiento

Por la noche a las 00:00 se ejecutan 2 procesos en todos los servidores /etc/samba/borrado_nocturno.pl que borra los registros de trabajos_en_cola y /etc/init.d/dir_colas.sh restart que borra todos los ficheros PS /etc/samba/borrado_nocturno.pl

#!/usr/bin/perl -w

sub consulta{
    $db=shift;
    $sql=shift;

    print("consulta: ".$sql."\n");

    my $sth = $db->prepare($sql);
    $sth->execute;
    $sth->finish;
}

use DBI;            # Load the DBI module

my $dbh = DBI->connect( "dbi:Pg:dbname=spool", "consulta", "consulta" )
    or die "No se ha podido conectar a la base de datos: $DBI::errstr\n";

consulta($dbh,"delete from trabajos_en_cola");

$dbh->disconnect
    or warn "La desconexion ha fallado: $DBI::errstr\n";

base de datos en SQL


Samba

Samba se uiliza para poder compartir archivos y impresoras entre linux y windows, nos permite que los clients windows se conecten a las impresoras del servidor, tambien lo utilizamos para validar desde la web(ver interfaz web). El fichero de configuración ha sido pues to antes nos valos a centrar en X partes El dominio en el que estamos

workgroup = alumnos

Que carge todas las impresoras desde el fichero /etc/printcap.cups

load printers = yes

printcap = /etc/printcap.cups

Que la impression sea de tipo lprng para poder especificar el commando con el que se imprime (ver mas adelante printcmd.pl)

printing = lprng

Juego de caracteres que utilizamos para los nombres de archivos

unix charset = UTF-8

Opciones de todas las impresoras , que el camino a los ficheros PS sea /tmp/local y que el comando de impresión sea “= /etc/samba/printcmd.pl IMPRESORA FICHERO_PS EQUIPO USUARIO NOMBRE_DEL_TRABAJO ”

printers?
   comment = All Printers
   browseable = yes
   path = /tmp/local
   printable = yes
   print command = /etc/samba/printcmd.pl %p %s %m %U "%J"   2> /tmp/logsmb
   public = yes

Recurso para la gestion de las impresoras accessible de lectura para todo el mundo (para que se puedan instalar los drivers) y de escritura solo para los administradores

print$?
    path = /etc/samba/print
    browseable = yes
    read only = yes
    write list = ALUMNOS\ivan
    guest ok = yes

Recurso oculto para validar la parte de administracion del interfaz web, solo accessible por los administradores.

admin?
    path = /etc/samba
    browseable = no
    valid users = alumnos\ivan

Recurso oculto para la validación de los usuarios en el interfaz web, accesible a todo el mundo que tenga cuenta en el dominio

validar?
    read only = yes
    browseable = no
    path = /home/null

Comando printcmd.pl

El script recibe la impresora,fichero(PS),maquina,usuario y nombre del trabajo, estos datos son utilizados para contar las paginas, comprobar que el postscript sea de nivel 2 e imprimir el archivo si la impresora esta despausada o encolarlo si esta pausada (nota si se despausa una impresora y tiene documentos encolados estos seguiran pausados aunque los nuevos trabajo empezaran a imprimirse según se enbien). Para la conexión a la base de datos se utiliza un modulo de perl para acceso a baes de datos postgres DBI:pg. Para meros importantes del fichero que deben ser revisados:

$sede="ICADE";

(indica la sede en la que estamos imprimiendo y con ella el servidor central encontrara la ruta al fichero PS /tmp/$sede/fichero_PS )

$srvdb="127.0.0.1";

(indica el servidor que contiene la base de datos en los servidores satelite sera el servidor principal, en el servidor central sera el mismo)

#!/usr/bin/perl

sub consulta{
    $db=shift;
    $sql=shift;

    print("consulta: ".$sql."\n");

    my $sth = $db->prepare($sql);
    $sth->execute;
    $sth->finish;
    return @ary_ref = $sth->fetchrow_array;
}

sub insercion{
    $db=shift;
    $sql=shift;

    print("consulta: ".$sql."\n");

    my $sth = $db->prepare($sql);
    $sth->execute;
    $sth->finish;
    return $sth;
}

sub parsear{
    $cadena=shift;
#    $cadena= s/\b//g;
#    $cadena= s/\s//g;
#    $cadena= s/microsoftpowerpoint-/""/g;
#    $cadena= s/microsoftword-/""/g;
#    $cadena= s/microsoftexcel-/""/g;
#    $cadena= s/microsoftaccess-/""/g;
    $cadena= s/\200/c/g;
    $cadena= s/\207/c/g;
    $cadena= s/\230//g;
    $cadena= s/\233//g;
    $cadena= s/\234//g;
    $cadena= s/\235//g;
    $cadena= s/\236/f/g;
    $cadena= s/\237/l/g;
    $cadena= s/\250/"?"/g;
    $cadena= s/\251//g;
    $cadena= s/\252//g;
    $cadena= s/\40//g;
    $cadena= s/\253/"1:2"/g;
    $cadena= s/\254/"1:4"/g;
    $cadena= s/\255/"<A1>"/g;
    $cadena= s/\256/"<"/g;
    $cadena= s/\257/">"/g;
    $cadena= s/\341/a/g;
    $cadena= s/\203/a/g;
    $cadena= s/\216/a/g;
    $cadena= s/\217/a/g;
    $cadena= s/\240/a/g;
    $cadena= s/\246/a/g;
    $cadena= s/\351/e/g;
    $cadena= s/\202/e/g;
    $cadena= s/\210/e/g;
    $cadena= s/\211/e/g;
    $cadena= s/\212/e/g;
    $cadena= s/\220/e/g;
    $cadena= s/\221/ae/g;
    $cadena= s/\222/ae/g;
    $cadena= s/\355/i/g;
    $cadena= s/\241/i/g;
    $cadena= s/\363/o/g;
    $cadena= s/\242/o/g;
    $cadena= s/\223/o/g;
    $cadena= s/\224/o/g;
    $cadena= s/\225/o/g;
    $cadena= s/\231/o/g;
    $cadena= s/\242/o/g;
    $cadena= s/\247/o/g;
    $cadena= s/\372/u/g;
    $cadena= s/\226/u/g;
    $cadena= s/\227/u/g;
    $cadena= s/\232/u/g;
    $cadena= s/\374/u/g;
    $cadena= s/\201/u/g;
    $cadena= s/\232/u/g;
    $cadena= s/\243/u/g;
    $cadena= s/\361/n/g;
    $cadena= s/\244/n/g;
    $cadena= s/\245/n/g;
    $cadena= s/\301/A/g;
    $cadena= s/\311/E/g;
    $cadena= s/\315/I/g;
    $cadena= s/\323/O/g;
    $cadena= s/\332/U/g;
    $cadena= s/\321/\361/g;
    $cadena= s/\321/N/g;
    $cadena = lc $cadena;
    return $cadena;
}

sub paginas {
    my $fichero = shift;
    my $n=0;
    my $level=0;
#    return `grep -c \"%%\\0?;
$fichero=$sede."/".$ARGV1?;
$maquina=$ARGV2?;
$usuario=$ARGV3?;
$usuario  s/.*_//;
$nombre=$ARGV4?;
qx(echo $nombre > /tmp/prueba);
$paginas=paginas("/tmp/".$fichero);
$srvdb"127.0.0.1";


#
#       conexion a la BD
#
use DBI;            # Load the DBI module
use Time::localtime;

# formato de fecha SQL
my $fecha=localtime->mday() . "/" . (localtime->mon()+1) . "/" .(localtime->year() + 1900);
my $hora=localtime->hour .":".localtime->min.":".localtime->sec;

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
my $tam=$size;
my $dbh = DBI->connect( "dbi:Pg:dbname=spool;host=$srvdb", "consulta", "consulta" )
    or die "No se ha podido conectar a la base de datos: $DBI::errstr\n";
#
#       Anyade las impresoras que no existen a la base de datos
#

#$sth = consulta($dbh,"select * from impresoras where nombre='".$impresora."'");

@linea = $dbh->selectrow_array("select count(id) as num from impresoras where nombre='".$impresora."'");
print("Impresora: ".$linea"num"?."\n");
if($linea"num"?<0){
    insercion($dbh,"insert into impresoras (nombre,descripcion,id_aula,id_sede) values ('".$impresora."','Sindefinir',1,1)");
    }
#permisos del fichero para poder ser accedido por www-data

qx(/bin/chmod ugo+rw /tmp/$fichero 2>/tmp/logprintcmd);

#impresion del fichero ala vieja usanza
$consulta="select count(id) as num from impresoras where ( \"nombre\"='".$impresora."' ) and ( pausada=false );\n";
@linea = $dbh->selectrow_array($consulta);
print($consulta);
print("Impresora ".$impresora." activa: ".$linea"num"?."\n");
if($linea"num"?>0){
    print("impreso\n");
    if(!$paginas){$paginas=0;}
    insercion($dbh,"insert into trabajos_impresos (usuarios,fichero,nom_fich,paginas,impresora,hora,fecha,equipo) values ('".$usuario."','".$fichero."','".$nombre."',".$paginas.",'".$impresora."','".$hora."','".$fecha."','".$maquina."');");
    qx(lpr -U$usuario -P$impresora -r -J"($paginas)$nombre" /tmp/$fichero);
    }
else {
    print("encolado\n");
#
#       Anyade los trabajos a la cola
#
    if(!$paginas){$paginas=0;}
    insercion($dbh,"insert into trabajos_en_cola (usuarios,fichero,nom_fich,paginas,impresora,hora,fecha,equipo) values ('".$usuario."','".$fichero."','".$nombre."',".$paginas.",'".$impresora."','".$hora."','".$fecha."','".$maquina."');");
    }


$dbh->disconnect
        or warn "La desconexion ha fallado: $DBI::errstr\n";

Cups

Es el programa servidor de impresión que se encarga de enviar nuestros trabajos a las impresoras se configura accediendo a las dirección http://equipo:631 por defecto lo tenemos limitado a los servidores se configura en el fichero /etc/cups/ estas dos partes son las que nos interesan:

<Location />
Order Deny,Allow
Deny From All
Allow From 127.0.0.1
#ip de la maquina que tienen que acceder al cups
Allow From 192.168.1.100
</Location>

<Location /admin>
AuthType? Basic
AuthClass? System

## Restrict access to local domain
Order Deny,Allow
Deny From All
Allow From 127.0.0.1
#ip de la maquina que tienen que acceder al cups
Allow From 192.168.1.100

#Encryption Required
</Location>

<Location /jobs>
Order Deny,Allow
Deny From All
Allow From 127.0.0.1
#ip de la maquina que tienen que acceder al cups
Allow From 192.168.1.100
</Location>

los usuarios que queramos que puedan acceder a cups deben ser creados en la maquina y pertenecer al grupo lpadmin. para mas informacionde cups http://www.cupsys.org

Interfaz Web

Esta hecha entera en php4 con variables de sesión, valida mediante una conexión con smbclient a un recurso samba local oculto, si esta tiene éxito deja acceder en caso contrario no. Interfaz de usuario El alumno debe introducir su ususario y contraseña para poder entrar en el gestor de impresión.

El gestor mostrará al usuario validado los trabajos pendiente que tenga; para imprimirlos bastará con que pulse en el boton imprimir o seleccionando los trabajos a imprimir y pulsando en “imprimir selección”. Para borrar un trabajo pulsamos en el boton borrar. El boton previo mostrará una versión preliminar de lo que se haya seleccionado. “Imprimir Todos” imprimira todos los documentos. “Borrar todos“ borrara todos los trabajos del usuario. “Salir” vuelve a la pagina de validación.

Tras mandar a imprimir uno o varios trabajos se mostrara un formulario en el que se podra seleccionar la impresora a la que se quieran mandar los trabajos (esta se selecciona de entre las impresoras no pausadas y que se puedan imprimir desde ese clienteX) “Salir” vuelve a la pagina de validación. “Atras” vuelve a la pantalla anterior.

Una vez se ha impreso el documento nos muestra el mensaje de que ha sido impreso y nos devuelve a nuestros trabajos. “Salir” vuelve a la pagina de validación.

Interfaz de administración

El usuario debe haber sido dado de alta en /etc/samba/smb.conf en el recurso admin. Para que pueda acceder a l interfaz de administración.

Colas

Los trabajos PS estan en /tmp, los enviados al equipo local estan en /tmp/local y en /tmp/SEDE_LOCAL los de cada sede estan en /tmp/SEDE (donde SEDE_LOCAL y SEDE son los nombres de las sedes) estos ultimos se montan por NFS del equipo local y de las sedes para ellos al inicio se arranca un script (/etc/init.d/dir_colas.sh) que crea los directorios para cada cola y monta el directorio /tmp/local de cada sede . /etc/exports

# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
/tmp/local  192.168.1.100(rw,sync) 192.168.1.101(rw,sync)

/etc/init.d/dir_colas.sh

#!/bin/sh

case "$1" in
  start)
    echo "Iniciando directorios de colas"
    mkdir /tmp/SEDE1 /tmp/SEDE2 /tmp/SEDE3 /tmp/SEDE4 /tmp/SEDE5 /tmp/local
    chmod ugo+rwx /tmp/SEDE1 /tmp/SEDE2 /tmp/SEDE3 /tmp/SEDE4 /tmp/SEDE5 /tmp/SEDE6 /tmp/local
    /etc/init.d/nfs-kernel-server restart
    mount -t nfs 192.168.1.100:/tmp/local /tmp/SEDE1 -o rw,users
    mount -t nfs 192.168.1.101:/tmp/local /tmp/SEDE2 -o rw,users
#    mount -t nfs 192.168.1.102:/tmp/local /tmp/SEDE3 -o defaults,rw,users
#    mount -t nfs 192.168.1.103:/tmp/local /tmp/SEDE4 -o defaults,rw,users
#    mount -t nfs 192.168.1.104:/tmp/local /tmp/SEDE5 -o defaults,rw,users
    ;;

  stop)
    echo "Parando Directorios de colas"
    umount /tmp/SEDE1
    umount /tmp/SEDE2
    umount /tmp/SEDE3
    umount /tmp/SEDE4
    umount /tmp/SEDE5
    rm -fr /tmp/SEDE1 /tmp/SEDE2 /tmp/SEDE3 /tmp/SEDE4 /tmp/SEDE5 /tmp/local
    ;;

  restart)
    $0 stop
    $0 start
    ;;
  *)
    echo "Usage: /etc/init.d/$NAME {start|stop|reload|reload-modules|force-reload|restart}"
    exit 1
    ;;
esac

Servidores Satelite

Samba

$srvdb="127.0.0.1";</pre> (indica el servidor que contiene la base de datos en los servidores satelite sera el servidor principal, en el servidor central sera el mismo)
Ver servidor central

!!Cups
Ver servidor central

!!Interfaz Web
Ver servidor central

!!Colas
Ver servidor central

!!Clientes X
!!Validación
Se ha modificado el /etc/inittab  para que al inicio de sesión inicie una Xwindow con el usuario dummy, se han deshabilitado todas las lerminales menos la 6, en la terminal 2 estan las X.

!!SO
GNU/Linux debian sid con una instalacion base mas los siguientes paquetes:
<pre>
xwindow
olwm
mozilla
gv
kernel 2.4-22
Xwindow

Al entrar en las X se borra la condiguracion de mozilla se restaura de un fichero y se arranca mozilla con la pagina web del gestor de impression por https, se arranca olwm como gestor de ventanas por ser el mas sencillito de los que se han probado. Se ha habilitado solo el boton izq del raton para que no salgan los menus del boton der ni en mozilla ni en el gestor de ventanas.

/.xinitrc
XF86Config
Mozilla

Se ha modificado el prefs.js para que no aparecan las barras de menu y navegacion de mozilla. Prefs.js

Con impresora local

Debe añadirse cups a la instalación y configurar la impresora local