sábado, 26 de octubre de 2013

Debian | Capacidad de discos y actualizaciones pendientes


Dos de las tareas más importantes para mantener un servidor disponible y seguro son:

  • Comprobar la capacidad de las particiones de los discos duros.
  • Comprobar si existen actualizaciones pendientes de las aplicaciones en servicio.

En el caso de un SO GNU/Linux como Debian, podemos utilizar la salida de los comandos df y apt-get, procesarlos con un script de Perl y enviar el resultado por email con formato HTML.

Para que Perl pueda enviar emails, utilizaremos el módulo MIME::Lite de CPAN. Para instalar este módulo podemos seguir estos pasos:

  • Instalar las librerías básicas de compilación y enlazado: apt-get install build-essential
  • Entrar en CPAN: cpan
  • Instalar el módulo: install MIME::Lite
  • Salir de CPAN: exit

Instalado el módulo, Perl podrá enviar emails.

Ahora el script en Perl. Lo puedes descargar clicando en éste enlace.

Las variables que tienes que personalizar en el script son:

  • $servidor: nombre corto que identifique al servidor en cuestión.
  • $from: dirección de email de origen (puedes inventarte una, aunque no exista).
  • $smtpserver: la ip del servidor de correo (SMTP) a enviar el mensaje (el que gestione el dominio de la direccion de email de entrega).
  • $to: dirección de email de entrega del mensaje (este email debe ser el real para recibir los informes).

Una vez personalizado, puedes crear una tarea programada con CRON para que ejecute el script con la frecuencia adecuada (por ejemplo, una vez al día) y esperar que te lleguen los informes por email en un bonito formato HTML.

viernes, 19 de abril de 2013

Citrix: información de sesiones

En un entorno Citrix a veces es necesario conocer rápidamente las sesiones de usuario iniciadas en un servidor concreto, como por ejemplo, para diagnosticar alguna incidencia con alguna aplicación.

Para no perder tiempo en acceder a la consola de administración y averiguar esta información, he preparado un script con PowerShell que, indicando el nombre de un servidor Citrix en la variable $nombre_host y ejecutándolo en cualquier otro host con los permisos suficientes muestra la información de las sesiones de Citrix activas:

# información de sesiones citrix


# nombre del servidor de Citrix
$nombre_host = hostname


# fecha/hora/minuto/segundo de la toma
$t = get-date
$anio = $t.year
$mes = $t.month
$dia = $t.day
$hora = $t.hour
$minuto = $t.minute
$segundo = $t.second

$tiempo = "$anio $mes $dia $hora $minuto $segundo"

# captura sesiones actuales del servidor de Citrix indicado
$sesiones = qwinsta /SERVER:$nombre_host

# elimina primera línea
$sesiones = $sesiones[1..$sesiones.length]

# inicia variables
$usuario = ""
$sesionid = 0
$total_cpu = 0
$mem = 0

foreach ( $sesion in $sesiones )
{
  # si se trata de una sesión de citrix
  if ( $sesion -match "wdica" )
  {
    $sesion = $sesion -replace “\s+”,” ”
    $t = $sesion.split(" ")

    # captura usuario e id de sesión
    $usuario = $t[2]
    $sesionid = $t[3]

    # inicia total_cpu y mem para esta sesión/usuario
    $total_cpu = 0
    $mem = 0

    # captura la memoria y el total de cpu de los procesos
    # de cada sesión/usuario de citrix
    $procesos = get-process | where {$_.sessionid -eq $sesionid}
    foreach ( $proceso in $procesos )
    {
      $total_cpu += $proceso.cpu
      $mem += $proceso.ws
    }
    $mem = [int]($mem / 1mb)
    write-host $tiempo $nombre_host $usuario $total_cpu $mem
  }
}


martes, 25 de diciembre de 2012

Punteros y Arrays en C

C es uno de los lenguajes de programación más utilizados por su portabilidad, potencia y rapidez, y con él se han escrito sistemas operativos, otros muchos lenguajes y aplicaciones críticas.

En general, el aprendizaje de C no difiere mucho de cualquier otro, pero hay un par de cosas que lo hacen característico: sólo tiene disponible tipos de datos básicos (entero, caracter, etc.) y es necesario tener un conocimiento profundo de punteros y arrays para desplegar toda su potencia.

Los punteros en C siempre han sido tema de discusión por su dificultad, pero eso depende de cómo se expliquen. Uno de los mejores tutoriales de punteros que existen por su simplicidad es el de Ted Jensen (disponible en este enlace), y he realizado la correspondiente traducción con su permiso (disponible en este enlace).

martes, 11 de diciembre de 2012

Información de un sistema Windows con WMI y C

Ya sabemos que WMI es la forma más sencilla de extraer información útil de un sistema Windows, ya sea para realizar diagnósticos, para registrar equipos o para realizar informes.

Buscando la forma más sencilla para conseguir esta información en cualquier máquina Windows, existe un comando de consola que extrae el dato directamente: wmic

Por ejemplo, si queremos ver el número de serie de la máquina local, podemos hacerlo así:

    wmic csproduct get identifyingnumber

de igual forma, si queremos ver el nombre del microprocesador, utilizamos:

    wmic cpu get name

Si con antelación sabemos la información que nos interesa de un sistema, podemos incluir todas
las sentencias que queramos en un archivo por lotes (.bat) y utilizarlo, pero si además nos interesa disponer de un archivo ejecutable que realice lo mismo, podemos hacerlo con un pequeño programa en C, llamado por ejemplo regsys.c de la siguiente forma:

#include <stdio.h>
#include <stdlib.h>

char *wmi();

int main()
{
// número de serie
char *nserie = "wmic csproduct get IdentifyingNumber";
char *pNserie = wmi( nserie );
printf("Numero de serie: %s", pNserie);

// fabricante
char *fabricante = "wmic computersystem get Manufacturer";
char *pFabricante = wmi( fabricante );
printf("Fabricante: %s", pFabricante);

// modelo placa
char *modeloPlaca = "wmic computersystem get model";
char *pModeloPlaca = wmi( modeloPlaca );
printf("Modelo placa: %s", pModeloPlaca);

// arquitectura
char *arq = "wmic computersystem get SystemType";
char *pArq = wmi( arq );
printf("Arquitectura: %s", pArq);

// procesador
char *cpu = "wmic cpu get name";
char *pCpu = wmi( cpu );
printf("Procesador: %s", pCpu);

return 0;
}

char *wmi( char *in )
{
FILE *fp;
char line[130];
char *line2;
line2 = malloc(130 * sizeof(char *));
 
fp = popen( in, "r" );

int x = 0;

while ( fgets( line, sizeof line, fp))
{
if ( x == 1 )
{
int z;

for ( z = 0 ; z < sizeof line ; z++ )
{
line2[z] = line[z];
}
}
x++;
}

pclose(fp);

return line2;
}

Podemos modificar el programa anterior e incluir todas las sentencias WMI que necesitemos mostrar. Además, con los conocimientos necesarios podemos ampliarlo para darle más funcionalidad como aceptar argumentos y escribir informes en un archivo HTML, por ejemplo.

El programa anterior se puede escribir en cualquier Windows, y compilarlo y enlazarlo con MinGW de la siguiente forma:

    cc regsys.c -o regsys.exe

y ya tendremos la herramienta regsys.exe lista para ejecutarlo.

jueves, 22 de noviembre de 2012

Exchange 2010: listado de reenvíos de buzones

Es muy útil redirigir mensajes que llegan a un buzón y entregarlos en otro buzón. Además también se puede elegir si entregar el mensaje en ambos buzones o sólo en el de reenvío. Para ello puedes utilizar la consola de administración de Exchange y también puedes utilizar una pequeña herramienta para realizarlo directamente conociendo los nombres de las cuentas (propiedad samAccountName) de los buzones en cuestión.

Cuando existe un número elevado de buzones que están redirigidos a otros, es necesario tenerlo controlado y disponer de un listado de ellos con su correspondiente configuración en un momento dado.

Puedes realizar este listado con Powershell, en concreto con el cmd-let de Exchange Get-Mailbox, que muestra las propiedades de los buzones. En este caso las propiedades son ForwardingAddressDeliverToMailboxAndForward.

Con el siguiente script de Powershell puedes conseguir este listado: todas las cuentas de todos los buzones que tengan activado el reenvío, la cuenta del buzón de reenvío y si el reenvío se entrega en ambos buzones o sólo en el buzón de reenvío:

# ignora errores
$ErrorActionPreference = "SilentlyContinue"

function bruto_a_sam($bruto)
{
  $bruto2 = $bruto -replace "^.*/", ""
  $root = [ADSI]''
  $busca = new-object System.DirectoryServices.DirectorySearcher($root)
  $busca.Filter = "(&(|(objectCategory=person)(objectCategory=group))(Name=$bruto2))"
  $sam = $busca.findone()
  return $sam.properties.samaccountname
}

$buzones = Get-Mailbox
$c = 0
foreach ($b in $buzones)
{
  $buzon = [string]$b.samaccountname
  $reenviar_a = [string]$b.ForwardingAddress
  $dual = [string]$b.DeliverToMailboxAndForward

  if ( $reenviar_a )
  {
    Write-Host Buzón: $buzon
    $sam = bruto_a_sam($reenviar_a)
    write-host Dirección de reenvío: $sam
    if ( $dual -eq "True" )
    {
      write-host Entrega en buzón y en dirección de reenvío
    }
    else
    {
      Write-Host Entrega sólo en dirección de reenvío
    }
 
    Write-Host -----
    $c++
  }
}

Write-Host $c registros

sábado, 16 de junio de 2012

¿Qué servidor hay detrás de una web?

Detrás de cualquier sitio web hay un servidor web, como Apache, IIS, etc. Una forma de saber esto es mirar el campo Server de la cabecera HTTP en la respuesta del sitio web en cuestión.

Por ejemplo, hagamos una lista de sitios web en un archivo de texto ( webs.txt ):

www.microsoft.com
www.google.com
www.apple.com
www.wikipedia.org
www.yahoo.com
www.facebook.com
www.twitter.com

Y ahora utilicemos el siguiente script de Powershell ( webserver.ps1 ) en la misma carpeta que el archivo webs.txt:

# webserver.ps1 - servidores web desde urls

function servidor_web($url)
{
  if ( $url -ne "" )
  {
    $solicitud=[system.Net.HttpWebRequest]::Create("http://"+$url)
    $cabecera = $solicitud.getresponse()
    $cabecera.Close()
    if ( $cabecera.Server ) { write-host $url "->" $cabecera.Server }
    else { write-host $url "-> no especificado" }
  }
}

$urls = get-content ./webs.txt

foreach ( $url in $urls) { servidor_web($url) }


El resultado es el siguiente:

www.microsoft.com -> Microsoft-IIS/8.0
www.google.com -> gws
www.apple.com -> Apache/2.2.3 (Oracle)
www.wikipedia.org -> Apache
www.yahoo.com -> YTS/1.20.10
www.facebook.com -> no especificado
www.twitter.com -> tfe

Y las conclusiones son interesantes:
  • Los servidores web de Google, Yahoo y Twitter son de desarrollo propio ( gws es Google Web Server, YTS es Yahoo Traffic Server y tfe sólo lo sabrán los ingenieros de Twitter ).
  • Facebook no da a conocer el campo Server en su cabecera (no especificado).
  • Apple y Wikipedia apuestan por Apache.

jueves, 3 de mayo de 2012

Concesiones DHCP con Netsh y PowerShell


¿Cuales son los hosts cuyas direcciones ip son asignadas de forma dinámica por un servidor DHCP de Windows?

Para conocer esta información normalmente consultas las concesiones de direcciones del servicio DHCP mediante su consola de administración.

Si necesitas la información anterior en otro formato para utilizarla después, la consola de administración de DHCP te permite realizar una exportación a un fichero de texto, pero ¿existe alguna manera automática de conseguir esta información? El comando netsh también puede mostrar esa información, como en el siguiente ejemplo (la ip del servidor DHCP es 192.168.1.100 y el ámbito consultado es 192.168.0.0):

netsh dhcp server 192.168.1.100 v4 scope 192.168.0.0 show clientsvq


Si redireccionas la salida del comando anterior a un fichero de texto ya tendrías un listado que puede servir de informe, pero si quieres un informe personalizado o automatizar otras tareas con esta información, es necesario extraer cada ip, mac y nombre de cada host del listado.

Para ello, puedes utilizar la salida del comando anterior en un script de PowerShell de la siguiente forma:


$clientes = netsh dhcp server 192.168.1.100 v4 scope 192.168.0.0 show clientsvq

foreach ($cliente in $clientes)
{
  if ($cliente -match "^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}")
  {
    $cliente -match "^(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s{1,}-\s\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\s{1,}-(\w\w-\w\w-\w\w-\w\w-\w\w-\w\w).*-[D|U|N]\s-(.*?)\s-"

    $ip     = $Matches[1]
    $mac    = $Matches[2] -replace "-",""
    $nombre = $Matches[3]

    write-host "$ip - $mac - $nombre"
  }
}


Y ya tendrías la ip, la mac y el nombre de cada host disponibles para lo que quieras.