lunes, 23 de noviembre de 2015

Notas de javascript

"With great power there must also come great responsibility!"
— Stan Lee

A continuación unas anotaciones que tenía por aquí acerca de Javascript, ese lenguaje tan interesante y potente a la par que lleno de peligros.





  • Declarar un elemento en un array puede significar la creación implícita de elementos de índices inferiores pese a no ser declarados. array[100]=21; Se crearán los índices no definidos, desde 0 hasta 100. Por este motivo puede ser mejor idea usar las funciones push y pop en los array si queremos evitar este efecto
  • El borrado de un elemento de array en javascript elimina el valor, propiedades, etc, no la entrada en si. delete array[1]; longitud tras borrado no disminuye. array[1] será undefined    
  • false, NaN, "", null en javascript se evalúan como false
  • trabajamos con referencias 
  • parseInt analiza una cadena en busca de numeros para tratarlos como enteros. Se detiene el análisis tan pronto como se encuentra un NaN y se queda con lo que haya conseguido analizar.
  • no hay character, son cadenas de texto.
  • Examinando código podemos encontrarnos con frecuencia con !! (doble negación). Es una forma de devolver el valor booleano de una variable. Es como un casting a booleano.
  • Los operadores booleanos no tienen por qué devolver un booleano, sino que devuelven el último valor de todas las condiciones en el caso del &&. Esto justifica el uso de !! que comentamos anteriormente.
  • && y || sirve para detener la evaluación de condiciones en caso de que ya haya evidencia del resultado de la condición.
  • Iteración 'foreach': for(elemento in array) . Debemos tener cuidado ya que el array es un objeto, por lo tanto susceptible de que se le pueda agregar una propiedad. En este caso la iteración podría detenerse al encontrarse índices (la propiedad) no numéricos.
  • Invocar la función sin sus parámetros, devuelve el código de la misma.
  • underscore.js es una librería de utilidades que trata de ampliar y hacer más robusto el lenguaje.
  • Fuera de una función una variable declarada tiene un ámbito global. Esto da pie a conflictos con diversos fragmentos de código. Es recomendable incluir las variables dentro de las funciones. Introducimos variables dentro de funciones anónimas autoejecutables para preservarlas del resto de código y librerías.
          
    (function(){ var foo = "Hi";})();
  • Para poner valores por defecto para los valores de los parámetros de una función usamos un OR:
    function myFunc(str){
        var str = str || "";

viernes, 9 de octubre de 2015

Ubuntu - limpiar Kernels antiguos

Hoy me ha tocado arreglar un portátil con Ubuntu instalado. Una cosa rara, teniendo en cuenta que en años nunca había fallado. ¿La edad? No. A la partición del Sistema le quedaban menos de 100 Mb de espacio. Eso hacía que no arrancara normalmente.

Después de limpiar casi 3 Gb de documentos/fotos/etc... que ya tenían su propio backup, se "arregló".

En cuanto he entrado al sistema de nuevo, he pasado la herramienta de analizador de discos para saber dónde se habían ido los Gigas y mi sorpresa cuando entre modules y headers de Kernels antiguos había casi ¡16 Gb!

Para limpiar estos Kernels antiguos, basta con ejecutar en la terminal el siguiente comando:

dpkg -l 'linux-*' | sed 
'/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* 
[^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge


Fuente: Ubuntu Cleanup: How to Remove All Unused Linux Kernel Headers, Images and Modules

domingo, 7 de junio de 2015

Trucos Transmission

Hace ya un par de meses que tengo puesta la Raspberry Pi y la verdad es que estoy encantado. Pero todo es mejorable y os voy a contar un par de cambios menores que acabo de hacer en la configuración del Transmission que creo que mejorarán lo que ya tengo a día de hoy.

Un breve apunte para recordar que Transmission es un cliente Torrent que tengo puesto como daemon en la Raspberry Pi y que lo tengo configurado para acceder remotamente desde navegador Web para poder añadir los ficheros .torrent.

Hasta ahora, con lo que viene por defecto y lo configurado tal y como explicaba en una entrada anterior, el modo de conseguir algo compartido era:
  • Desde cualquier dispositivo (PC, portátil,...) de mi Red buscaba por Internet el recurso compartido y bajaba localmente el fichero .torrent.
  • Entraba desde el navegador al cliente Transmission (IP de la Raspberry Pi + puerto 9091 configurado en el Transmission) con su usuario/contraseña y ahí subía el fichero local.
  • En la configuración del Transmission estaba puesto que iniciase automáticamente la descarga, así que en ese aspecto no había que hacer nada.
  • Borraba el fichero .torrent guardado en local.
  • Una vez terminada la descarga, desde el propio navegador eliminaba de la lista el torrent acabado.
  • El contenido descargado se me bajaba en una carpeta "descargas", pero hay veces en las que quería moverlo a algún otro sitio (para clasificarlo, por ejemplo) o borrarlo una vez visto (o incluso limpiar los ficheros adicionales que se te bajan). El caso es que como lo que se descarga lo hace el usuario daemon-transmission, o lo movía como root desde una consola SSH, o desde esa consola SSH como root cambiaba los permisos para poder moverlo (chmod 777).

Ahora vienen los cambios que he hecho para simplificar este proceso:

  1. Primero me he creado este script en la carpeta /home (dándole permisos para que pueda ser ejecutado por cualquiera) y lo he llamado "purge.sh" (¡OJO! Hay que cambiar "user:password" por el usuario y contraseña que se tenga configurado para el acceso remoto):
  2. #!/bin/sh
    
    # the folder to move completed downloads to
    
    # port, username, password
    SERVER="9091 --auth user:password"
    
    # use transmission-remote to get torrent list from transmission-remote list
    # use sed to delete first / last line of output, and remove leading spaces
    # use cut to get first field from each line
    TORRENTLIST=`transmission-remote $SERVER --list | sed -e '1d;$d;s/^ *//' | cut --only-delimited --delimiter=" "  --fields=1`
    
    transmission-remote $SERVER --list 
    
    # for each torrent in the list
    for TORRENTID in $TORRENTLIST
    do
        # check if torrent download is completed
        DL_COMPLETED=`transmission-remote $SERVER --torrent $TORRENTID --info | grep "Percent Done: 100%"`
    
        # check torrents current state is
        STATE_STOPPED=`transmission-remote $SERVER --torrent $TORRENTID --info | grep "State: Seeding\|Stopped\|Finished\|Idle"`
        
        # if the torrent is "Stopped", "Finished", or "Idle after downloading 100%"
        if [ "$DL_COMPLETED" ] && [ "$STATE_STOPPED" ]; then
            # move the files and remove the torrent from Transmission
            transmission-remote $SERVER --torrent $TORRENTID --remove
        fi
    done 

  3. Ahora sí que hay que parar el servicio de Transmission:
  4. sudo /etc/init.d/transmission-daemon stop

  5. Y editar el fichero de configuración:
  6. sudo nano -w /var/lib/transmission-daemon/info/settings.json


    • Para que coja los ficheros .torrent de una carpeta automáticamente hay que añadir las opciones:
    • ...
      
      "watch-dir": "/media/extdisc/descargas",
      
      "watch-dir-enabled": true

    • Para que limpie de la lista automáticamente los torrent ya descargados, hay que modificar las opciones:
    • ...
      
      "script-torrent-done-enabled": true,
      
      "script-torrent-done-filename": "/home/user/purge.sh",
      
      ...
      
      "trash-original-torrent-files": true,
      
      ...

    • Finalmente, para que no haya problemas en mover o eliminar las descargas ya realizadas, hay que cambiar el valor de la opción umask, que por defecto es 18 y ponerlo a 0:
    • ...
      
      "umask": 0,
      
      ...

  7. Una vez guardados los cambios, se inicia de nuevo el servicio de Transmission:
  8. sudo /etc/init.d/transmission-daemon start


Ahora mi proceso de descargas es:

  • Desde cualquier dispositivo (PC, portátil,...) de mi Red busco por Internet el recurso compartido y bajo el fichero .torrent a la carpeta compartida en Red de la Raspberry Pi (en mi caso y por lo puesto en el fichero de configuración de Transmission a /media/extdisc/descargas).
  • Una vez descargado, si quiero moverlo (o eliminarlo) lo puedo hacer sin problemas desde cualquier dispositivo de mi Red sin necesidad de entrar en la consola SSH.

Por estos pequeños cambios ni soy más feliz ni se me soluciona la vida, pero son pequeñas cosas para ir mejorando poco a poco.

domingo, 22 de marzo de 2015

Raspberry Pi: gestiones remotas

En el post anterior he contado como he puesto en casa una Raspberry Pi como Servidor con diferentes funcionalidades. Lo que voy a contar a continuación es cómo acceder a este Servidor. O mejor dicho, cómo accedo yo.

Caso 1: acceso al disco duro externo

Este caso es el más simple y puede que el más usado después del DNLA (esto se hace automáticamente desde la televisión si lo soporta o desde una Play Station). Se puede usar el disco duro externo como carpeta de Red compartida entre los diferentes dispositivos, aparte de poder gestionar el contenido multimedia (por ejemplo borrando lo que ya hemos visto).

Desde un Sistema Operativo como Windows o Ubuntu, se puede explorar la Red desde el sistema de archivos y encontraremos la Raspberry Pi y dentro estará la carpeta que definimos para el disco duro externo (el nombre será el que se puso al configurar SAMBA). Además, pedirá credenciales de acceso, que serán las que se definieron en SAMBA.

Desde el móvil con Android, yo uso el programa ES explorador de archivos. Aquí simplemente habrá que añadir un nuevo Servidor con la IP fija de la Raspberry Pi y poner el usuario contraseña que se puso al configurar SAMBA. Ahora ya tenemos acceso también desde el móvil cuando estemos conectados a la Wifi de casa.

Caso 2: gestionar torrent

Para poder gestionar los torrents que se están bajando o para añadir nuevos torrent para bajar, se puede acceder desde cualquier navegador (incluido el del móvil) a la IP fija de la Raspberry Pi con el puerto 9091, es decir, en mi caso poniendo en la barra del explorador 192.168.0.16:9091. Pedirá credenciales que serán las definidas en la configuración del transmission-daemon.

Aparte de esto, existe una aplicación Android que aunque permite la misma funcionalidad, es más cómodo que andar metiendo siempre la IP y las credenciales. Se trata de Remote Transmission.

Caso 3: controlar la Raspberry Pi

Para poder controlar la Raspberry Pi, podemos, o bien conectar una pantalla, teclado y ratón directamente o aprovechar que está en Red y acceder por SSH.

Si lo hacemos desde Ubuntu, si tenemos SSH instalado, simplemente desde la terminal se ejecuta ssh pi@192.168.0.16. Nos pedirá contraseña y ya estaremos controlando la Raspberry Pi. Por supuesto, se puede utilizar cualquier otro programa SSH, pero esto es lo que de momento uso yo.

Desde Windows, también existen diferentes opciones, pero yo uso el programa PuTTY. Con esto me conecto mediante SSH y es lo mismo que desde Ubuntu o desde la propia Raspberry Pi.

Por último, desde Android también hay diferentes programas SSH, pero yo uso ConnectBot. Aparte de conexiones SSH también permite telnet,...

Una última cosa es que para facilitar el control de la Raspberry Pi desde Android me he bajado el teclado Hacker's Keyboard. Parece una tontería, pero este teclado de móvil tiene teclas tan usadas en modo terminal como las flechas, el ctrl, el tabulador,... y eso facilita mucho su uso.

Raspberry Pi: NAS + torrent

He tenido un finde largo con puente incluido y el tiempo no ha acompañado para salir, así que, como buen informático, me he dedicado a trastear. Aunque la idea original se debe a las quejas sobre el ruido de mi adorable mujer.

Originalmente tenía el PC de sobremesa siempre encendido porque lo usaba para tener un cliente torrent y guardar series o películas (ambas cosas no tienen relación entre sí, las pelis son compradas y pasadas al ordenador, of course ;) ) que luego veíamos en la televisión (tiene opción UPnP). Además, teníamos una carpeta compartida en Red para poder intercambiar ficheros entre los distintos dispositivos de la casa (PC sobremesa, portátil, móviles,...). La cosa funciona muy bien, pero aparte de lo que consume un PC siempre encendido (no creo que sea para tanto, pero bueno), está el problema del ruido de ventiladores (también ayuda a que no está lo limpio que debería y ya tiene sus años).

Por otro lado, tengo una Raspberry Pi Model B (esta) desde hace un par de años muerta de risa en el cajón. En su día le puse un MAME y varios cientos de ROMs, así que de higos a brevas echo una partida a algún juego mítico, pero poco más.

También tengo varios discos duros externos, así que de momento para esto he usado uno de 500GB, que lo he usado más bien porque era el que tenía libre y me sirve para probar toda esta instalación. Como parece que lo he conseguido, a futuro lo reemplazaré por uno con más capacidad.

Lo único aparte que me he tenido que comprar es un hub de puertos USB con alimentación propia (este). Esto último es muy importante, porque la Raspberry Pi no provee suficiente energía por sus puertos USB y por tanto, para poner un ratón/teclado USB o incluso para un pendrive es suficiente, pero si se pone directamente un disco duro externo no lo reconoce (no le llega suficiente energía y es como si estuviese apagado).

Paso 0: Actualizar la Raspberry Pi

En su momento, cuando compré la Raspberry Pi me bajé el Sistema Operativo Raspbian y metí la imagen del mismo en una tarjeta SD que es con lo que funciona actualmente mi Raspberry Pi. Es el Sistema Operativo original y no es el único, pero a mi me ha servido y no he tenido que cambiarlo.

Lo que he hecho antes de nada es conectar el cable de Red y actualizar todo lo que tenía ya instalado, mediante APT:
sudo apt-get update
sudo apt-get upgrade

Paso 1: Poner IP fija


Tanto para el paso anterior como para este, he tenido que poner (temporalmente) un monitor y teclado/ratón a la Raspberry Pi.

En mi caso la Raspberry Pi tiene la IP asignada dinámicamente por DHCP, así que lo primero era saber qué IP tenía asignada. Para ello ejecutamos:
ifconfig


Y apuntamos la IP. No es obligatorio ponerle la misma IP que te ha asignado el router dinámicamente. Incluso algunos router pueden dar problemas porque tienen un rango de IPs fijas y otro rango para las dinámicas, pero en mi caso me ha servido ponerle la misma IP.

Lo siguiente es editar el fichero de configuración:
sudo nano -w /etc/network/interfaces

Uso nano como editor, pero puede usarse cualquier otro (vi, pico, emacs,...). En el fichero de configuración hay que cambiar donde poner:
iface eth0 inet dhcp

Poner:
iface eth0 inet static
address 192.168.0.16
netmask 255.255.255.0
gateway 192.168.0.1

Una vez puesta la IP fija y reiniciada la Raspberry Pi, ya no son necesarios el monitor y el teclado/ratón, ya que se puede acceder por SSH desde cualquier otro ordenador (o incluso desde el móvil).

Paso 2: Añadir disco duro externo

Lo primero que hice fue formatear el disco duro externo con formato ext4. No es indispensable que sea este formato (puede ser NTFS) y se puede hacer desde la propia Raspberry Pi, pero yo usé el programa GParted desde el Ubuntu del PC de sobremesa.

Ahora es cuando se conectan los diferentes elementos, así que apagué primero la Raspberry Pi para manejar todo y colocarlo ordenado en un rincón detrás de la tele:
  1. Enchufé el hub a la corriente. 
  2. El conector USB macho del hub lo conecté a la Raspberry Pi.
  3. La Raspberry Pi la conecté con el cable de Red al router.
  4. El disco duro externo lo conecté al hub.
  5. La Raspberry Pi puede ir conectada a la corriente con un enchufe propio o como lo hice yo, aprovechar un cable USB de cargador de móvil y lo conecté con el hub. De este modo hay un solo enchufe y es el hub el que da la energía a la Raspberry Pi.

Con esto último se enciende la Raspberry Pi y volvemos a entrar mediante SSH para seguir configurando.

Debería detectarse el disco duro externo, aunque no esté montado todavía. PAra comprobarlo, hay que ejecutar:
sudo fdisk -l


Saldrá una lista con los diferentes discos y particiones. En mi caso, las particiones de la tarjeta SD y el disco duro externo como /dev/sda1 (este identificador es el que hay que apuntar o tener en cuenta).

Creé una carpeta donde dejar montado permanentemente el disco duro externo y le di permisos totales:
sudo mkdir /media/extdisc
sudo chmod 777 /media/extdisc


Lo siguiente es editar el fichero de configuración de la tabla de discos:
sudo nano -w /etc/fstab


En este fichero hay que añadir la línea que en mi caso es:
/dev/sda1    /media/extdisc    ext4    defaults    0    0


Con esto se consigue que desde el inicio quede montado el disco duro externo en la carpeta que hemos creado para tal efecto. Para que este cambio tenga efecto, o bien se reinicia la Raspberry Pi o se ejecuta:
sudo mount -a


Paso 3: Instalar SAMBA

Para convertir la Raspberry Pi en un Servidor de ficheros o NAS, hay que instalar SAMBA:

sudo apt-get install samba samba-common-bin

Después hay que modificar su fichero de configuración:

sudo nano -w /etc/samba/smb.conf

Hay que añadir al final del fichero nuestra configuración para compartir el disco duro externo. En mi caso añadí:

[Raspberry Pi Externo]
comment = Disco duro externo en Raspberry Pi
path = /media/extdisc
writeable = Yes
create mask = 0777
directory mask = 0777
browseable = Yes
valid users @users
force user = pi

Con este cambio en teoría ya funciona, pero además se pueden añadir estos cambios en el mismo fichero (en el apartado [global]) para optimizar:

max xmit = 65535
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_SNDBUF=65535 SO_RCVBUF=65535
read raw = yes
write raw = yes
max connections = 65535
max open files = 65535

Además, para seguir optimizando (por tanto son cambios opcionales), se puede descomentar (borrar el # que tiene al principio de la línea):

security = user


Y comentar (añadir # o ; al inicio de la línea) todas las líneas activas del apartado "Share definitions" (homes, printers,...).

Una vez modificado el fichero y guardado, hay que añadir el usuario "pi" que hemos indicado al servicio SAMBA. Para ello:

sudo smbpasswd -a pi

Y nos pedirá una contraseña que habrá que ponerla dos veces. Este usuario y contraseña es el que hay que usar para acceder al disco duro externo desde cualquier otro dispositivo de la Red.

Finalmente se reinicia el servicio SAMBA con el comando:

sudo /etc/init.d/samba restart

Paso 4: Servidor DLNA

Para que la Raspberry Pi pueda servir el contenido multimedia del disco duro externo a la televisión, instalé el programa "miniDLNA":

sudo apt-get install minidlna


A continuación edité el fichero de configuración:

sudo nano -w /etc/minidlna.conf


Y modifiqué dos líneas fáciles de encontrar:

...
media_dir=/media/extdisc/
...
friendly_name=RaspberryPi
...


Esta última línea es para indicar qué nombre aparecerá en la televisión. Respecto al primero, es el que indica dónde se encuentran los ficheros que hay que indexar. En mi caso sólo existe ese directorio y quiero que se indexen todos, pero si hiciesen falta más de un origen, sería suficiente con añadir una nueva línea con el parámetro "media_dir=...". Además, se le puede indicar si sólo se quieren indexar ficheros de un tipo en concreto. Es decir, si se le añade al principio de la ruta una "V," sólo indexará vídeos y si se le añade una "A," sólo ficheros de audio. Un hipotético ejemplo:

...
media_dir=/media/extdisc/detodo/
media_dir=V,/media/extdisc/videos/
media_dir=A,/media/extdisc/musica/
...


Una vez guardados los cambios, hay que reiniciar el servicio:

sudo service minidlna restart


Y una última cosa importante, hay que indicarle que indexe:

sudo minidlna -R


Esto último tardará más o menos dependiendo de cuantos ficheros tenga que indexar. De todos modos, en este punto ya aparecerá en la televisión "RaspberryPi" y empezarán a aparecer paulatinamente todos los contenidos según se vayan indexando.

La parte mala de esto es que cada vez que añadamos un nuevo fichero o eliminemos uno existente, hay que "refrescar" para que se entere. Todavía no lo he usado suficiente y no tengo claro si es suficiente con re-indexar o si hay que reiniciar el servicio. Sólo lo he hecho una vez y he optado por reiniciar el servicio.


Paso 5: Descargador de torrents

Para convertirla Raspberry Pi en un Servidor de descarga de Torrents, le instalaremos el servicio (no la parte GUI) del cliente P2P Transmission:

sudo apt-get install transmission-daemon


Antes de editar el fichero de configuración, hay que tener en cuenta que el cliente torrent suele tener unos ficheros temporales mientras está el proceso de bajada en marcha y aunque no sea indispensable, es mejor crear una nueva carpeta en el disco duro externo para tener estos ficheros:

sudo mkdir /media/extdisc/temp
sudo chmod 777 /media/extdisc/temp


Ahora sí, se edita el fichero de configuración:

sudo nano -w /etc/transmission-daemon/settings.json


Dentro de este fichero hay que modificar las siguientes líneas para indicarle que guarde los ficheros en nuestro disco duro externo:

...
"download-dir": "/media/extdisc",
...
"incomplete-dir": "/media/extdisc/temp",
"incomplete-dir-enabled": true,
...


Además, le he dado permiso de acceso remoto para poder gestionar los torrents desde otro equipo de la Red:

...
"rpc-password": "Mi_Contraseña",
...
"rpc-username": "Mi_Usuario",
...
"rpc-whitelist-enabled": false, 
...


Una vez guardados los cambios, se reinicia el servicio:

sudo service transmission-daemon restart



Y esto es todo... o casi. En la siguiente entrada pondré cómo usar remotamente todo lo que hemos puesto en la Raspberry Pi.