sábado, marzo 01, 2014

Wget para descargar todos los ficheros txt enlazados desde una página

Tanto me ha costado que vale la pena dejar apuntado por alguna parte cómo hacer esto. Para descargar únicamente los archivos txt que están enlazados desde una página y que están en un único directorio evitando navegar por todo el site podemos usar este comando

wget -I "/static/public/constellations/txt/" -X * -r -A *.txt -P . http://www.iau.org/public/themes/constellations/


  • -I Indica el directorio que queremos incluir
  • -X Indica los directorios que queremos excluir (todos)
  • -A *.txt indica el patrón de archivos que queremos descargar
  • -P . indica la localización donde queremos dejar los archivos

martes, febrero 11, 2014

Mover cadenas en una línea con el comando sed

Sed es un útil comando para manipular cadenas de un archivo.

En mi caso me encontraba con la necesidad de alterar unas sentencias update de una sql de la siguiente forma

UPDATE VIDEOTECA SET 
    TAGS = 'CIENCIA-FICCIÓN, ESPACIO, EXTRATERRESTRES, MICROBIO, ENFERMEDAD, PLAGA, DISTRI U', DISTRIBUIDORA = NULL
WHERE (VIDEOID = 326);

Que debería convertir en:

UPDATE VIDEOTECA SET 
    TAGS = 'CIENCIA-FICCIÓN, ESPACIO, EXTRATERRESTRES, MICROBIO, ENFERMEDAD, PLAGA', DISTRIBUIDORA = 'U'
WHERE (VIDEOID = 326);

Así durante más 500 líneas.

Como podéis ver en realidad lo que quiero es coger el valor que hay tras   'DISTRI' y moverlo donde está el NULL (básicamente, para actualizar los valores de una tabla moviendo uno de los tags a una nueva columna)

SED nos permite recorrer línea a línea nuestro archivo buscando patrones y, entre otras operaciones posibles, realizar sustituciones. Para ello utiliza expresiones expresiones regulares. Como nuestra cadena está muy cerrada es fácil determinar una expresión regular que detecte la cadena que queremos mover y mediante los argumentos \1 (\2 si hubiera más expresiones) mover las partes variables a donde queramos

sed -r "s/, DISTRI (.*)', DISTRIBUIDORA = NULL/', DISTRIBUIDORA = '\1'/" archivo_origen.sql > archivo_destino.sql

Revisando rápidamente el comando

  • sed [parámetros] "s/patron/sustitucion/" archivo_origen > archivo destino
  • -r para que use las expresiones regulares extendidas
  • s para que realice las operaciones de sustituciones
  • / son los separadores
  • , DISTRI (.*)', DISTRIBUIDORA = NULL el patrón que queremos detectar, la parte en negrita detecta cualquier cadena de caracteres que previa que luego vaya seguida de ', DISTRIBUIDORA = NULL y la almacena en el token \1
  • ', DISTRIBUIDORA = '\1'el patrón por el que queremos sustuir. Usamos el token  \1 para recuperar la primera variable detectada en el patrón de búsqueda
Otro ejemplo encontrado durante el mismo desarrollo y que es algo más complicado
Cambiar este sql

UPDATE VIDEOTECA SET 
    TAGS = 'DistriSONY, Drama, Rural, Años 50, Adolescencia, Cine, Jeff Bridges, Ben Johnson', DISTRIBUIDORA = NULL
WHERE (VIDEOID = 1917);

por este otro

UPDATE VIDEOTECA SET 
    TAGS = 'Drama, Rural, Años 50, Adolescencia, Cine, Jeff Bridges, Ben Johnson', DISTRIBUIDORA = 'SONY'
WHERE (VIDEOID = 1917);

El comando

sed -r "s/Distri([A-Za-z0-9]*), (.*)', DISTRIBUIDORA = NULL/\2', DISTRIBUIDORA = '\1'/" videoteca-update.sql > videotec-distri-update.sql




sábado, junio 08, 2013

Copias de seguridad de tarjetas SD desde linux: guardando nuestra Raspberry Pi

Vista la facilidad con la que se corrompen la tarjetas en mi última instalación completa me he decidido a hacer una copia de seguridad de la RPi para poder restaurarla completamente en unos momentos.

De hecho, como lo utilizo de servidor multimedia y siempre me doy cuenta en el momento de estar sentado frente a la tele, me he creado una copia de respaldo en otra tarjeta para poder cambiarla y en el momento disfrutar de la película.

Usamos una máquina linux y un par de comandos rápidos:

Para hacer la copia de seguridad, me aseguro de meter la tarjeta desmontar las particiones con umount y hacer las copias de seguridad así:

$umount /dev/sdb1
$umount /dev/sdb2
$sudo dd if=/dev/sdb | gzip > /path/a/tu/imagen/nombre.bkp.gz

Y para restaurarla en otra tarjeta o en la misma:

$umount /dev/sdb1
$umount /dev/sdb2
$ sudo gzip -dc /path/a/tu/imagen/nombre.bkp.gz | dd of=/dev/sdb

Puede que tu sistema no monte la tarjeta en /dev/sdb ajústalo a tus necesidades.

viernes, junio 07, 2013

Raspberry Pi + Deluge Torrent + MiniDLNA = Happy Sony PS3

El gran partido que le estoy sacando a la Rasberry Pi es en combinación con el servidor de torrent y la PS3. Ahora puedo cargar contenidos desde mi móvil en el servidor de torrent de la RPi y luego consumirlos directamente desde la PS3.

Para ello basta con instalar un servidor multimedia en la RPI que sirva los contenidos. La configuración es muy sencilla.

$ sudo apt-get install minidlna

Edita el archivo de configuración

$sudo nano /etc/minidlna.conf

Busca las siguientes líneas y dale los valores que necesitas

media_dir=/media/usbdisk/torrent #directorio donde debe buscar los archivos
root_container=V   #para que sólo busque archivos de vídeo
friendly_name=RPi  #nombre que verás de la RPi
inotify=yes        #para que revise siempre si aparecen nuevos archivos

Reinicia el servidor para que se lleven a cabo los cambios y escanee las carpetas.

$sudo service minidlna restart
$sudo service minidlna force-reload 

Ya puedes arrancar tu PS3 y buscar tu RPI para disfrutar de tus vídeos.

Instalar torrent en Raspberry Pi - Parte II: Instalar el servidor de torrent (Deluge)

Aunque hay otros servidores de torrent más populares en linux mi preferido sigue siendo Deluge. Es un poco más complicado de configurar pero resulta ser bastante menos voraz con la conexión (sigo pudiendo navegar con mi red) dando una tasas de descarga muy altas. Además permite acceder al servidor desde un sencillo navegador, desde un cliente gráfico en otra máquina o incluso desde un teléfono android usando Transdroid. Esta última opción es especialmente útil porque el propio Transdroid dispone de un buscador así que el método de uso se vuelve especialmente sencillo: arrancamos en nuestro móvil transdroid, buscamos lo que queremos y directamente lo ponemos a descargar en nuestra RPi.

Vamos al método:

Fija la IP
Antes de todo sería conveniente que fijaras la dirección ip de tu RPi, si no será complicado que puedas conectarte a ella desde después. Tienes las instrucciones en este artículo.

Asegurar el espacio en disco
Si no lo has hecho antes es también importante que instales un disco duro externo que permita tener espacio de sobra para tus descargas. En el artículo anterior te explico cómo hacerlo.

En mi caso las descargas se llevarán a cabo en /media/usbdisk/torrent/. Asegúrate que el directorio que escojas exista y sea accesible para tu usuario pi.

Instalar y configurar Deluge server
Las instrucciones están extraídas de la propia web de Deluge y adaptadas a mi caso particular.

Podemos usar el paquete que se distribuye en los repositorios

$sudo apt-get install deluged deluge-console deluge-web

Hacemos una corta ejecución para que genere los archivos de configuración del usuario

$deluged
$pkill deluged

Añadimos un usuario que luego utilizaremos para conectarnos al servidor a través de la red:

$ echo "pi:pipass:10" >> ~/.config/deluge/auth


Ahora viene la configuración del arranque del servidor que es algo más delicada. Tenemos que crear un par de archivos:

$ sudo nano /etc/default/deluge-daemon

y pega este contenido dentro para que sea el usuario pi el que ejecuta deluge

# Configuration for /etc/init.d/deluge-daemon

# The init.d script will only run if this variable non-empty.
DELUGED_USER="pi"    

# Should we run at startup?
RUN_AT_STARTUP="YES"

Ahora creamos el script de arranque, basta con editar el siguiente archivo:

$ sudo nano /etc/init.d/deluge-daemon

Y completarlo con el siguiente contenido:

#!/bin/sh
### BEGIN INIT INFO
# Provides:          deluge-daemon
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Should-Start:      $network
# Should-Stop:       $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Daemonized version of deluge and webui.
# Description:       Starts the deluge daemon with the user specified in
#                    /etc/default/deluge-daemon.
### END INIT INFO

# Author: Adolfo R. Brandes 

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Deluge Daemon"
NAME1="deluged"
NAME2="deluge"
DAEMON1=/usr/bin/deluged
DAEMON1_ARGS="-d"             # Consult `man deluged` for more options
DAEMON2=/usr/bin/deluge-web
DAEMON2_ARGS=""               # Consult `man deluge-web` for more options
PIDFILE1=/var/run/$NAME1.pid
PIDFILE2=/var/run/$NAME2.pid
UMASK=022                     # Change this to 0 if running deluged as its own user
PKGNAME=deluge-daemon
SCRIPTNAME=/etc/init.d/$PKGNAME

# Exit if the package is not installed
[ -x "$DAEMON1" -a -x "$DAEMON2" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME

# Load the VERBOSE setting and other rcS variables
[ -f /etc/default/rcS ] && . /etc/default/rcS

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

if [ -z "$RUN_AT_STARTUP" -o "$RUN_AT_STARTUP" != "YES" ]
then
   log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it."
   exit 0
fi

if [ -z "$DELUGED_USER" ]
then
    log_warning_msg "Not starting $PKGNAME, DELUGED_USER not set in /etc/default/$PKGNAME."
    exit 0
fi

#
# Function that starts the daemon/service
#
do_start()
{
   # Return
   #   0 if daemon has been started
   #   1 if daemon was already running
   #   2 if daemon could not be started
   start-stop-daemon --start --background --quiet --pidfile $PIDFILE1 --exec $DAEMON1 \
      --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK --test > /dev/null
   RETVAL1="$?"
   start-stop-daemon --start --background --quiet --pidfile $PIDFILE2 --exec $DAEMON2 \
      --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK --test > /dev/null
   RETVAL2="$?"
   [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] || return 1

   start-stop-daemon --start --background --quiet --pidfile $PIDFILE1 --make-pidfile --exec $DAEMON1 \
      --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK -- $DAEMON1_ARGS
   RETVAL1="$?"
        sleep 2
   start-stop-daemon --start --background --quiet --pidfile $PIDFILE2 --make-pidfile --exec $DAEMON2 \
      --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK -- $DAEMON2_ARGS
   RETVAL2="$?"
   [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] || return 2
}

#
# Function that stops the daemon/service
#
do_stop()
{
   # Return
   #   0 if daemon has been stopped
   #   1 if daemon was already stopped
   #   2 if daemon could not be stopped
   #   other if a failure occurred

   start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $DELUGED_USER --pidfile $PIDFILE2
   RETVAL2="$?"
   start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $DELUGED_USER --pidfile $PIDFILE1
   RETVAL1="$?"
   [ "$RETVAL1" = "2" -o "$RETVAL2" = "2" ] && return 2

   rm -f $PIDFILE1 $PIDFILE2

   [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] && return 0 || return 1
}

case "$1" in
  start)
   [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME1"
   do_start
   case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
   esac
   ;;
  stop)
   [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME1"
   do_stop
   case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
   esac
   ;;
  restart|force-reload)
   log_daemon_msg "Restarting $DESC" "$NAME1"
   do_stop
   case "$?" in
     0|1)
      do_start
      case "$?" in
         0) log_end_msg 0 ;;
         1) log_end_msg 1 ;; # Old process is still running
         *) log_end_msg 1 ;; # Failed to start
      esac
      ;;
     *)
        # Failed to stop
      log_end_msg 1
      ;;
   esac
   ;;
  *)
   echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
   exit 3
   ;;
esac

:

Convertimos el archivo en ejecutable...

$sudo chmod 755 /etc/init.d/deluge-daemon

...con el siguiente comando hacemos que se ejecute en cada arranque...

$sudo update-rc.d deluge-daemon defaults


Y ya podemos arrancar el servidor...

$sudo service deluge-daemon start


Ya deberías poder conectar con el servidor abriendo tu navegador y visitando la dirección http://192.168.0.254:8112/ (ajustando la IP a la de tu RPi). Es el momento adecuado para que configures la carpeta donde quieres que realicen las descargas y demás.

Configurando Deluge para acceder con otros clientes
Habilitamos el acceso remoto para poder acceder desde nuestro nuestro portatil con el GUI

$deluge-console "config -s allow_remote True"
$deluge-console "config allow_remote"
$sudo service deluge-daemon restart

Ya puedes configurar tu cliente de Deluge en tu portátil.

Para configurar Transdroid debes asegurarte que el servidor web se conecta automáticamente al servidor local de Deluge. Lo apagamos, editamos la configuración y lo volvemos a arrancar.

$sudo service deluge-daemon restart
$nano ~/.config/deluge/web.conf

Busca la siguiente línea y la cambias así
"default_daemon": "" 
"default_daemon": "127.0.0.1:58845"

Protege de cambios el archivo web.conf para que no se actualice en cada arranque:

$chmod 444 ~/.config/deluge/web.conf

Ya puedes reiniciar el servidor y conectar con Transdroid.

$sudo service deluge-daemon start

Instalar torrent en Raspberry Pi - Parte I: Configurar un disco duro por usb

Uno de los aspectos más interesantes de la RPI es su bajo consumo y su capacidad para realizar tareas que no necesitan demasiado capacidad de cálculo. En este caso pretendo evitar tener que dejar el pc de escritorio encendido para una tarea tan sencilla como descargar torrents. Como una tarjeta SD no proporciona mucho espacio, lo conveniente es añadir un disco externo por USB. Así pues divido el tutorial en dos partes: la configuración de un disco duro y la instalación del servicio de torrent.

Montar un disco duro fijo
Ante todo dejar claro que yo utilizo la RPI únicamente por línea de comandos y ssh a través de la red, no tengo monitor enganchado. Asegúrate de que sabes conectar con tu terminal antes de empezar. También parto de que tienes un disco duro listo y formateado, en mi caso lo tengo formateado en ext4 para poder aprovecharme de todas las ventajas de ese sistema. También serviría un disco fat e incluso ntfs aunque la configuración variaría ligeramente. Consulta este enlace si tienes dudas respecto a que opciones debes poner más adelante en el fstab.

Lo primero que vamos a crear es un punto de montaje, es decir, el directorio en el que estará disponible el nuevo disco duro. Por convención se suelen usar los directorio /mnt/nombre_disco o /media/nombre_disco. Lo hacemos con en siguiente comando:

$sudo mkdir /media/usbdisk
$sudo chmod 777 /media/usbdisk

Es importante el segundo comando para asegurarnos que una vez montados el disco cualquier usuario podrá añadir o borrar carpetas o archivos en él. Puede parecer una brecha de seguridad (y de hecho no es nada recomendable en un sistema serio) pero es la forma más sencilla de que tanto el usuario pi (el que usamos normalmente) como el del servicio torrent puedan acceder a los archivos sin problemas. Aprende algo más sobre el sistema de permisos unix si tienes curiosidad.

Para terminar vamos a crear un enlace sencillo que nos permitirá acceder desde nuestro directorio de usuario al disco duro de una forma más directa. Este paso es opcional pero ¡así aprendes a hacer un enlace!

$ln -s /media/usbdisk/ /home/pi/usbdisk

Vale, ya tenemos el punto de enlace listo. Ahora toca montar el disco duro. Encendemos la alimentación si es necesario y conectamos el disco por usb. Después de un ejecuta:

$sudo blkid

Debería aparecerte algo así:


/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="3312-932F" TYPE="vfat" 
/dev/mmcblk0p2: UUID="b7b5ddff-ddb4-48dd-84d2-dd47bf00564a" TYPE="ext4" 
/dev/sda1: UUID="497daa7e-50f7-4d8b-8013-6c02ad83056d" TYPE="ext4" 


Lo que aparece como /dev/sda o /dev/sdb son los dispositivos de disco duro, lo que aparece como /dev/sda1 /dev/sda2 o /dev/sdb1... son las particiones que tiene tu disco (todo en linux es un archivo). En mi caso sólo hay un disco (/dev/sda) con una única partición (/dev/sda1). Pues bien ahora lo que vamos a hacer es montar esa partición con el comando mount.

$sudo mount /dev/sda1 /media/usbdisk

Asegurate de poner el /dev/sdxx correpondiente a lo que hayas obtenido en el paso anterior... y si no ves ningún mensaje de error ¡ya está! ¡disco montado! puedes ir a la carpeta y comprobar que funciona, creando unos archivos y carpetas. También puedes usar este comando para obtener un poco más de información:

$ df -T
Filesystem     Type     1K-blocks     Used Available Use% Mounted on
rootfs         rootfs     7591392  1603680   5602248  23% /
/dev/root      ext4       7591392  1603680   5602248  23% /
devtmpfs       devtmpfs    224436        0    224436   0% /dev
tmpfs          tmpfs        44900      224     44676   1% /run
tmpfs          tmpfs         5120        0      5120   0% /run/lock
tmpfs          tmpfs        89780        0     89780   0% /run/shm
/dev/mmcblk0p1 vfat         57288    16872     40416  30% /boot
/dev/sda1      ext4     115379200 11968804 103410396  11% /media/usbdisk

En la última línea puedes ver mi partición /dev/sda1 en formato ext4 montada en /media/usbdisk y con sólo el 11% de su capacidad usada.

Montarlo automáticamente al arrancar
Evidente no vamos a estar pendientes cada vez que arranquemos la RPI de montar manualmente el disco duro. Para que lo cargue automáticamente en el inicio debemos incluir en el fstab ¿Cómo? muy sencillo. Primero asegúrate de desmontar el disco duro:

$sudo umount /dev/sda1

Editamos el archivo fstab:

$sudo nano /etc/fstab

...y le añadimos la siguiente línea al final:

/dev/sda1  /media/usbdisk  ext4  defaults  0  0

Teniendo en cuenta que el sda debe ser el tuyo. Donde pone ext4 es por mi sistema de archivos, si el tuyo es fat deberíamos poner vfat y si es ntfs, pues eso, ntfs. Consulta el enlace de arriba si tienes dudas.

Si lo hemos hecho todo bien ahora podemos referirnos directamente a la carpeta de destino para montar el sistema:

$sudo mount /media/usbdisk

¡Otro paso dado! Ahora cada vez que arranque y el disco duro esté pinchado lo montará automáticamente en esa localización. 

Ya casi lo podríamos dejar así pero le vamos a dar una vuelta de tuerca más. Tal vez ya se te haya ocurrido ¿qué pasa si pongo varios discos duros?¿o si lo cambio de puerto USB? ¿cómo sabe qué disco tiene que montar en cada punto?

Pues la respuesta corta es "no lo sabe". Al menos de momento. Tenemos que especificarle que no nos sirve cualquier disco duro si no que es uno en concreto el que queremos montar en /media/usbdisk. Lo primero será indentificar la partición con un código que se genera al crearla. Para obtener el UUID podemos usar el mismo comando de antes:


/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="3312-932F" TYPE="vfat" 
/dev/mmcblk0p2: UUID="b7b5ddff-ddb4-48dd-84d2-dd47bf00564a" TYPE="ext4" 
/dev/sda1: UUID="497daa7e-50f7-4d8b-8013-6c02ad83056d" TYPE="ext4" 

En negrita puedes ver la UUID de mi disco, en tu caso puede ser igual o más corta lo importante es identificar la partición con el sdxx correpondiente. Ahora copiamos esa cadena y la sustituimos en la línea del fstab:

UUID=497daa7e-50f7-4d8b-8013-6c02ad83056d /media/usbdisk  ext4  defaults  0  0

...y lo probamos con mount y umount. Si no nos da problemas ¡ya está todo! Tenemos un disco identificado unívocamente que se montará en cada arranque en una carpeta en concreto. Todo está listo para instalar nuestro cliente de Torrent.