Me acabo de enterar que se puede forzar un valor booleano de la siguiente forma:
!!algo
en vez de hacer cosas como:
algo ? true : false
o
Boolean(algo)
Ademas otra cuestion muy importante es que cuando se declaran las variables en Javascript estas adoptan "undefined" como valor inicial, no null. Y gracias a esto podemos chequear si una variable fue o no utilizada o asignada con algun valor:
var otracosa;
typeof otracosa;
devuelve "undefined"
var otracosa = null;
typeof otracosa;
devuelve "object"
var otracosa = "hola";
typeof otracosa;
devuelve "string"
Friday, October 1, 2010
Wednesday, September 29, 2010
Repositorio para Debian Etch (ya que ahora no hay mas soporte)
Me ocurrio que no pude hacer un dist-upgrade en una maquina en produccion por diversos motivos, y como los repositorios de Debian para Etch fueron removidos no se pueden instalar mas paquetes via internet, entonces hay que cambiar el /etc/apt/sources.list con la siguiente linea para volver a tener disponibles los paquetes de Etch:
deb http://archive.debian.org/debian etch main contrib non-free
Ya que en http://archive.debian.org han mantenido un mirror para gente como yo ;-)
Ademas, las ISO's viejas de Debian pueden conseguirse en:
http://cdimage.debian.org/cdimage/archive/
Saludos !
deb http://archive.debian.org/debian etch main contrib non-free
Ya que en http://archive.debian.org han mantenido un mirror para gente como yo ;-)
Ademas, las ISO's viejas de Debian pueden conseguirse en:
http://cdimage.debian.org/cdimage/archive/
Saludos !
Friday, August 20, 2010
Expresion regular para URL's de bit.ly (regex)
http:\/\/bit\.ly\/[A-Za-z0-9]{6}
y un preg_replace en PHP para esta regex seria:
$result = preg_replace('%http://bit\.ly/[A-Za-z0-9]{6}%', '', $subject);
Tuesday, July 20, 2010
Arrancar y parar servicios en Ubuntu 10.04 LTS (y configurarlos en el arranque)
Hace aproximadamente 4 o 5 años que no usaba linux en escritorio, asi que decidi comprarme un disco de 1 TB y probar Ubuntu Server 10.04 LTS.
Para mi sorpresa, los enlaces en /etc/init.d/* ya no funcionaban mas, ya que se decidio cambiar el sistema de arranque a upstart (todavia desconozco bien el funcionamiento).
Todas las utilidades como por ejemplo rcconf y sysv-rc-conf dejaron de funcionar. Ahora existe un nuevo directorio /etc/init/ en donde se almacena informacion de upstart para cada servicio que tengamos en la maquina.
Lo primero que quise hacer es deshabilitar algunos servicios que no usaba, asi que la forma de hacerlo es agregar o modificar la siguiente linea dentro de cada servicio en particular dentro del directorio /etc/init/:
start on runlevel [!0123456]
lo que significa no arrancar en los runlevels 0123456, o sea, no arrancar nunca.
Ademas, la nueva (para mi por lo menos :P) forma de arrancar o parar servicios es con el comando "service":
service mysql stop
service mysql start
o sino tambien con los comandos "stop" y "start"
stop mysql
start mysql
Ire comentando todas las diferencias que vaya encontrando en Ubuntu 10.04 respecto a las distribuciones que utilizaba hace 4 o 5 años (que deben ser unas cuantas).
Saludos
Para mi sorpresa, los enlaces en /etc/init.d/* ya no funcionaban mas, ya que se decidio cambiar el sistema de arranque a upstart (todavia desconozco bien el funcionamiento).
Todas las utilidades como por ejemplo rcconf y sysv-rc-conf dejaron de funcionar. Ahora existe un nuevo directorio /etc/init/ en donde se almacena informacion de upstart para cada servicio que tengamos en la maquina.
Lo primero que quise hacer es deshabilitar algunos servicios que no usaba, asi que la forma de hacerlo es agregar o modificar la siguiente linea dentro de cada servicio en particular dentro del directorio /etc/init/:
start on runlevel [!0123456]
lo que significa no arrancar en los runlevels 0123456, o sea, no arrancar nunca.
Ademas, la nueva (para mi por lo menos :P) forma de arrancar o parar servicios es con el comando "service":
service mysql stop
service mysql start
o sino tambien con los comandos "stop" y "start"
stop mysql
start mysql
Ire comentando todas las diferencias que vaya encontrando en Ubuntu 10.04 respecto a las distribuciones que utilizaba hace 4 o 5 años (que deben ser unas cuantas).
Saludos
Tuesday, May 18, 2010
Ordenar un array en PHP de acuerdo a un valor de los elementos que queremos ordenar (usort + funciones anonimas)
Retorcido ? bueno, mejor el ejemplo del codigo:
Interesante para ordenar arrays de forma "no convencional" con una funcion propia. En este caso se ordeno el $array de menor a mayor de acuerdo al subvalor 'secs_order' de cada elemento del $array.
Saludos !
<?php
$array = array(0 => array('id' => 1, 'secs_order' => 82800), 1 => array('id' => 2, 'secs_order' => 64800), 2 => array('id' => 3, 'secs_order' => 19300));
$cmp = function ($a, $b) {
if ($a['secs_order'] == $b['secs_order']) return 0;
return ($a['secs_order'] < $b['secs_order']) ? -1 : 1;
};
echo '<pre>' . print_r($array, TRUE) . '</pre>'; // desordenado
usort($array, $cmp); // notese q aca $cmp es una funcion anonima ...
echo '<pre>' . print_r($array, TRUE) . '</pre>'; // ordenado
?>
Interesante para ordenar arrays de forma "no convencional" con una funcion propia. En este caso se ordeno el $array de menor a mayor de acuerdo al subvalor 'secs_order' de cada elemento del $array.
Saludos !
Thursday, May 6, 2010
Convertir codigo html en entidades html para entradas en blogspot
Simplemente copiar y pegar el codigo en este sitio http://www.simplebits.com/cgi-bin/simplecode.pl y pegarlo en la entrada ...
Saludos !
Saludos !
JQuery, controlar multiples eventos para remover errores en un formulario HTML
Donde #start_date, #end_date, #rec_until son input=text y el codigo html que remueve el remove() es por ejemplo:
Ahora, el codigo en si es el siguiente:
Se que no es muy explicativo, pero lo interesante de esto es la funcion bind() que nos permite manejar diferentes eventos con una misma funcion. Lo que hace el codigo es remover con una animacion fadeOut() el dd+span que se agrego al formulario a causa de un error.
Saludos !
<dd><span class="error error_start_date">Invalid start date (format: mm/dd/yyyy)</span></dd>
Ahora, el codigo en si es el siguiente:
$('#start_date, #end_date, #rec_until').bind('click blur select', function() {
$('.error_' + $(this).attr('id')).fadeOut('slow', function () {
$(this).parent().remove();
});
});
Se que no es muy explicativo, pero lo interesante de esto es la funcion bind() que nos permite manejar diferentes eventos con una misma funcion. Lo que hace el codigo es remover con una animacion fadeOut() el dd+span que se agrego al formulario a causa de un error.
Saludos !
Thursday, April 29, 2010
Problema con checkbox, IE6, IE7, IE8 y JQuery
IE no lanza el evento .change() de JQuery en checkboxes (y posiblemente, no lo testie pero dicen que tampoco en radio) en ninguna de sus versiones, como me acabo de enterar despues de renegar bastante y de buscar un poco en google ...
La "solucion" es esta:
Gracias IE por hacernos la vida imposible. Gracias.
La "solucion" es esta:
if ($.browser.msie) {
$('#elemento').click( function () {
$(this).blur();
$(this).focus();
// hacer algo para IE
});
} else {
$('#elemento').change( function () {
// hacer algo para cualquier otro browser decente
});
}
Gracias IE por hacernos la vida imposible. Gracias.
Wednesday, April 14, 2010
Validar fechas con JQuery o Javascript teniendo en cuenta los años bisiestos
En el HTML para el siguiente codigo Javascript hay que colocar 3 elementos select (o cambiar el selector de JQuery para colocar un input) que tengan la propiedad ID nombrada a detect_month, detect_day y detect_year.
El regex obviamente se puede mejorar (o cambiar), pero lo dejo de esa forma para que se pueda reutilizar checkeando fechas en el formato mm/dd/yyyy. En si, lo importante del codigo es el checkeo de si es o no un año bisiesto.
Ojala le resulte util a alguien ...
Saludos !
El regex obviamente se puede mejorar (o cambiar), pero lo dejo de esa forma para que se pueda reutilizar checkeando fechas en el formato mm/dd/yyyy. En si, lo importante del codigo es el checkeo de si es o no un año bisiesto.
$(function() {
var regexDateValidator = function (month, day, year) {
return (month + "/" + day + "/" + year).match(/(0[1-9]|1[012])[\- \/.](0[1-9]|[12][0-9]|3[01])[\- \/.]((?:19|20)+\d{2})/);
}
$("select[id*='detect_']").change(function () {
var result, check, month, day, year;
result = regexDateValidator(month = $('#detect_month').val(), day = $('#detect_day').val(), year = $('#detect_year').val());
if ( Boolean(result) ) {
if ( result[2] == 31 && (result[1] == 4 || result[1] == 6 || result[1] == 9 || result[1] == 11) ) {
check = false; // 31 de un mes con 30 dias
} else if (result[2] >= 30 && result[1] == 2) {
check = false; // febrero 30 o 31
} else if ( (result[1] == 2) && (result[2] == 29) && ( !(result[3] % 4 == 0 && (result[3] % 100 != 0 || result[3] % 400 == 0)) ) ) {
check = false; // febrero 29 fuera de un año bisiesto
} else {
check = true;
}
} else {
check = false;
}
if ( check ) {
// hacer algo (fecha valida)
} else {
// hacer algo (fecha invalida)
}
});
});
Ojala le resulte util a alguien ...
Saludos !
Sunday, April 4, 2010
fbinst (particionar pendrive)
Es un muy buen programa para particionar (por ejemplo, pendrives) bajo windows y es free.
http://download.gna.org/grubutil/
Lo unico es que al terminar de ejecutar los comandos hay que desmontar el pendrive y volverlo a introducir (no se como sincronizar el sistema operativo todavia).
Obviamente, estos son simples ejemplos de uso del programa.
Mas info en: http://www.boot-land.net/forums/index.php?showtopic=7932
Saludos !
http://download.gna.org/grubutil/
Lo unico es que al terminar de ejecutar los comandos hay que desmontar el pendrive y volverlo a introducir (no se como sincronizar el sistema operativo todavia).
fbinst.exe --list
fbinst.exe (hdX) format --force --raw --fat32 --size 3800m
fbinst.exe (hdX) format --force --raw --fat16 --size 1900m
Obviamente, estos son simples ejemplos de uso del programa.
Mas info en: http://www.boot-land.net/forums/index.php?showtopic=7932
Saludos !
Sunday, February 14, 2010
Saturday, February 13, 2010
Instalar Windows 7 / Vista / XP y Linux desde una unidad USB o pendrive
Investigando un poco me tope con un EXCELENTE proyecto llamado WinSetupFromUSB que permite crearnos un USB booteable con practicamente cualquier cosa que queramos. Efectivamente se pueden hacer pendrives multibooteables con windows 7 / Vista / XP y Linux todo junto.
http://www.msfn.org/board/index.php?showtopic=120444
Estuve un dia entero renegando con ciertas cosas, asi que lo que recomiendo es ir directamente a la carpeta /files/tools y correr los siguientes:
HPUSBFW.EXE = con esto formateamos en FAT32 el pendrive USB, es muy importante ya que no cualquier formato es reconocido por los BIOS. Ante mi asombro, dentro de un formato FAT32 existen varios tipos como USB-FDD, USB-ZIP, USB-HDD single y multiple. Esta utilidad nos deja el pendrive como USB-HDD single.
BOOTICE.EXE = process MBR y PBR. En ambos instalamos GRUB for DOS y copiamos el grldr (bootloader) y bueno, los menu.lst que querramos (igual al grub de linux).
Despues con el programa en si podemos insertarle el setup de cualquier windows que querramos (se que funciona con XP/Vista/7) e incluso diferentes distros de linux desempaquetando las ISO's en el rigido y agregandolas con la opcion "SysLinux bootsector/Linux distribution using SysLinux" luego.
Recalco que hay q saber editar las entradas de grub (menu.lst) para dejar andando toda la ensalada de sistemas operativos, pero yo he podido crear un multibooteable con windows xp y windows 7 + backtrack 4 sin problemas.
Adios compacteras !
http://www.msfn.org/board/index.php?showtopic=120444
Estuve un dia entero renegando con ciertas cosas, asi que lo que recomiendo es ir directamente a la carpeta /files/tools y correr los siguientes:
HPUSBFW.EXE = con esto formateamos en FAT32 el pendrive USB, es muy importante ya que no cualquier formato es reconocido por los BIOS. Ante mi asombro, dentro de un formato FAT32 existen varios tipos como USB-FDD, USB-ZIP, USB-HDD single y multiple. Esta utilidad nos deja el pendrive como USB-HDD single.
BOOTICE.EXE = process MBR y PBR. En ambos instalamos GRUB for DOS y copiamos el grldr (bootloader) y bueno, los menu.lst que querramos (igual al grub de linux).
Despues con el programa en si podemos insertarle el setup de cualquier windows que querramos (se que funciona con XP/Vista/7) e incluso diferentes distros de linux desempaquetando las ISO's en el rigido y agregandolas con la opcion "SysLinux bootsector/Linux distribution using SysLinux" luego.
Recalco que hay q saber editar las entradas de grub (menu.lst) para dejar andando toda la ensalada de sistemas operativos, pero yo he podido crear un multibooteable con windows xp y windows 7 + backtrack 4 sin problemas.
Adios compacteras !
configuracion wifi / wireless con backtrack 4
ifconfig wlan0 up
iwconfig wlan0 essid 'miredinalambrica'
en el /etc/wpa_supplicant/wpa_supplicant.conf (si es q usamos WPA-PSK con AES unicamente):
network={
ssid="miredinalambrica"
key_mgmt=WPA-PSK
pairwise=CCMP
group=CCMP
psk="migranpassword"
}
luego levantamos la red asi:
wpa_supplicant -D wext -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
y por ultimo, si usamos dhcp:
dhclient wlan0
Thursday, December 17, 2009
Limpiar archivos de log en linux
Una simple linea nos permite limpiar archivos de texto:
Con fuser podemos saber si el archivo esta siendo usado por algun proceso:
> /directorio/archivo.log
Con fuser podemos saber si el archivo esta siendo usado por algun proceso:
fuser /directorio/archivo.log
Particiones y labels en ext3, swap y reiserfs
Se pueden crear y montar particiones con "labels", y tiene la ventaja de que si el nombre del dispositivo cambia, no nos interesa porque el kernel sabe que label corresponde a cada particion. Esto es MUY util en servidores ya que de cambiar el nombre del dispositivo por cualquier motivo, evitamos quedarnos con un sistema sin bootear.
Supongamos claro que /dev/hda1 es una swap, /dev/hda2 es el root del sistema de archivos con ext3 y /dev/hdb1 es una particion reiser
Luego en /etc/fstab tenemos las siguientes entradas
Supongamos claro que /dev/hda1 es una swap, /dev/hda2 es el root del sistema de archivos con ext3 y /dev/hdb1 es una particion reiser
tune2fs -L ROOT /dev/hda2
swapoff /dev/hda1
mkswap -L SWAP /dev/hda1
swapon /dev/hda1
umount /dev/hdb1
reiserfstune -l DATA /dev/hdb1
Luego en /etc/fstab tenemos las siguientes entradas
LABEL=ROOT / ext3 noatime,errors=remount-ro 0 1
LABEL=SWAP none swap sw 0 0
LABEL=DATA /www reiserfs defaults 0 0
Sunday, March 22, 2009
Deshabilitar completamente el Autorun y el Autoplay de Windows XP
Ya que vienen circulando 8000 virus a traves de los pendrives y como ya me infecte 3 veces por olvidarme de revisar pendrives a mano antes de abrirlos entonces busque bien como realmente desactivar el autorun de windows, y digo realmente porque si bien hay muchos metodos para desactivarlo, cuando uno hace click sobre alguna unidad que tiene el autorun.inf, el maldito se SIGUE ejecutando.
Entonces:
Inicio, ejecutar: gpedit.msc
Ir a Administrative Templates -> System -> Turn off Autoplay
Configurarlo en Enabled para todas las unidades.
Ademas de esto, abrir con el notepad y crear un archivo con cualquier nombre pero con la extension .reg (para crear un archivo de registro) y pegarle el siguiente texto:
Guardarlo y hacer doble click sobre el archivo. Cuando windows pregunte si desea agregar la informacion al registro darle que si.
Ahora si tenemos REALMENTE el autorun desactivado por completo. Aclaro que el gpedit.msc solo funciona en la version Professional de Windows XP.
Saludos !
Entonces:
Inicio, ejecutar: gpedit.msc
Ir a Administrative Templates -> System -> Turn off Autoplay
Configurarlo en Enabled para todas las unidades.
Ademas de esto, abrir con el notepad y crear un archivo con cualquier nombre pero con la extension .reg (para crear un archivo de registro) y pegarle el siguiente texto:
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\Autorun.inf]
@="@SYS:DoesNotExist"
Guardarlo y hacer doble click sobre el archivo. Cuando windows pregunte si desea agregar la informacion al registro darle que si.
Ahora si tenemos REALMENTE el autorun desactivado por completo. Aclaro que el gpedit.msc solo funciona en la version Professional de Windows XP.
Saludos !
Thursday, March 19, 2009
Crear y montar una particion basada en archivo
Supongamos que ya compramos un servidor con linux en algun datacenter y que por X motivo no lo podemos reparticionar o reinstalar y necesitamos tener otras particiones, quiza con otro sistema de archivo ...
1) le decimos a dd que cree un archivo de 1 GB (bs = block size) 1M x 1000 = 1 GB
2) losetup asocia dispositivos de loop con archivos normales
3) formateamos con reiserfs (puede ser ext3, etc) el archivo /particion.part
4) montamos la particion
5) hacemos algo util
6) desmontamos la particion
7) desvinculamos el dispositivo de loop /dev/loop0 del archivo que creamos
Supongamos ahora que deseamos automontar esta "particion" al bootear, para ello editamos el archivo /etc/fstab y agregamos lo siguiente:
Ahora los scripts de inicio se encargaran de montar la particion que hemos creado en un archivo sobre otro sistema de archivos.
1) dd if=/dev/zero of=/particion.part bs=1M count=1000
2) losetup /dev/loop0 /particion.part
3) mkfs -t reiserfs /dev/loop0
4) mount -t reiserfs /dev/loop0 /www
5) Ya tenemos disponible la particion /www para hacer lo que queramos
6) umount /www
7) losetup -d /dev/loop0
1) le decimos a dd que cree un archivo de 1 GB (bs = block size) 1M x 1000 = 1 GB
2) losetup asocia dispositivos de loop con archivos normales
3) formateamos con reiserfs (puede ser ext3, etc) el archivo /particion.part
4) montamos la particion
5) hacemos algo util
6) desmontamos la particion
7) desvinculamos el dispositivo de loop /dev/loop0 del archivo que creamos
Supongamos ahora que deseamos automontar esta "particion" al bootear, para ello editamos el archivo /etc/fstab y agregamos lo siguiente:
/particion.part /www reiserfs defaults,loop 0 0
Ahora los scripts de inicio se encargaran de montar la particion que hemos creado en un archivo sobre otro sistema de archivos.
Copiar via ssh un archivo o directorio comprimiendo al vuelo con bzip2
Este metodo es un poco distinto del anterior, ya que lo unico que se requiere es ssh, tar y bzip2 (no dependemos de rsync). Por supuesto, este metodo va comprimiendo cada archivo con bzip2, asi que es util para pasar backups de un server a otro sin gastar espacio para el backup
esto copia /archivo comprimiendo el envio via ssh a 192.168.1.1 en el directorio /tmp
o para copiar un directorio:
esto copia el directorio mydir comprimiendo el envio via ssh a 192.168.1.1 en el directorio /tmp
y ahora, quiza otra variante interesante sea comprimir un archivo o directorio y dejar el resultado comprimido en un tar en el host remoto:
o para un directorio:
Supongamos que tenemos un disco de 20 GB y tenemos 19.5 GB ocupados. Logicamente hacer un backup dentro de ese disco es imposible, asi que con el metodo que menciono arriba se comprimen los datos al vuelo y se envian al host remoto sin utilizar espacio en la maquina local.
Espero que resulte util.
tar cjf - ./archivo | ssh "-oPort=1234" root@192.168.1.1 'cd /tmp && tar xjpvf -'
esto copia /archivo comprimiendo el envio via ssh a 192.168.1.1 en el directorio /tmp
o para copiar un directorio:
tar cjf - mydir/ | ssh "-oPort=1234" root@192.168.1.1 'cd /tmp && tar xjpvf -'
esto copia el directorio mydir comprimiendo el envio via ssh a 192.168.1.1 en el directorio /tmp
y ahora, quiza otra variante interesante sea comprimir un archivo o directorio y dejar el resultado comprimido en un tar en el host remoto:
tar cjf - ./archivo | ssh "-oPort=1234" root@192.168.1.1 'cd /tmp && cat - > ./archivo.tar.bz2'
o para un directorio:
tar cjf - directorio/ | ssh "-oPort=1234" root@192.168.1.1 'cd /tmp && cat - > ./directorio.tar.bz2'
Supongamos que tenemos un disco de 20 GB y tenemos 19.5 GB ocupados. Logicamente hacer un backup dentro de ese disco es imposible, asi que con el metodo que menciono arriba se comprimen los datos al vuelo y se envian al host remoto sin utilizar espacio en la maquina local.
Espero que resulte util.
Copiar via ssh un archivo o directorio con rsync comprimiendo on-the-fly (al vuelo)
El ya de por si interesante programita rsync tiene un flag que permite comprimir lo que se esta enviando (gzip). Podemos combinar rsync + ssh para hacer un envio seguro de los datos de la siguiente forma:
o sino para un directorio completo:
cabe aclarar que la barra al final de dir_a_copiar es muy importante ya que si esta nos dice que copiemos el contenido de /dir_a_copiar dentro de /dir_remoto, si no la colocamos el comando copiara /dir_a_copiar/ DENTRO de /dir_remoto, por lo que la estructura quedaria /dir_remoto/dir_a_copiar (las idiosincracias de rsync ;-)
los flags hacen lo siguiente:
rsync -azvhe "ssh -p 1234" /dir_local/archivo root@192.168.1.1:/dir_remoto
o sino para un directorio completo:
rsync -azvhe "ssh -p 1234" /dir_a_copiar/ root@192.168.1.1:/dir_remoto
cabe aclarar que la barra al final de dir_a_copiar es muy importante ya que si esta nos dice que copiemos el contenido de /dir_a_copiar dentro de /dir_remoto, si no la colocamos el comando copiara /dir_a_copiar/ DENTRO de /dir_remoto, por lo que la estructura quedaria /dir_remoto/dir_a_copiar (las idiosincracias de rsync ;-)
los flags hacen lo siguiente:
a: archiva
z: comprime (gzip)
v: verbose (dar detalles podria ser la traduccion)
h: human readable, mostrar los detalles de forma que un humano los pueda entender
e: especifica el shell remoto a utilizar, en nuestro caso ssh en el puerto 1234, obviamente hay q reemplazar por el puerto que corresponda (22 en un caso normal)
Tuesday, February 24, 2009
Usar un campo entero en MySQL para almacenar mas de un flag
Ante la necesidad de almacenar varios flags (banderas) en un solo campo entero, podemos implementar la siguiente solucion:
UNSIGNED TINYINT = 8 bits / 1 byte
UNSIGNED SMALLINT = 16 bits / 2 bytes
UNSIGNED MEDIUMINT = 24 bits / 3 bytes
UNSIGNED INT = 32 bits / 4 bytes
etc, etc ...
Por cada bit, tenemos una posicion, asi que si tomamos el ejemplo de un campo TINYINT, tendriamos disponibles 8 posiciones, u 8 flags para utilizar.
A cada posicion le asignamos un valor superior en base 2, de esta forma:
define("POS_1", 1);
define("POS_2", 2);
define("POS_3", 4);
define("POS_4", 8);
define("POS_5", 16);
define("POS_6", 32);
define("POS_7", 64);
define("POS_8", 128);
Ahora, supongamos que queremos activar los flags de las posiciones 3, 6 y 8, entonces realizamos un bitwise OR (operacion binaria):
$campo = (POS_3 | POS_6 | POS_8);
La operacion OR entre dos numeros dice que si el valor A o el valor B son 1, el resultado final es 1:
00000100 = 4
OR
00100000 = 32
OR
10000000 = 128
--------
10100100 = 164 = campo en la tabla MySQL
y a la variable campo la almacenamos en la base de datos.
Ahora, la "magia" la hacemos formulando la siguiente consulta, que de acuerdo a mis test, funciona bastante bien a pesar que el optimizador de MySQL no la optimiza.
SELECT * FROM `tabla` WHERE ((`campo` & 4) && (`campo` & 32) && (`campo` & 128));
En esta consulta se hace una operacion bitwise AND entre el valor de nuestro campo (164 = 10100100) en la base de datos y el valor decimal de cada posicion.
10100100 = 164
AND
00000100 = 4
--------
00000100 = 4
La operacion AND dice que si el valor en A y el valor en B son 1, entonces el resultado final es 1.
Ahora, en la consulta vemos que el WHERE hace AND's bitwise y logicos, y ahi esta el secreto, ya que si la operacion and en cada parentesis da un numero cero, la comprobacion logica falla y el registro no concuerda.
Por ejemplo, si buscamos para la POS_5, que es 16, entonces tenemos que:
10100100 = 164
AND
00010000 = 16
--------
00000000 = 0
Por ende, no se cumple y afecta al resto de la comprobacion logica (doble ampersand &&).
He probado esta consulta en una tabla con 88000 registros, de los cuales unos 4000 son distintos y obtuve un tiempo de 0.0024 seg de promedio, asi que podriamos decir que la consulta funciona bien, aunque el optimizador no este trabajando.
Esto incluyendo SQL_NO_CACHE para obtener un resultado fiel (no usar el cache, obviamente).
Saludos
PD: comentarios y sugerencias, totalmente aceptados ...
UNSIGNED TINYINT = 8 bits / 1 byte
UNSIGNED SMALLINT = 16 bits / 2 bytes
UNSIGNED MEDIUMINT = 24 bits / 3 bytes
UNSIGNED INT = 32 bits / 4 bytes
etc, etc ...
Por cada bit, tenemos una posicion, asi que si tomamos el ejemplo de un campo TINYINT, tendriamos disponibles 8 posiciones, u 8 flags para utilizar.
A cada posicion le asignamos un valor superior en base 2, de esta forma:
define("POS_1", 1);
define("POS_2", 2);
define("POS_3", 4);
define("POS_4", 8);
define("POS_5", 16);
define("POS_6", 32);
define("POS_7", 64);
define("POS_8", 128);
Ahora, supongamos que queremos activar los flags de las posiciones 3, 6 y 8, entonces realizamos un bitwise OR (operacion binaria):
$campo = (POS_3 | POS_6 | POS_8);
La operacion OR entre dos numeros dice que si el valor A o el valor B son 1, el resultado final es 1:
00000100 = 4
OR
00100000 = 32
OR
10000000 = 128
--------
10100100 = 164 = campo en la tabla MySQL
y a la variable campo la almacenamos en la base de datos.
Ahora, la "magia" la hacemos formulando la siguiente consulta, que de acuerdo a mis test, funciona bastante bien a pesar que el optimizador de MySQL no la optimiza.
SELECT * FROM `tabla` WHERE ((`campo` & 4) && (`campo` & 32) && (`campo` & 128));
En esta consulta se hace una operacion bitwise AND entre el valor de nuestro campo (164 = 10100100) en la base de datos y el valor decimal de cada posicion.
10100100 = 164
AND
00000100 = 4
--------
00000100 = 4
La operacion AND dice que si el valor en A y el valor en B son 1, entonces el resultado final es 1.
Ahora, en la consulta vemos que el WHERE hace AND's bitwise y logicos, y ahi esta el secreto, ya que si la operacion and en cada parentesis da un numero cero, la comprobacion logica falla y el registro no concuerda.
Por ejemplo, si buscamos para la POS_5, que es 16, entonces tenemos que:
10100100 = 164
AND
00010000 = 16
--------
00000000 = 0
Por ende, no se cumple y afecta al resto de la comprobacion logica (doble ampersand &&).
He probado esta consulta en una tabla con 88000 registros, de los cuales unos 4000 son distintos y obtuve un tiempo de 0.0024 seg de promedio, asi que podriamos decir que la consulta funciona bien, aunque el optimizador no este trabajando.
Esto incluyendo SQL_NO_CACHE para obtener un resultado fiel (no usar el cache, obviamente).
Saludos
PD: comentarios y sugerencias, totalmente aceptados ...
Friday, February 13, 2009
Inflación
"No es el dinero, como a veces se dice, sino la depreciación del dinero -la destrucción cruel y astuta del dinero- la que es la causa de muchos males.
La inflación destruye el ahorro individual y la autosuficiencia mientras gradualmente erosiona la riqueza personal. Pocas son las políticas más calculadas para destruir las bases existentes de una sociedad libre que la destrucción de su moneda."
Hans F. Sennholz
La inflación destruye el ahorro individual y la autosuficiencia mientras gradualmente erosiona la riqueza personal. Pocas son las políticas más calculadas para destruir las bases existentes de una sociedad libre que la destrucción de su moneda."
Hans F. Sennholz
Friday, December 12, 2008
SSH sin password y en puerto no estandar
Si necesitamos hacer sftp o ssh a una maquina remota sin tipear el password cada vez que queremos ingresar, hacemos lo siguiente:
y le damos enter a TODO lo que pregunta (incluso el password, lo dejamos en blanco).
Esta operacion genera una llave publica y privada para nuestra maquina, entonces ahora lo que tenemos que hacer es copiar la llave publica a la maquina remota.
Ademas, de esta forma podemos copiarla via un puerto no estandar, como el 5678 en mi caso:
Donde logicamente la maquina remota es 192.168.1.2 y el usuario remoto con el que nos interesa loguearnos es root.
Cabe aclarar que hay dos formas de generar las llaves, una es con el algoritmo DSA y otra con el RSA y se prefiere este ultimo ya que es mucho mas seguro.
Las llaves en la maquina remota quedan almacenadas en:
~/.ssh/authorized_keys2 para llaves RSA.
~/.ssh/authorized_keys para las viejas llaves DSA.
Como dato adicional agrego como conectar con SFTP y SSH en este puerto no estandar:
Saludos !
ssh-keygen -t rsa
y le damos enter a TODO lo que pregunta (incluso el password, lo dejamos en blanco).
Esta operacion genera una llave publica y privada para nuestra maquina, entonces ahora lo que tenemos que hacer es copiar la llave publica a la maquina remota.
Ademas, de esta forma podemos copiarla via un puerto no estandar, como el 5678 en mi caso:
ssh-copy-id -i ~/.ssh/id_rsa.pub "-p 5678 root@192.168.1.2"
Donde logicamente la maquina remota es 192.168.1.2 y el usuario remoto con el que nos interesa loguearnos es root.
Cabe aclarar que hay dos formas de generar las llaves, una es con el algoritmo DSA y otra con el RSA y se prefiere este ultimo ya que es mucho mas seguro.
Las llaves en la maquina remota quedan almacenadas en:
~/.ssh/authorized_keys2 para llaves RSA.
~/.ssh/authorized_keys para las viejas llaves DSA.
Como dato adicional agrego como conectar con SFTP y SSH en este puerto no estandar:
sftp "-oPort=5678" 192.168.1.2
ssh "-oPort=5678" 192.168.1.2
Saludos !
Monday, December 1, 2008
Unreal Tournament choppy/entrecortado (problemas con dual core)
Tengo una notebook con un procesador Intel Dual-Core, y al correr el Unreal Tournament se veia "acelerado" por demas, como si tuviese un cluster de maquinas corriendo el pobre jueguito.
No se porque ciertas maquinas tienen el problema y ciertas no, pero lo que si se es que encontre una solucion: habilitar solo un core para el juego.
Esto ultimo lo podemos lograr manualmente con el administrador de tareas clasico de windows, o bajarnos una aplicacion de la gente de tomshardware.com que se llama TaskAssign y que nos permite crear perfiles para cada aplicacion.
URL de la aplicacion:
http://images.tomshardware.com/2004/05/28/getting_more_bang_out_of_your_dual_processing_buck/taskassign.zip
Logicamente, elegimos el ejecutable UnrealTournament.exe y le asignamos un solo core.
Problema solucionado !
Un amigo me recomendo tambien que actualice el renderer de OpenGL para el UT (no tiene nada que ver con el problema en si, pero logramos mejor performance ya que estamos), que lo podemos bajar de aca:
http://cwdohnal.home.mindspring.com/utglr/
y el enlace directo es:
http://cwdohnal.home.mindspring.com/utglr/utglr34.zip
Y extraemos los archivos en C:\UnrealTournament\System sobreescribiendo el .dll existente.
Por lo general hay que iniciar el UT en "Safe Mode" y seleccionar "Change your 3D video device", luego "Show All Devices" y por ultimo elegir la opcion de "OpenGL support".
Eso es todo amigos !
No se porque ciertas maquinas tienen el problema y ciertas no, pero lo que si se es que encontre una solucion: habilitar solo un core para el juego.
Esto ultimo lo podemos lograr manualmente con el administrador de tareas clasico de windows, o bajarnos una aplicacion de la gente de tomshardware.com que se llama TaskAssign y que nos permite crear perfiles para cada aplicacion.
URL de la aplicacion:
http://images.tomshardware.com/2004/05/28/getting_more_bang_out_of_your_dual_processing_buck/taskassign.zip
Logicamente, elegimos el ejecutable UnrealTournament.exe y le asignamos un solo core.
Problema solucionado !
Un amigo me recomendo tambien que actualice el renderer de OpenGL para el UT (no tiene nada que ver con el problema en si, pero logramos mejor performance ya que estamos), que lo podemos bajar de aca:
http://cwdohnal.home.mindspring.com/utglr/
y el enlace directo es:
http://cwdohnal.home.mindspring.com/utglr/utglr34.zip
Y extraemos los archivos en C:\UnrealTournament\System sobreescribiendo el .dll existente.
Por lo general hay que iniciar el UT en "Safe Mode" y seleccionar "Change your 3D video device", luego "Show All Devices" y por ultimo elegir la opcion de "OpenGL support".
Eso es todo amigos !
Monday, November 24, 2008
Conociendo fuser (que proceso usa un socket o un sistema de archivos)
fuser es una utilidad que sirve para averiguar que proceso esta usando un archivo, socket o sistema de archivos.
El otro dia necesite saber que proceso estaba abriendo el puerto 113, entonces ahi vino fuser al rescate:
El numero 2786 que vemos en la salida indica (en mi caso) que el proceso con numero 2786 esta abriendo el puerto 113 tcp. Por supuesto se puede cambiar el "space" y en vez de usar tcp, usar udp si es necesario.
Otro uso muy util es para averiguar que procesos estan usando un filesystem, y se usa de la siguiente manera:
Lo que podemos ver en la salida del comando es el numero de proceso seguido por algunas letras y entre parentesis el propietario o usuario del proceso. Las letras que se ven tienen el siguiente significado:
Espero que les resulte util como a mi ;-)
Saludos !
El otro dia necesite saber que proceso estaba abriendo el puerto 113, entonces ahi vino fuser al rescate:
fuser -n tcp 113
lo cual me devolvio
113/tcp: 2786
El numero 2786 que vemos en la salida indica (en mi caso) que el proceso con numero 2786 esta abriendo el puerto 113 tcp. Por supuesto se puede cambiar el "space" y en vez de usar tcp, usar udp si es necesario.
Otro uso muy util es para averiguar que procesos estan usando un filesystem, y se usa de la siguiente manera:
# fuser -m -u /dev/sda3
/dev/sda3: 1rce(root) 2rc(root) 3rc(root) 4rc(root) 5rc(root) 6rc(root) 9rc(root) 10rc(root) 103rc(root) 143rc(root) 144rc(root) 145rc(root) 146rc(root) 595rc(root)
y la lista continua pero la corto por una cuestion de simplicidad ...
Lo que podemos ver en la salida del comando es el numero de proceso seguido por algunas letras y entre parentesis el propietario o usuario del proceso. Las letras que se ven tienen el siguiente significado:
c = current directory / directorio actual
e = executable being run / ejecutable siendo corrido
f = open file / archivo abierto
F = open file for writing / archivo abierto para escritura
r = root directory / directorio de root
m = mmap'ed file or shared library / archivo de mmap o libreria compartida
Espero que les resulte util como a mi ;-)
Saludos !
Thursday, November 20, 2008
TIP: Conectar con SSH o SFTP en otro puerto que no sea el 22
Supongamos que deseamos correr el daemon sshd en otro puerto que no sea el default (o sea, el 22) para evitar la mayoria de los escaneos por bots, e intentos de conexion por diccionario, u otro motivo si vamos al caso.
Modificamos el /etc/ssh/sshd_config en la linea de Port = 22 y le asignamos el numero de puerto que deseemos:
Reiniciamos ssh con:
Y luego desde algun cliente podemos conectar, suponiendo que la IP de esa maquina es 192.168.1.1 al puerto 5000 de la siguiente forma:
Saludos !
Modificamos el /etc/ssh/sshd_config en la linea de Port = 22 y le asignamos el numero de puerto que deseemos:
Port = 5000
Reiniciamos ssh con:
/etc/init.d/ssh restart
Y luego desde algun cliente podemos conectar, suponiendo que la IP de esa maquina es 192.168.1.1 al puerto 5000 de la siguiente forma:
sftp "-oPort=5000" 192.168.1.1
ssh "-oPort=5000" 192.168.1.1
Saludos !
Uso de la RAM para guardar datos con RAMFS o TMPFS
Hace algun tiempo se me ocurrio la idea de que seria util almacenar ciertos datos en la RAM debido a su velocidad de escritura, asi que me puse a investigar y encontre dos sistemas para hacerlo, uno RAMFS y el otro TMPFS.
Como montar ambos ? aqui va para los impacientes nuevamente:
o sino para ramfs, de la siguiente forma:
Con ambos comandos disponemos de 10 MB en RAM para escribir, pero con las siguientes diferencias:
- RAMFS crece dinamicamente, asi que si tenemos 1 GB de RAM y le seguimos tirando datos, ocupara toda la memoria e incluso ocupara SWAP (peligroso para mi gusto).
- TMPFS no crece dinamicamente, asi que si lo usamos como en el ejemplo, nunca nos iremos del limite de 10 MB, pero logicamente obtendremos los mismos errores al quedarnos sin espacio que con una particion llena en disco. No usa SWAP, por ende es el mas seguro de los dos.
Logicamente, podemos montar una particion con cualquiera de los dos sistemas al inicio en /etc/fstab como cualquier otro sistema de archivos.
Y por ultimo, una obviedad: al ser ambos sistemas de archivos alojados en la RAM, al desmontarlos o al reiniciar el equipo perdemos los datos, asi que hay que copiar los datos a algun otro lugar antes de desmontar o reiniciar.
El uso personal que le doy a todo esto es para almacenar las sesiones de php en un directorio especial, en el php.ini se puede cambiar con la directiva:
Eso es todo amigos !
Como montar ambos ? aqui va para los impacientes nuevamente:
mkdir -p /mnt/tmp
mount -t tmpfs -o size=10m tmpfs /mnt/tmp
o sino para ramfs, de la siguiente forma:
mkdir -p /mnt/ram
mount -t ramfs -o size=10m ramfs /mnt/ram
Con ambos comandos disponemos de 10 MB en RAM para escribir, pero con las siguientes diferencias:
- RAMFS crece dinamicamente, asi que si tenemos 1 GB de RAM y le seguimos tirando datos, ocupara toda la memoria e incluso ocupara SWAP (peligroso para mi gusto).
- TMPFS no crece dinamicamente, asi que si lo usamos como en el ejemplo, nunca nos iremos del limite de 10 MB, pero logicamente obtendremos los mismos errores al quedarnos sin espacio que con una particion llena en disco. No usa SWAP, por ende es el mas seguro de los dos.
Logicamente, podemos montar una particion con cualquiera de los dos sistemas al inicio en /etc/fstab como cualquier otro sistema de archivos.
Y por ultimo, una obviedad: al ser ambos sistemas de archivos alojados en la RAM, al desmontarlos o al reiniciar el equipo perdemos los datos, asi que hay que copiar los datos a algun otro lugar antes de desmontar o reiniciar.
El uso personal que le doy a todo esto es para almacenar las sesiones de php en un directorio especial, en el php.ini se puede cambiar con la directiva:
session.save_path = "/tmp/ramdisk"
Eso es todo amigos !
Editor Vim (explicación sencilla)
Increíblemente, después de años de usar linux para distintas cosas, recién ahora me pongo a ver como usar más o menos el famoso editor Vim.
El editor consta de 2 modos: Inserción y Comando
Para entrar en el modo Inserción basta con presionar la tecla "Insert" en nuestro teclado, y abajo a la izquierda vim nos avisa con "-- INSERT --" o si presionamos dos veces "Insert" con "-- REPLACE --" (obviamente con este último modo reemplazamos el texto).
Para salir del modo Inserción presionamos la tecla "Esc".
Cabe aclarar que vim se inicia en modo comando.
Los comandos que aprendi hasta el momento (los que me sirven a mi por lo menos) son los siguientes (nótese la diferencia entre mayúsculas y minúsculas):
Para borrar un número de lineas, se puede presionar "d" mas el nro de lineas que deseamos borrar (ej: 3) y luego "d" nuevamente.
Tambien en el modo comando, al ingresar "dos puntos" o ":" podemos tipear diversos comandos, como pueden ser:
Y para mi asombro (gracias Carlitos), vim tiene tabs. Para usar este modo debemos invocar vim de la siguiente manera:
Luego nos movemos entre tabs con los comandos :tabn y :tabp (para next/siguiente o previous/anterior respectivamente)
Tambien una vez dentro de vim se puede usar el comando :tabnew nombrearchivo para abrir un nuevo tab con otro archivo.
Por supuesto existen muchos mas comandos y tips para vim, estos son simplemente los comandos que permiten un uso básico (y que como ya dije, me sirven a mi).
Espero que les sea de utilidad
Saludos !
El editor consta de 2 modos: Inserción y Comando
Para entrar en el modo Inserción basta con presionar la tecla "Insert" en nuestro teclado, y abajo a la izquierda vim nos avisa con "-- INSERT --" o si presionamos dos veces "Insert" con "-- REPLACE --" (obviamente con este último modo reemplazamos el texto).
Para salir del modo Inserción presionamos la tecla "Esc".
Cabe aclarar que vim se inicia en modo comando.
Los comandos que aprendi hasta el momento (los que me sirven a mi por lo menos) son los siguientes (nótese la diferencia entre mayúsculas y minúsculas):
h: mueve el cursor hacia la izquierda
j: mueve el cursor hacia abajo
k: mueve el cursor hacia arriba
l: mueve el cursor hacia la derecha
$: mueve el cursor al final de la linea
0: mueve el cursor al principio de la linea
v: marca una selección de texto
CTRL+v: marca una selección de texto libre (modo columna, similar a UltraEdit)
y: copia el texto seleccionado
x: corta el texto seleccionado
p: pega el texto después del cursor
P: pega el texto antes del cursor
u: deshace los cambios
U: deshace los cambios pero solo en la línea actual
CTRL+r: rehace los cambios
Para borrar un número de lineas, se puede presionar "d" mas el nro de lineas que deseamos borrar (ej: 3) y luego "d" nuevamente.
Tambien en el modo comando, al ingresar "dos puntos" o ":" podemos tipear diversos comandos, como pueden ser:
:q (salir)
:q! (salir sin guardar cambios)
:w (guardar archivo)
:wq (salir guardando el archivo)
:e nombre_archivo (abrir otro archivo en la misma consola)
:bn (proximo buffer/archivo, usado para moverse entre archivos si tenemos mas de uno abierto)
:bp (igual que :bn pero para ir al buffer previo)
Y para mi asombro (gracias Carlitos), vim tiene tabs. Para usar este modo debemos invocar vim de la siguiente manera:
vim -p archivo1.txt archivo2.txt archivo3.txt
Luego nos movemos entre tabs con los comandos :tabn y :tabp (para next/siguiente o previous/anterior respectivamente)
Tambien una vez dentro de vim se puede usar el comando :tabnew nombrearchivo para abrir un nuevo tab con otro archivo.
Por supuesto existen muchos mas comandos y tips para vim, estos son simplemente los comandos que permiten un uso básico (y que como ya dije, me sirven a mi).
Espero que les sea de utilidad
Saludos !
Problema con Samba y Windows Vista (NTLMv2)
Sin demasiada introducción (los impacientes, contentos), hay que cambiar estas líneas por las siguientes:
por simplemente
Además en los shares, lo mismo:
Además es necesario ajustar en las máquinas Vista lo siguiente:
1) Abrir la consola "Local Security Policies" ejecutando el comando "secpol.msc" (solo disponibles en la version Bussiness y Ultimate).
2) Ir a Local Policies –> Security Options –> Network Security: LAN Manager authentication level.
3) Cambiar el valor de "NTLMv2 responses only" a "LM and NTLM – use NTLMV2 session security if negotiated".
Si tienen la version Home de Vista (que no tiene la consola secpol.msc como dije mas arriba) se puede cambiar el valor directamente desde el registro ejecutando el comando "regedit" y ajustando el siguiente valor de 3 a 1:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\LMCompatibilityLevel
Como siempre, mucho cuidado al editar el registro a mano.
Esta configuración me permitió tener un mix de clientes con XP y Vista y seguir usando el sistema de autenticación con usuarios simples
PD: Disculpen, pero tengo Windows en ingles :-/
[global]
valid users = %S
por simplemente
[global]
users = %S
Además en los shares, lo mismo:
[www]
comment = sites
path = /www
users = %S # esta linea estaba con "valid users" antes
public = no
writable = yes
printable = no
create mask = 0700
Además es necesario ajustar en las máquinas Vista lo siguiente:
1) Abrir la consola "Local Security Policies" ejecutando el comando "secpol.msc" (solo disponibles en la version Bussiness y Ultimate).
2) Ir a Local Policies –> Security Options –> Network Security: LAN Manager authentication level.
3) Cambiar el valor de "NTLMv2 responses only" a "LM and NTLM – use NTLMV2 session security if negotiated".
Si tienen la version Home de Vista (que no tiene la consola secpol.msc como dije mas arriba) se puede cambiar el valor directamente desde el registro ejecutando el comando "regedit" y ajustando el siguiente valor de 3 a 1:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\LMCompatibilityLevel
Como siempre, mucho cuidado al editar el registro a mano.
Esta configuración me permitió tener un mix de clientes con XP y Vista y seguir usando el sistema de autenticación con usuarios simples
PD: Disculpen, pero tengo Windows en ingles :-/
Subscribe to:
Posts (Atom)
Followers
About me
- coke
- Santa Fe, Argentina
- Programador Web, PHP, MySQL, JQuery, Administrador Linux. LAMP, Lighttpd, Nginx.