jueves, 23 de mayo de 2013

Powershell y passwords

EnPower Shell a veces tenemos la necesidad de manejar claves, para lo que tenemos que por ejemplo para leer una clave y que aparezcan los típicos asteriscos, cada vez que pulsamos una tecla hacemos:

$psw = Read-Host "Ingrese la clave" -AsSecureString


Donde, con  "-AsSecureString" le indicamos que guarde lo ingresado en un string seguro. Bueno, ahora si ponemos

Write-Host $psw


vemos que la respuesta es

System.Security.SecureString


Lo cual nos deja un poco perplejos, para ver el valor ingresado debemos hacer

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($psw)

Write-Host [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)


...lo que nos mostrará la clave ingresada por el usuario.

miércoles, 15 de mayo de 2013

PowerShell: Búsqueda Binaria en arrays de objetos personalizados

El problema del IComparer

Siguiendo con el tema de la búsqueda rápida (haciendo búsqueda binaria), en éste artículo ya había encontrado cómo hacer una búsqueda binaria sobre un ArrayList desde Power Shell, pero al complicar un poco el tema, usando arreglos de objetos propios encontré un problema...
El problema es que al ser objetos propios debemos indicarle sobre qué campo hacer la búsqueda y cómo se ordenan los objetos... El mismo problema tenemos al ordenar (hacer un sort) sobre un Array o ArrayList.
Veamos a un ejemplo, tenemos un ArrayList de objetos Empleado, con atributos Nombre, Apellido, Legajo... por ej uso esta funcion para crearlos:

function Nuevo-Empleado(){
    param ($Nombre, $Apellido, $Codigo)
   
    $empleado= New-Object PSObject
   
    $empleado| Add-Member -type NoteProperty -Name Nombre -Value $Nombre
    $empleado| Add-Member -type NoteProperty -Name Apellido -Value $Apellido
    $empleado| Add-Member -type NoteProperty -Name Legajo -Value $Codigo

    return $empleado
}

Y supongamos que los cargamos de un archivo csv desordenado y queremos buscar por nro de legajo...

[System.Collections.ArrayList] $listaEmpleados = New-Object System.Collections.ArrayList
$listaEmpleados =  Import-Csv  -h Nombre, Apellido, Codigo
$listaEmpleados = $listaEmpleados | sort Codigo # ordeno por codigo


Ahora el tema es.. cómo hace para ordenar por  código... bueno, supongamos que código es string... luego, para poder hacer el BinarySearch...

La función de comparación

$src = @'

using System;
using System.Collections;
using System.Management.Automation;

   public sealed class ScriptBlockComparer : IComparer
   {
      ScriptBlock _Comparer;
      
      public ScriptBlockComparer(ScriptBlock Comparer) { ComparerScript = Comparer; }
      
      public ScriptBlock ComparerScript
      {
         get { return _Comparer; }
         set { _Comparer = value; }
      }
      
      public int Compare(object x, object y)
      {
         try {
            return (int)ComparerScript.Invoke(x, y)[0].BaseObject;
         } catch(Exception ex) {
            throw new InvalidOperationException("Comparer Script failed to return an integer!", ex);
         }
      }
      
   }
   
'@

Add-Type -TypeDefinition $src -Language CSharpVersion3

$cmp = New-Object ScriptBlockComparer {
    Param($primero, $segundo)
    $pos = $primero.Codigo.CompareTo($segundo)
   
    return $pos
}



.......
..........
mas codigo
...........
... y...

$pos = $list.BinarySearch($codigoABuscar, $cmp)


Y nos devuelve en pos la posición del elemento buscado en el array (empezando desde 0) y un nro <0 si no se encontró. Espero les sirva de ayuda!

Nota: si les tira error con la version de .Net  pueden intentar cambiar
Add-Type -TypeDefinition $src -Language CSharpVersion3
Por:
Add-Type -TypeDefinition $src -Language CSharp
Ya que espera tener instalado el Framework .Net versión 3.5

martes, 7 de mayo de 2013

bat2sh

Cómo convertir fácilmente un archivo bat de windows en un sh para linux.

Para eso comencé a crear este pequeño script en perl (mejorable por cierto) para automatizar un poco esta tarea. Dejo el código en su estado actual aquí abajo, pueden encontrar la última versión (y participar en ella para mejorarla) en éste github.


#!/usr/bin/perl

sub cat_ {
local *F;
open F, $_[0] or return;
my @l = ;
wantarray() ? @l : join '', @l
}
sub output {
my $f = shift;
local *F;
open F, ">$f" or die "output in file $f failed: $!\n";
print F foreach @_; 1
}
  
if (@ARGV != 2) {
die "Usage: bat2sh.pl <input .bat file> <output .sh file>\n";
}
my @contents = cat_($ARGV[0]);

foreach my $line (@contents) {
# rem -> #
$line =~ s/rem /# /i;
# move -> mv
$line =~ s/^\s*move\b/mv/;
# del -> rm
$line =~ s/^\s*del\b/rm/;
# dos eol to unix eol
$line =~ s/\r\n/\n/;
# set
$line =~ s/^\s*set //i;
# \ -> /
$line =~ s/\\/\//g;
# copy -> cp
if ($line =~ m/^\s*copy\b/ig){
$line =~ s/^\s*copy\b/cp/ig;
$line =~ s/\n//; #remove eol
$line .= " ./\n";
}
# %varName% -> $varName
while ($line =~ m/(%\w*%)/ig){
my $word = "\$" . substr($1, 1, -1);
$line =~ s/(%\w*%)/$word/ig;
}
# if ERRORLEVEL 1 goto ERROR -> if [ "$?" = "1" ]; then sub_error fi
if ($line =~ m/^\s*if\s*ERRORLEVEL\s*1\s*goto\s*(\w*)\s*$/ig){
$line = "if [ \"\$?\" = \"1\" ]; then \n exit 1\nfi\n";
}
}
my $line = "#!/bin/sh\n\n\n";
unshift @contents, $line;

output $ARGV[1], @contents;

lunes, 6 de mayo de 2013

Sonidos desde power shell


Con estas 4 líneas de abajo puedo ver dos cosas importantes en Power Shell,
  • ... una es resolver el path relativo a un archivo, como se ve,
    resolve-path .\warning.wav deja en $advertencia el path del archivo warning.wav, dentro del directorio en el que estamos trabajando.
  • ... la segunda, es como escuchar un sonido de un archivo wav


$advertencia = resolve-path .\warning.wav
$sound = New-Object System.Media.SoundPlayer
$sound.soundLocation = $rango
$sound.Play()


Hacer sonar algunos sonidos del sistema...

[System.Media.SystemSounds]::Asterisk.Play();
[System.Media.SystemSounds]::Beep.Play();
[System.Media.SystemSounds]::Exclamation.Play();
[System.Media.SystemSounds]::Hand.Play();
[System.Media.SystemSounds]::Question.Play(); 




Búsqueda rápida en Power Shell

Problema

Se debe hacer una búsqueda en power shell en una gran cantidad de datos, digamos un archivo de texto con 200 mil registros, de a uno por línea. La búsqueda común en powershell tarda mucho.

Solución

Se realiza la búsqueda utilizando ArrayLists (System.Collections.ArrayList)


clear
#leo el archivo
$db = get-content miArchivo
 
#cargo el contenido del archivo en un ArrayList
[System.Collections.ArrayList] $list = New-Object System.Collections.ArrayList 
 
foreach ($item in $db){
    [void] $list.Add($item)
} 
 
#ordeno el archivo (sin esto no funciona la búsqueda binaria)
$list.Sort()

$reg = Read-Host "Ingrese el registro a buscar"
$pos = $list.BinarySearch($reg)
if ($pos -ge 0){
    Write-Host "El registro se encuentra en la posición: " + $pos
}else{
    Write-Host "No se encuentra el registro"
}

Más info en:

ArrayList (sort)

viernes, 3 de mayo de 2013

Problema de permisos Power Shell

Al tratar de ejecutar un power shell por primera vez suele tirar algunas veces

File  cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.


El problema se soluciona abriendo la consola power shell con usuario administrador y corriendo las siguientes líneas

Set-ExecutionPolicy Unrestricted
Set-ExecutionPolicy RemoteSigned


Ambas solicitan confirmación.

viernes, 19 de abril de 2013

Tips Windows

Links simbólicos en windows 7 

Ahora windows permite tener links simbólicos al estilo linux, un gran avance... como crearlos:

mklink /D origen destino


El /D se usa para crear un "directorio" simbólico... no se usa /D para crear links a archivos.

viernes, 5 de abril de 2013

Algunas cosas sobre el comando sc

Crear y eliminar servicios en windows desde línea de comandos.

El comando sc, sirve para, entre otras cosas instalar y desinstalar servicios...
Por ejemplo para instalar

sc create nombre_de_mi_servicio binPath= path_del_exe start= auto


Prestar atención a que después de binPath= hay un espacio en blanco y despues el path, así se ponen los parametros, dejando un espacio en blanco, sino no funciona (loquísimo!), igual en start= auto y los demás...

Para eliminar el servicio

sc delete nombre_de_mi_servicio

También hay otros parámetros como start , para iniciar el servicio, stop para detenerlo, y el más útil "sc help" nos da la ayuda sobre SC...

Nota:

Cuando estaba probando instalar mi servicio, tuve que instalarlo y desinstalarlo varias veces con distintos parámetros. Pero me pasaba que una vez desinstalado, cuando quería reinstalarlo me tiraba el siguiente mensaje de error:


The specified service has been marked for deletion.


... y no me instalaba el servicio nuevamente.
A poco de probar descubrí que la "culpa" de ese error la tenía la consola de servicios de windows (ctrl-alt-del -> start task manager -> solapa Services -> botón Services), mientras estaba abierta tira ese error, cuando la cierro el error deja de ocurrir.

jueves, 4 de abril de 2013

Usar FunsionInventory-Agent con OCSInventory

Bueno, vamos a suponer que no tenemos instalado el OCSInventory y decidimos instalarlo

Instalación de OCSInventory server(Debian linux)

  1. Bajamos la última versión del servidor de www.ocsinventory-ng.org (al momento que escribo la 2.0.5) y la descomprimimos en alguna carpeta.
  2. Ejecutamos el archivo setup.sh, el mismo nos guiará paso a paso en toda la instalación. 
  3. Una vez terminado de ejecutar correctamente setup.sh, la instalación continúa por web en http://localhost/ocsreports, seguimos configurando por ahí hasta que se terminan correctamente todos los pasos y no tire ningún error por web.
 Bueno, ahora viene a lo que iba este artículo...

Cómo hacer para que el FusionInventory-Agent funcione con el servidor OCSInventory.

Del lado del servidor debemos hacer un par de cambios...
  1. En primer lugar ir al archivo /etc/apache2/conf.d/z-ocsinventory-server.conf y poner ésta línea
    PerlSetEnv OCS_OPT_EXT_USERAGENTS_FILE_PATH /etc/ocsinventory/agents.txt
    1. en su última parte (/etc/ocsinventory/agents.txt) indica la ubicación de un archivo de configuración que debemos crear...
    2. El archivo z-ocsinventory-server.conf podría llamarse ocsinventory-server.conf o de otra forma, de acuerdo a lo que haya configurado al instalar el OCSInventory Server.
  2. Crear el archivo /etc/ocsinventory/agents.txt (usar el path que hayamos indicado en la configuración del paso anterior).
    1. Este archivo de texto debe tener los nombres de los agentes de Fusion Inventory que pueden conectarse al servidor, incluyendo su versión, por ejemplo, su contenido podría ser:
      FusionInventory-Agent_v2.1.7-2
      FusionInventory-Agent_v2.0.6
      FusionInventory-Agent_v2.2.3
      FusionInventory-Agent_v2.2.7-3
      ^ Presten atención al formato, se agreta el "_v2" etc...
    2. Para ver la versión del agente, en la máquina cliente se ejecuta, desde consola de comando (ej en windows):
      C:\Program Files\FusionInventory-Agent-GLPI\perl\bin>perl.exe fusioninventory-agent -v
Desde el lado del cliente, debemos recordar apuntarlo a la dirección del servidor OCSInventory que recibe los datos en http://miserver/ocsinventory

Y listo... ya tenemos nuestro agente FusionInventory-Agent funcionando contra un servidor OCSInventory.

martes, 26 de febrero de 2013

Tips Graphite


Eliminar gráficas

Si queremos eliminar métricas realizadas en nuestro graphite, es muy fácil...
Los datos de las gráficas quedan en
 
/opt/graphite/storage/whisper/
 
...De donde los podemos borrar directamente.

Validar los esquemas

Graphite nos dá una herramienta para validar que nuestros archivos de schema estén bien formados, la misma se encuentra en
 
/opt/graphite/bin/validate-storage-schemas.py

Resulta muy útil para estar seguros de no tener errores en nuestros schemas.

Resetear Carbon

Es necesario hacer un restart al Carbon después de haber cambiado los archivos conf
/opt/graphite/bin/carbon-cache.py start

Sincronizar database

sudo /opt/graphite/webapp/graphite/python manage.py syncdb