SafeChildren Banner

Havoc Oracle Solaris Experts

viernes, 26 de febrero de 2010

Manejo de Project y Configuraciones Dinámicas en Solaris 10 - Parte 2

Introducción
Hasta ahora hemos visto cómo gestionar los parámetros dinámicamente mediante el uso de <prctl> y project sin embargo, Cómo saber si se están superando los límites? Bien, para ello, tenemos el comando <rctladm> que nos permite examinar y modificar los parámetros globales de nuestro sistema de control de recursos.

Vamos a utilizar <rctladm> para habilitar el sistema de log y de esta forma, poder ver cuándo y quién está sobrepasando los límites que hemos asignado.

Si ejecutamos el comando <rctladm> sin ningún argumento, se nos mostrará el estado de cada una de las opciones del resource manager donde podremos ver si tenemos activado el sistema de log <syslog=notice> o, si por el contrario está apagado <syslog=off> -que es su valor por defecto-
# rctladm
process.max-port-events     syslog=off     [ deny count ]
process.max-msg-messages    syslog=off     [ deny count ]
process.max-msg-qbytes      syslog=off     [ deny bytes ]
process.max-sem-ops         syslog=off     [ deny count ]
process.max-sem-nsems       syslog=off     [ deny count ]
process.max-address-space   syslog=off     [ lowerable deny no-signal bytes ]
process.max-file-descriptor syslog=notice  [ lowerable deny count ]
process.max-core-size       syslog=off     [ lowerable deny no-signal bytes ]
process.max-stack-size      syslog=off     [ lowerable deny no-signal bytes ]
process.max-data-size       syslog=off     [ lowerable deny no-signal bytes ]
process.max-file-size       syslog=off     [ lowerable deny file-size bytes ]
process.max-cpu-time        syslog=off     [ lowerable no-deny cpu-time inf seconds ]
task.max-cpu-time           syslog=off     [ no-deny cpu-time no-obs inf seconds ]
task.max-lwps               syslog=notice  [ count ]
project.max-contracts       syslog=off     [ no-basic deny count ]
project.max-device-locked-memory syslog=off     [ no-basic deny bytes ]
project.max-locked-memory   syslog=off     [ no-basic deny bytes ]
project.max-port-ids        syslog=off     [ no-basic deny count ]
project.max-shm-memory      syslog=off     [ no-basic deny bytes ]
project.max-shm-ids         syslog=off     [ no-basic deny count ]
project.max-msg-ids         syslog=off     [ no-basic deny count ]
project.max-sem-ids         syslog=off     [ no-basic deny count ]
project.max-crypto-memory   syslog=off     [ no-basic deny bytes ]
project.max-tasks           syslog=off     [ no-basic count ]
project.max-lwps            syslog=off     [ no-basic count ]
project.cpu-cap             syslog=off     [ no-basic deny no-signal inf count ]
project.cpu-shares          syslog=n/a     [ no-basic no-deny no-signal no-syslog count ]
zone.max-swap               syslog=off     [ no-basic deny bytes ]
zone.max-locked-memory      syslog=off     [ no-basic deny bytes ]
zone.max-shm-memory         syslog=off     [ no-basic deny bytes ]
zone.max-shm-ids            syslog=off     [ no-basic deny count ]
zone.max-sem-ids            syslog=off     [ no-basic deny count ]
zone.max-msg-ids            syslog=off     [ no-basic deny count ]
zone.max-lwps               syslog=off     [ no-basic count ]
zone.cpu-cap                syslog=off     [ no-basic deny no-signal inf count ]
zone.cpu-shares             syslog=n/a     [ no-basic no-deny no-signal no-syslog count ]
Para activar el sistema de log simplemente deberemos ejecutar el siguiente comando
rctladm -e syslog __nombre.propiedad__
Y para desactivar el sistema de log
rctladm -d syslog __nombre.propiedad__
Como siempre, si intentamos hacerlo desde la zona no global Solaris nos mostrará el siguiente error:
# rctladm -e syslog project.max-port-ids
rctladm: unable to update control block contents: Not owner
De esta forma, cada vez que un recurso supere los límites que hemos definido -y esté activo el log- nos escribirá una entrada en </var/adm/message> de la zona global, indicando propiedad y límite superado
# tail -f /var/adm/messages
Feb 23 18:11:32 test genunix: [ID 120576 kern.notice] basic rctl process.max-file-descriptor (value 256) exceeded by process 323.
Veamos un ejemplo completo. Vamos a limitar el número de procesos ligeros que Apache HTTP Server puede crear, vamos a permitir sólo 5
# projmod -sK 'task.max-lwps=(priv,3,deny)' user.www
# /opt/www/apache-1.3.41/bin/apachectl stop
# /opt/www/apache-1.3.41/bin/apachectl start
# dmesg|tail

Feb 23 17:51:53 test genunix: [ID 748619 kern.notice] privileged rctl task.max-lwps (value 3) exceeded by process 24512 in task 32260.
Feb 23 17:51:57 test genunix: [ID 748619 kern.notice] privileged rctl task.max-lwps (value 3) exceeded by process 24526 in task 32260.
Feb 23 17:51:58 test genunix: [ID 748619 kern.notice] privileged rctl task.max-lwps (value 3) exceeded by process 24533 in task 32260.
Como hemos visto en otras ocasiones, podemos modificar los valores de un proceso en ejecución sin tener que reiniciarlo, vamos a modificar el valor de max-lwps del PID 24582
# ps -u www -f
     UID   PID  PPID   C    STIME TTY         TIME CMD
     www 24582 24577   0 17:52:14 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
     www 24581 24577   0 17:52:14 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
     www 24579 24577   0 17:52:14 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
     www 24580 24577   0 17:52:14 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
     www 24691 24577   0 17:54:20 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
     www 24578 24577   0 17:52:14 ?           0:00 /opt/www/apache-1.3.41/bin/httpd
# prctl -n task.max-lwps -i process 24582
process: 24582: /opt/www/apache-1.3.41/bin/httpd
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
task.max-lwps
        privileged        250       -   deny                                 -
# prctl -r -t priv -n task.max-lwps -v 350 -i process 24582
# prctl -n task.max-lwps -i process 24582
process: 24582: /opt/www/apache-1.3.41/bin/httpd
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
task.max-lwps
        privileged        350       -   none                                 -

<< Configuraciones Dinámicas Parte 1

Conclusión
Poco a poco vamos avanzando en el uso de Resource Manager y vemos como podemos aplicarlo a nuestras instalaciones. Os dejo que hagáis vuestras pruebas y ver cómo se comporta.

Referencias

miércoles, 24 de febrero de 2010

Cómo saber el PID del proceso actual

Introducción
Para saber el PID del proceso actual, simplemente debemos utilizar la variable de $$, así que si hacemos un <echo $$> nos devolverá el PID de nuestro Shell
$ ps -f -u postgres |grep bash|grep -v grep
postgres  4518  3433   0 20:36:59 pts/7       0:00 -bash
$ echo $$
4518

Referencias

lunes, 22 de febrero de 2010

Número de descriptores de ficheros abiertos en Solaris 10

Introducción
Por defecto, Solaris viene con una configuración muy conservadora, y por lo tanto, debemos ajustar algunos parámetros, entre ellos, el número máximo de descriptores de ficheros.

Este parámetro antiguamente había que declararlo en el archivo </etc/system> y requería un reboot del sistema para que se aplicara.

En Solaris 10 esto ya no es necesrio y se puede gestionar con una propiedad del proceso <process.max-file-descriptor> y, por lo tanto gestionable en caliente. Ya hemos visto en post anteriores como Gestionar Dinámicamente Parámetros en Solaris 10, pues bien, ahora vamos a ver otra aplicación del comando <prctl>

Para aquellos que tengaís Solaris 9 u 8, para poder definir el número máximo de descriptores permitidos hay que declarar las siguientes variables en el archivo de configuración </etc/system>. Recordar que este archivo es muy importante, y si tiene errores sintácticos Solaris NO Arrancará, así que editarlo con cuidado y recordar que los comentarios empiezan con "*" y no con "#"


Solaris 8 y 9

# vi /etc/system
  *
  * rflim_fd_max
  *       Limite de descriptores maximos de archivos abiertos
  *       por defecto: 1024
  *
  set rlim_fd_max=16384

  *
  * rlim_fd_cur
  *       por defecto: 64
  *
  set rlim_fd_cur=8192

:wq
Solaris 10
Ya hemos dicho que en Solaris 10 debemos utilizar <prctl> para gestionar estos parámetros dinámicos del sistema -si queremos podemos incluirlos en el /etc/system-
# echo $$
3433
# ulimit -a
core file size        (blocks, -c) unlimited
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
open files                    (-n) 8192
pipe size          (512 bytes, -p) 10
stack size            (kbytes, -s) 8192
cpu time             (seconds, -t) unlimited
max user processes            (-u) 29980
virtual memory        (kbytes, -v) unlimited
# prctl -r -t privileged -n process.max-file-descriptor -v 1024 -i process 3433
# ulimit -a                                                                   
core file size        (blocks, -c) unlimited
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 10
stack size            (kbytes, -s) 8192
cpu time             (seconds, -t) unlimited
max user processes            (-u) 29980
virtual memory        (kbytes, -v) unlimited
Hemos utilizado el comando <prctl> para modificar el valor de descriptores máximos permitidos al proceso 3433. Ahora bien, si queremos que la configuración se aplique a un conjunto de procesos, utilizaremos un project e incluiremos la propiedad en la definición.

Por ejemplo, para permitir que el usuario postgres tenga 1024 descriptores de archivos, haremos lo siguiente -asumimos que existe un project para el grupo postgres:
# projmod -sK 'process.max-file-descriptor=(priv,1024,deny)' group.postgres                                                                         
# su - postgres

POSTGRES VERSION: 8.4
POSTGRES HOME   : /u01/app/postgres/8.4/db
PGDATA          : /var/postgres/8.4/data
PGARCH          : 64

$ ulimit -a
core file size        (blocks, -c) unlimited
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 10
stack size            (kbytes, -s) 8192
cpu time             (seconds, -t) unlimited
max user processes            (-u) 29980
virtual memory        (kbytes, -v) unlimited

Conclusión
Hemos visto como editando el archivo </etc/system> se puede tunear muchos límites que en la versión inicial de Solaris debemos mejorar. Además si todavía eres de los que no ven claro los project y la configuración dinámica aquí tienes una excusa nueva para, poco a poco, enamorarte de esta funcionalidad.


Referencias

viernes, 19 de febrero de 2010

Actualizar Guest Additions de Virtual Box para Solaris 10

Introducción
Con cada nueva versión de VirtualBox, debemos instalar el paquete VBoxGuest que se encluye. Sin embargo, si intentamos hacerlo sin desinstalar la versión anterior, Solaris nos informará de que no es posible tener varias instalaciones del paquete y por ello debemos primero desinstalarlo.

Veamos un ejemplo del error que nos mostrará Solaris
# cd /cdrom/
bash-3.00# ls -l
total 10
lrwxrwxrwx   1 root     nobody        27 feb 18 22:34 cdrom0 -> ./vboxadditions_3.1.4_57640
drwxr-xr-x   2 root     nobody       512 dic  1 23:10 vboxadditions_3.1.0_55467
drwxr-xr-x   2 root     nobody       512 ene 10 12:29 vboxadditions_3.1.2_56127
dr-xr-xr-x   2 root     sys         2048 feb 12 20:32 vboxadditions_3.1.4_57640
# cd vboxadditions_3.1.4_57640/
# pkgadd -G -d VBoxSolarisAdditions.pkg

The following packages are available:
  1  SUNWvboxguest     Sun VirtualBox Guest Additions
                       (i386) 3.1.4,REV=r57640.2010.02.12.20.26

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]:all

Procesando versión del software desde

Sun VirtualBox Guest Additions(i386) 3.1.4,REV=r57640.2010.02.12.20.26

La administración actual precisa la creación de una única versión del
paquete . No obstante, ya se ha alcanzado el numero
máximo de versiones del paquete que pueden admitirse a la vez en el
mismo sistema.

No se hicieron cambios en el sistema.
Ahora, vamos a ver cómo podemos hacer la instalación de forma correcta. Para ello, primero debemos eliminar el paquete SUNWvboxguest y lo volveremos a instalar.
# pkgrm SUNWvboxguest

El siguiente paquete se está instalado en este momento:
   SUNWvboxguest  Sun VirtualBox Guest Additions
                  (i386) 3.1.1,REV=r56127.2009.12.17.13.24

?Quiere eliminar este paquete? [y,n,?,q] y

## Eliminando entrada de paquete instalado

Este paquete contiene archivos de comandos que serán ejecutados con
permiso de superusuario durante el proceso de instalación de este
paquete.

Quiere continuar con la eliminación de este paquete [y,n,?,q] y
## Verificando las dependencias del paquete en la zona global
## Procesando información del paquete.
## Ejecutando secuencia de pre-eliminación.
Sun VirtualBox Guest Additions - preremove script
This script will unload the VirtualBox Guest kernel module...
VirtualBox FileSystem kernel module not loaded.
VirtualBox guest kernel module unloaded.
Restoring X.Org...
Done.
## Borrar nombre de rutas de acceso en clase
## Borrar nombre de rutas de acceso en clase
...

...
...
## Actualizando información del sistema.

Quitar se hizo con éxito.
# pkgadd -G -d VBoxSolarisAdditions.pkg
The following packages are available:
  1  SUNWvboxguest     Sun VirtualBox Guest Additions
                       (i386) 3.1.4,REV=r57640.2010.02.12.20.26

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]: all


...
... mensajes de información de la instalación
... 
Por último, simplemente rebotaremos el sistema y ya tendremos la nueva versión. Para comprobar la nueva versión instalada utilizaremos el comando <pkginfo>
# pkginfo -l SUNWvboxguest
   PKGINST:  SUNWvboxguest
      NAME:  Sun VirtualBox Guest Additions
  CATEGORY:  application
      ARCH:  i386
   VERSION:  3.1.4,REV=r57640.2010.02.12.20.26
   BASEDIR:  /
    VENDOR:  Sun Microsystems, Inc.
      DESC:  VirtualBox Guest Additions for Solaris guests
    PSTAMP:  vboxguest20100212202648_r57640
  INSTDATE:  feb 18 2010 22:50
   HOTLINE:  Please contact your local service provider
     EMAIL:  info@virtualbox.org
    STATUS:  completely installed
     FILES:       51 installed pathnames
                   3 linked files
                   4 directories
                  18 executables
                   1 setuid/setgid executables
               16473 blocks used (approx)
Referencias

miércoles, 17 de febrero de 2010

Solaris Network Cache and Accelerator, Cache Web a Nivel de Kernel - Parte 1

Introducción
Solaris Network Cache and Accelerator (NCA) es un sistema de caché a nivel de kernel. Se encarga de mantener las páginas más accedidas a nuestro servidor web en memoria incrementando el rendimiento de nuestros servidores Web.

Actualmente los servidores que soportan este funcionamiento optimizado en Solaris -sin cambios- son: Apache incluido en Solaris, Sun Web Server y Zeus. El funcionamiento se basa en la modificación del tipo de socket AF_INET por AF_NCA. No quiero entrar en mucho detalle de su funcionamiento, pero se basa en el uso de memoria compartida y un sistema de acceso rápido.

Y qué pasa con los Apaches -compilados- por nosotros que no tienen soporte nativo para AF_NCA? No hay problema. Simplemente deberemos precargar la bilbioteca /usr/lib/libnca_addr.so antes de ejecutar nuestros servicios (para 32bits) y /usr/lib/64/ncad_addr.so para 64bits.

Como hemos comentado en otras ocasiones, para precargar una biblioteca simplemente exportaremos la variable de entorno LD_PRELOAD_32 o LD_PRELOAD_64

Activar NCA
Para activar NCA, simplemente deberemos editar los archivos /etc/nca/nca.if y /etc/nca/ncakmod.conf y reiniciar la máquina. Veamos los sencillos pasos, lo primero que debemos hacer, es activar los interfaces en los cuales NCA va a escuchar -en el archivo /etc/nca/nca.if-. Los interfaces deben tener el archivo /etc/hostname._interface_ creado y dado de alta en el archivo /etc/hosts
# vi /etc/nca/nca.if
ce0
:wq
# ls -ltr /etc/hostname.ce0
-rw-r--r--   1 root     root          16 oct 15 13:35 /etc/hostname.ce0
# vi /etc/nca/ncakmod.conf
 status=enabled
 httpd_door_path=/var/run/nca_httpd_1.door
 nca_active=disabled
:wq
El módulo NCA, por defecto escucha en el puerto 80, pero podemos definir los puertos -y las IPs- en los que queremos que lo haga editando el archivo /etc/nca/ncalogd.conf
# cat /etc/nca/ncaport.conf
 ncaport=*/80
 ncaport=*/8080
:wq
Por último, podemos activar -no es obligatorio- el sistema de Log, editando el archivo /etc/nca/ncalogd.conf y pondremos la variable status=enabled y reiniciaremos la máquina para que los cambios tengan efecto.
# vi /etc/nca/ncalogd.conf
 status=enabled
 logd_path_name="/var/nca/log"
 logd_file_size=1000000
:wq
# reboot
Conclusiones
En esta primera parte hemos visto cómo activar NCA es realmente sencillo. En las siguientes partes, veremos si el Caché a nivel de kernel, es una solución aplicable a nuestra arquitectura.

Es muy importante tener en cuenta que si activamos NCA, es muy recomendable -si tenemos un volumen muy elevado de peticiones- que la dediquemos exclusivamente como servicio Web, o al menos, que intentemos limitar el número de procesos  de kernel para evitar sustos.

Referencias

lunes, 15 de febrero de 2010

DBLinks en PostgreSQL

Introducción
Para aquellos que ya saben Qué es un DBLink pueden pasar al siguiente apartado. Para aquellos que no saben qué es, lo resumiremos como Un sistema que nos permite acceder de una base de datos a otra de forma transparente.

La idea es poder acceder desde la base de datos DB1 a los objetos de la base de datos DB2 de forma sencilla y transparente, pudiendo utilizar los comando SQL generales.

En Oracle haremos esto utilizando el símbolo "@" para hacer referencia a que la SQL pertenece a un base de datos remota.
 SQL> SELECT 1 FROM DUAL@OLTP2;

         1
----------
         1
En postgres es un poco diferente, principalmente porque el soporte para dblinks no está activado por defecto y debemos cargar el archivo dblink.sql que se encuentra en $POSTGRES_HOME/share/contrib/dblink.sql

Un ejemplo Completo
Vamos a crear dos base de datos -Test1 y Test2- y una tabla en cada una de ellas, con un registro de "Saludos desde Test1" -para Test1- y "Saludos desde Test2" -para Test2-. Posteriormente, haremos una consulta desde Test2 a la tabla de Test1 a traves de un dblink.
$ psql -U postgres
psql (8.4.0)
Digite ?help? para obtener ayuda.

postgres=# create database test;
CREATE DATABASE
postgres=# create database test2;
CREATE DATABASE
postgres=# \c test1
psql (8.4.0)
Ahora está conectado a la base de datos "test1".
test1=# create table test1(nombre character varying);
CREATE TABLE
test1=# insert into test1 values('saludos desde test1');
INSERT 0 1
test1=# \c test2
psql (8.4.0)
Ahora está conectado a la base de datos "test2".
test2=# create table test2(nombre character varying);
CREATE TABLE
test2=# insert into test2 values ('saludos desde test2');
INSERT 0 1
Una vez creada la estructura, vamos a cargar el soporte de dblink en la base de datos TEST2
$ psql -U postgres test2 -f $POSTGRES_HOME/share/contrib/dblink.sql
Una vez cargado, nos conectaremos a TEST2 y haremos la prueba de conexión -en nuestro caso no es necesario poner una contraseña, sin embargo, si es vuestro caso, simplemente deberemos incluir la cadena password=CONTRASEÑA en la conexión-
$ psql -U postgres test2
psql (8.4.0)
Digite ?help? para obtener ayuda.

test2=# select dblink_connect('dbname=test1');
 dblink_connect
----------------
 OK
(1 fila)

test2=# \q
Ya hemos dicho antes que en PostgreSQL es un poco diferente de Oracle, y uno de los cambios es que debemos informar a PostgreSQL de qué tipos son los resultados devueltos ya que sino -postgres- no será capáz de entender las cláusulas WHERE de la consulta SQL.

Por lo tanto, la recomendación -por parte de PostgreSQL- es crear una vista que sea la que realmente llame al DBLink y nosotros acceder a dicha vista de forma normal. El formato de la instrucción será el siguiente:
 SELECT *
        FROM dblink('dbname=NOMBREDB password=PASSWORD', 'SQL_A_EJECUTAR')
        AS t1(NOBRE_COLUMNA1 TIPO COLUMNA1, NOMBRE_COLUMNA2 TIPO_COLUMNA2, ...);
Así, siguiendo con nuestro ejemplo, vamos a crear una vista en la base de datos TEST2 que nos permitirá acceder a los datos de TEST1

test2=# select * from test2;
       nombre       
---------------------
 saludos desde test2
(1 fila)

test2=#  CREATE OR REPLACE VIEW test_view AS
test2-#       SELECT nombre
test2-#         FROM dblink('dbname=test1', 'select nombre from test1')
test2-#         as t1(nombre character varying);
CREATE VIEW
test2=# select * from test_view;
       nombre       
---------------------
 saludos desde test1
(1 fila)
Conclusión
El acceso a diferentes base de datos es un de las opciones más interesantes que podemos encontrar en el mundo SQL y PostgreSQL nos ofrece un sistema -aunque un poco extraño al principio- muy potente y flexible.

Referencias

viernes, 12 de febrero de 2010

Cómo Registrar los Accesos de SSH en Solaris

Introducción
En Solaris, por defecto, los registros de intentos de acceso mediante SSH no quedan registrados. Para poder registrarlos debemos modificar el valor de la variable de configuración <auth.notice> de <syslog>.

Para ello, editaremos el archivo de configuración /etc/syslog.conf y descomentaremos la entrada <auth.notice>
# vi /etc/syslog.conf
    auth.notice                    ifdef(`LOGHOST', /var/log/authlog, @loghost)
    # si queremos todos los niveles
   #auth.notice;auth.info;auth.debug                ifdef(`LOGHOST', /var/log/authlog, @loghost)
Una vez modificado, debemos recargar la configuración de nuestro syslogd de la siguiente forma
# pkill -HUP syslogd
Podemos consultar los intentos de accesos en el archivo</var/log/authlog> utilizando -por ejemplo- el comando <tail> o si queremos algo más avanzado LogWatch

Referencias

lunes, 8 de febrero de 2010

Manejo de Project y Configuraciones Dinámicas en Solaris 10 - Parte 1

Introducción
Una de las ventajas que nos ofrece Solaris en la Gestión Dinámica de Recursos -ya hemos hablado en otras ocasiones de esto como en Instalar varias Bases de Datos Oracle en la misma máquina- pero hoy vamos a ver con más detalle Cómo Gestionar Dinámicamente los valores de los Projectos.

Para ello, vamos a utilizar el comando <prctl> que nos va a permitir modificar y comprobar los valores que tenemos asignados por: project, task y pid.

Antes de empezar, debemos tener en cuenta que debemos conocer algunos conceptos básicos del manejo de projects como: Cómo saber cuál es el project actual, Cómo Ejecutar un proceso con un project diferente o Cómo cambiar el project de un proceso

La gestión de los recursos de nuestra máquina utilizando project nos ofrece una granualidad muy alta a la hora de expecificar: Memoria Máxima, Tiempo de CPU, Semáforos, etc. De esta forma, podemos ir ajustando las necesidades de nuestros procesos de forma dinámica.


Creación Project y Modificación Dinámica
Vamos a ver con un ejemplo, cómo podemos crear y modificar los valores de un project <en caliente> y cómo afecta al sistema. Lo primero que haremos será crear el project TEST.MIN con un valor de project.cpu-shares = 30 y luego, lo modificaremos a 100

# projadd -c 'Test Project' -G sysadmin -K 'project.cpu-shares=(privileged,200,none)' test.min
# cat /etc/project |grep test
test.min:102:Test Project::sysadmin:project.cpu-shares=(privileged,200,none)
Una vez creado, vamos a ejecutar nuestras operaciones utilizando este nuevo project -test.min-
# newtask -p test.min
# id -p
uid=0(root) gid=0(root) projid=102(test.min)
Como hemos comentado al principio, para poder modificar los valores de un project con una tarea en ejecución será necesario utilizar el comando <prctl> ya que, si utilizamos el comnado <projmod> estos cambios sólo se verán en las nuevas ejecuciones y no en las actuales. Veamos un ejemplo, para ello, vamos a obtener el valor de cpu-shares y posteriormente lo modificaremos con projmod y veremos cómo no se ha modificado. Por último, utilizaremos prctl para modificar el valor y comprobar cómo ahora si ha sido modificado.
# prctl -n project.cpu-shares -i pid 855
process: 855: prstat -J
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.cpu-shares
        privileged        200       -   none                                 -
# projmod -sK'project.cpu-shares=(privileged,60,none)' test.min
# prctl -n project.cpu-shares -i pid 855
process: 855: prstat -J
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.cpu-shares
        privileged        200       -   none                                 -
# cat /etc/project |grep test
test.min:102:Test Project::sysadmin:project.cpu-shares=(privileged,60,none)
Como podemos ver, el cambio utilizando el comando <projmod> no se ha visto reflejado sobre nuestro proceso <855> ya que está en ejecución.

Ahora, vamos a ver cómo utilizando <prctl> el cambio se ve reflejado en el proceso pero no en el archivo de configuración </etc/projects>
# prctl -r -t privileged -n project.cpu-shares -v 350 -i pid 855
# prctl -n  project.cpu-shares -i pid 855
process: 855: prstat -J
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.cpu-shares
        privileged        350       -   none                                 -
# cat /etc/project |grep test
test.min:102:Test Project::sysadmin:project.cpu-shares=(privileged,60,none)
En el ejemplo hemos modificado los valores para un pid en concreto, pero, la forma más habitual será hacer referencia al project para ello, deberemos utilizar el siguiente comando
prctl -r -t privileged -n project.cpu-shares -v 200 -i project test.min


Conclusiones
Podemos ver cómo con el uso de project y el comando prctl vamos a ajustar las necesidades de nuestro sistema de forma sencilla y rápida. Si a esto unimos el uso de pset y pools podemos tener un ajuste muy fino de los recursos asignados a cada proceso -project-

Os animo a investigar las opciones de prctl desde su man page y así poder explorar todas las opciones que nos aporta.

Referencias

miércoles, 3 de febrero de 2010

Gestión y Husos Horarios en Oracle

Introducción
El manejo de fechas es una de las tareas más tediosas que existen en cualquier sistema, y por supuesto, Oracle no será una excepción. Vamos a ver cómo podemos utilizar las herramientas de TimeZone <desplazamiento horario> que nos proporcionan.

Por defecto -y a no ser que cambiemos esta de forma consciente- Oracle define el desplazamiento de la base de datos como GMT+0, es decir, no se encuentra desplazada. De esta forma, es capáz de obtener las diferentes representaciones de las fechas en función de su desplazamiento.

Vamos a ver cómo podemos saber si tenemos configurada nuestra base de datos y cuál es su <dbtimezone>

SQL> SELECT dbtimezone FROM DUAL;

DBTIME
------
+00:00
Ahora bien, nuestro TimeZone estará formado por Continente/Ciudad -en la mayoría de los casos- y en el nuestro será <Europe/Madrid>, pero podemos obtener una lista de todos los TimeZone que Oracle conoce haciendo la siguiente consulta
SQL> SELECT DISTINCT tzname FROM V$TIMEZONE_NAMES ORDER BY 1;

TZNAME
----------------------------------------------------------------
Africa/Algiers
Africa/Cairo
Africa/Casablanca
Africa/Ceuta
Africa/Djibouti
Africa/Freetown
Africa/Johannesburg
Africa/Khartoum
Africa/Mogadishu
Africa/Nairobi
Africa/Nouakchott
...
... continúa ...
...
Bien, una vez introducido los principales elementos en el uso de husos horarios, vamos a ver cómo operar con ellos. Lo primero que haremos será obtener la fecha-hora del sistema

SQL> SELECT CURRENT_TIMESTAMP FROM DUAL;

CURRENT_TIMESTAMP
---------------------------------------------------------------------------
01/02/10 14:28:02,990759 +01:00

Ahora, vamos a ver esta hora como es representada en Arizona, es decir, qué hora es allí. Para ello, vamos a utilizar una función <TZ_OFFSET> que nos dará el desplazamiento horario respecto a nuestra base de datos -recordar que es GMT+0-

SQL> SELECT TZ_OFFSET('US/Arizona') FROM DUAL;

TZ_OFFS
-------
-07:00

Muchos podéis pensar que resto TZ_OFFSET a la hora y ya tengo la hora desplazada, ..., ummm, pues la verdad es que no. Más adelante veremos en qué circustancias eso no nos sirve.

Así que, la solución es utilizar la función <FROM_TZ> que nos permite convertir una Hora a un desplazamiento en concreto.

Continuando con el ejemplo, queremos saber la hora en US/Arizona
SQL> SELECT
  2  FROM_TZ( CAST(CURRENT_TIMESTAMP AS TIMESTAMP), 'Europe/Madrid') 
  3  AT TIME ZONE 'US/Arizona'AS Hora_Arizona
  4  FROM DUAL;

HORA_ARIZONA
---------------------------------------------------------------------------
01/02/10 06:38:39,705886 US/ARIZONA
También podemos hacer las variantes que queramos, por ejemplo, representar una Fecha-Hora de US/Arizona en nuestro desplazamiento Europe/Madrid

SQL> SELECT
  2  FROM_TZ(CAST(TO_DATE('1980-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'US/Arizona')
  3  AT TIME ZONE 'Europe/Madrid' AS Hora_Madrid
  4  FROM DUAL;

HORA_MADRID
---------------------------------------------------------------------------
01/01/81 07:59:59,000000 EUROPE/MADRID
Un poco más complejo
Como todos los años, volveremos a tener dos cambios de hora: Horario de Verano y Horario de Invierno. Bien, es aquí donde tendremos los problemas y por qué no podemos restar el valor de TZ_OFFSET a nuestra hora -principalmente porque tenemos que comprobar en que día estamos-. El 28 de Marzo a las 02:00h serán las 03:00h -en España- y por lo tanto habrá un período de tiempo en el cual, el desplazamiento no se corresponderá con el TZ_OFFSET -hasta que no se hagan los ajustes en aquellos países que realizan el cambio- pero, además, si es un país donde no se hacen cambios tendremos un TZ_OFFSET diferente para verano y otro para invierno.

Todos estos cálculos los realiza Oracle por nosotros, así que, vamos a utilizarlos. Veamos el ejemplo del 28 de Marzo con un desplazamiento de Africa/Mogadishu

SQL> SELECT TZ_OFFSET('Africa/Mogadishu') FROM DUAL;

TZ_OFFS
-------
+03:00

SQL> SELECT
1    FROM_TZ(CAST(TO_DATE('2010-03-28 01:00:00','YYYY-MM-DD
2    HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
3    AT TIME ZONE 'Africa/Mogadishu' AS Hora_Mogadishu
4    FROM DUAL;


HORA_MOGADISHU
---------------------------------------------------------------------------
28/03/10 03:00:00,000000 AFRICA/MOGADISHU

SQL> SELECT
1    FROM_TZ(CAST(TO_DATE('2010-03-28 03:00:00','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
2    AT TIME ZONE 'Africa/Mogadishu' AS Hora_Mogadishu
3    FROM DUAL;

HORA_MOGADISHU
---------------------------------------------------------------------------
28/03/10 04:00:00,000000 AFRICA/MOGADISHU
Como vemos en el ejemplo, el desplazamiento para Africa/Mogadishu es GMT+3, por lo tanto, si España es GMT+1, cabe pensar que añadiendo 2 horas se puede obtener la hora. Sin embargo, si nos fijamos con más detalle en la segunda SQL -cuando la hora es las 03:00h- en Mogadishu son las 04:00h y no las 05:00h. Esto se debe a que en España se ha cambiado de horario y en Mogadishu no se realiza ese cambio.

Además, según este esquema la en España la franja horaria 02:01:00h a 02:59:59h no existe -ya que a las 02:00h son las 03:00h- y si intentamos hacer cualquier cambio horario en esta franja, Oracle mostrará el siguiente error:

SQL> SELECT
  2  FROM_TZ(CAST(TO_DATE('2010-03-28 02:10:00','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
  3  AT TIME ZONE 'Africa/Mogadishu' AS Hora_Mogadishu
  4  FROM DUAL;
FROM_TZ(CAST(TO_DATE('2010-03-28 02:10:00','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
        *
ERROR at line 2:
ORA-01878: specified field not found in datetime or interval
Conclusiones
Realmente el manejo de Fechas y Horas en diferentes husos y desplazamientos horarios puede darnos muchos problemas. Por ello, es de vital importancia utilizar las funciones que nos proporciona Oracle y sobre todo, tener el sistema con los últimos parches de TZ disponibles.

Referencias

lunes, 1 de febrero de 2010

Desbloquear Cuenta Usuario Oracle

Introducción
Si tenemos activada la opción de bloqueo de cuentas en Oracle después de un número de intentos fallidos, al intentar conectarnos Oracle nos devolverá el error <ORA-28000 - Cuenta Bloqueada>. Para poder desbloquearla simplemente debremos utilizar la instrucción <ALTER USER> con la opción <ACCOUNT UNLOCK>

Veamos un ejemplo, primero bloquearemos la cuenta TEST y luego la desbloquearemos
$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.4.0 - Production on Wed Jan 27 17:22:08 2010

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Conectado a:
Oracle Database 10g Release 10.2.0.4.0 - 64bit Production

SQL>  ALTER USER TEST ACCOUNT LOCK;

Usuario modificado.

SQL> CONN TEST
Introduzca la contraseña:

ERROR: ORA-28000: la cuenta esta bloqueada
Advertencia: !Ya no esta conectado a ORACLE!

SQL> CONN / AS SYSDBA

SQL> ALTER USER TEST ACCOUNT UNLOCK;

Usuario modificado.

SQL> CONN TEST
Introduzca la contraseña:

Conectado.

SQL> QUIT

Referencias