sábado, 15 de diciembre de 2012

Uso de Dropbox desde RaspberryPi

... recuperamos un Super Poder!

Buenas tardes, nuestro amigo Rubén nos consulta vía Facebook:
Primero comentar que al próximo que me hable de usted ... bueno ... El caso es que estaba trabajando en un script que hiciera esto mismo, ya que Dropbox no tiene cliente nativo para arquitecturas ARM (nuestro querido Raspberry Pi), y justo en este momento Rubén nos informa de este script, veámoslo.

Si os pasáis por la lista de request features de Dropbox, veréis que hay muchas peticiones de que desarrollen un cliente para arquitecturas ARM, entre ellas la mía. Pero mientras que lo desarrollan, vamos a probar el script de esa web.
Lo primero antes de nada es tener una cuenta en Dropbox, desde aquí  puedes darte de alta.
Leemos un poco las características de dropbox_uploader y parece que las cumple todas, vayamos a nuestro RaspberryPi:
cd /usr/local/bin/
wget https://raw.github.com/andreafabrizi/Dropbox-Uploader/master/dropbox_uploader.sh
chmod +x dropbox_uploader.sh

Bien, fácil y sencillo, como a mi me gusta, continuemos:
./dropbox_uploader.sh

Nos pide la app key, esto forma parte de un sistema de autenticación llamado OAUTH, simplemente seguimos las instrucciones que nos dice y vamos a la URL https://www2.dropbox.com/developers/apps y hacemos clic en:
Y el siguiente formulario lo dejamos tal que así:
El nombre hay que dejarlo tal cual, es el que nos indica el script, evidentemente en la descripción ponemos lo que queramos. En mi caso he marcado Full Dropbox, porque pretendo darle un uso intensivo a varios directorios, si sólo vamos a usar un directorio con este script, marcaríamos App folder. Le damos a Create y nos tiene que salir la siguiente información:
La App key y el App secret son tuyos exclusivos, no se te ocurra ir por ahí publicándolos. Si volvemos al script, este nos pide primero la App key, luego el App secret y por último nos vuelve a pedir si vamos a darle acceso full o app, yo elijo 'f'. Para continuar con el proceso de autenticación OAUTH, nos indica una URL, que tendremos que visitar para dar acceso al script.
Le damos a permtir, volvemos al script y pulsamos intro.
Realmente el proceso es sencillísimo y seguramente te sonará de haber usado algo parecido alguna vez, como decía antes, este procedimiento se llama OAUTH, y lo he puesto pasito a pasito porque (con suerte) lo usaremos más de una vez. Podemos comprobar que funciona ejecutando por ejemplo:
# ./dropbox_uploader.sh list
 > Listing "/"... DONE
 [D] blogger
 [D] botijos
 [D] Camera Uploads
 [D] chorradas
 [D] compartido
 [D] curro
 [D] paraAndroid
 [F] parapapa.txt
 [D] Photos
 [D] Public
 [F] todo.kml
 [D] torrents
 [D] Videos

Hacer una copia de seguridad periódica de un directorio de Dropbox

El proceso anterior no tiene ningún mérito por mi parte, así que ahora vamos a darle la utilidad que buscaba desde el principio. Alguna vez te habrá pasado que has perdido las fotos del móvil al tocar donde no debías, o no te acordaste de hacer una copia al cambiarlo por otro. Para solucionar esto, los de Dropbox se pusieron las pilas y añadieron la opción de subida instantánea para la cámara de tu móvil, si no lo tienes ¿a que esperas?. Pero aún así, quiero que si Dropbox algún día le da por ser de pago, o por ser comprado por Microsoft, tener de antemano una copia del directorio "Camera Uploads" en mi NAS.
El NAS lo tengo montado en el RaspberryPi en /mnt/remoto , así que empezamos por crear un directrorio:
mkdir -p /mnt/remoto/copia-fotos-juanmol

y ahora el script /usr/local/bin/backup_dropbox.sh :
#!/bin/bash
# Programado por Juanmol para http://rsppi.blogspot.com
destino=/mnt/remoto/copia-fotos-juanmol
origen=Camera\ Uploads
listado=/tmp/listado.txt
log=/var/log/backup_dropbox.log

cd $destino
dropbox_uploader.sh list "Camera Uploads" > $listado

IFS=$'\n' ; for n in $(cat $listado | grep -v -e Listing -e DONE | sed 's/\ \[F\]\ //g');
do
        if [ -e $n ];
        then
                echo $n ya existe, no se hace nada ;
        else
                echo se copia $n a las $(date) >> $log ;
                dropbox_uploader.sh download "$origen/$n" ;
        fi
done
rm -r $listado

esta feo que yo lo diga, pero el script es precioso :) La primera vez que lo ejecutes tardará un siglo y medio en sincronizar (al menos en mi caso). Así que antes de ponerlo en el CRON, te recomiendo que lo ejecutes a mano, una vez. Cuando haya terminado, puedes añadir la siguiente linea al archivo /etc/crontab:
*/5 * * * *     root    /bin/bash /usr/local/bin/backup_dropbox.sh

y cada 5 minutos se descargará las fotos y vídeos nuevos que hagas con el móvil.
Todo el mérito es para los desarrolladores del script dropbox_uploader.sh yo sólo he añadido una sincronización.

Y esta ha sido nuestra primera petición vía Facebook ¿te animas? Pásate por este -> post.

25 comentarios:

  1. Se que suena descabellado, pero seria posible hacer una imagen de nuestro sistema y que la suba a Dropbox cada cierto tiempo?

    Se que debo de hacer una maquina virtual en mi PC y ponerle un debian, y usar tu post de copia. Pero si me puedo evitar eso y que se me suba una imagen .img a dropbox ya seria mas que la leche!

    ResponderEliminar
  2. Entrada interesante si señor. Me viene de perlas el dropbox_uploader.sh tanto para el raspberrypi como para la fonera 2.0n (tengo que adaptarlo, no funciona del todo).

    Por cierto, ayer Andrea ha actualizado el dropbox_uploader.sh mejorando la velocidad en los listados. Si tienes un Camera Uploads con muchísimos ficheros (como yo) y haces un "dropbox_uploader.sh list" vas a notar mucho la mejora.

    ResponderEliminar
  3. Esto me viene de perlas, tengo una carpeta donde voy dejando los torrents y con un script, adaptado del tuyo, las voy dejando en las raspberry en una ruta que el transmission audite y así las ponga en cola de descarga.

    ResponderEliminar
  4. Aporto otro script para subir un archivo a Dropbox y mantenga la estructura de directorio en Dropbox igual que la que hay en Raspberry pi

    -----------------------------------------------------
    #!/bin/bash
    DESTINO=Raspberrypi2k
    SCRIPT=/home/pi/Dropbox-Uploader-master/dropbox_uploader.sh
    MIDIR=$(pwd)

    cd $ORIGEN
    $SCRIPT upload $MIDIR/$1 $DESTINO/$MIDIR/$1
    -----------------------------------------------------

    uso
    ./backup_2_dropbox.sh archivoasubirtemp1.txt

    ResponderEliminar
  5. Gracias por el script, pero no tengo manera que me funcione.
    Inclusive ejecuto a mano
    pi@XXXXXXX ~ $ dropbox_uploader.sh download "Prueba1.txt"
    > Downloading "Prueba1.txt" to "Prueba1.txt"...

    > DONE

    y lo ejecute desde donde lo haga y poner DONE no se descarga o no se donde se descarga el fichero.

    Alguna idea ?

    Gracias

    ResponderEliminar
    Respuestas
    1. Vale nada ya he visto el fallo.
      No descarga ficheros vacíos que era mi caso como estaba creados (cosas de Windows).

      El Script funciona perfecto y con Cron la combinación ideal

      Gracias

      Eliminar
  6. Hola, al realizar los pasos que comentas me da un error en la parte del script que baja los ficheros, concretamente la línea dropbox_uploader.sh download "$origen/$n" ;, para que me funciones he tenido que poner dropbox_uploader.sh download "$origen/$n" /$destino/$n";
    Gracias por todas tus aportaciones

    ResponderEliminar
  7. Una pregunta. Yo tengo dos cuentas dropbox, una mia y otra de mi pareja. Si quiero ejecutar ese script para ambas, es posible?
    Imagino que tengo que crear toda la parte de autorizacion para cada cuenta, pero luego podrian convivir ambas en mi raspberry sin liarse?

    Gracias.

    ResponderEliminar
    Respuestas
    1. pues no lo tengo muy claro. Entre otras cosas relaciona el usuario que esta ejecutando el script. Así que necesitarías un usuario local en tu raspberrypi para cada cuenta de dropbox. Después todo es coser y cantar :)

      Eliminar
  8. Buenas! Este recurso de Dropbox me vino genial para mi Raspberry Pi. Lo implementé y funciona a las 1000 maravillas, te lo agradezco mucho.

    Respecto al script para sincronizar la carpeta, tengo una inquietud.. Tengo intenciones de hacer lo contrario al script que publicaste, es decir, en vez de descargar los nuevos archivos de Dropbox a la Raspberry, queria que el script fuera subiendo archivos a Dropbox a medida que estos se copiaban a una carpeta de la Raspberry, no se si me explico.
    La verdad, luego de darle varias vueltas durante horas al script que usaste, no logro encontrar la forma de hacer esto. Si se te ocurre algo estaria muy agradecido. Saludos!

    ResponderEliminar
    Respuestas
    1. Bueno, dos dias de intensivo "bashing" fueron suficientes como para ganar la batalla contra el maldito script (Yehe!). Con tu permiso, me tome el atrevimiento de utilizar.. practicamente todo tu código xD. Espero que que no te moleste...

      El script quedaria de la siguiente manera:

      -------------------------------------------

      #!/bin/bash
      echo Sincronizando con Dropbox...
      carpeta=/mnt/pendrive/dropbox
      listalocal=/tmp/local.txt
      listanube=/tmp/nube.txt
      repe="no"
      cd $carpeta
      ls > $listalocal
      dropbox_uploader.sh list > $listanube
      IFS=$'\n' ;

      for n in $(cat $listalocal)
      do
      repe="no";
      for m in $(cat $listanube | grep -v -e Listing -e DONE | sed 's/\ \[F\]\ //g');
      do
      if [ "$n" == "$m" ] ;
      then
      repe="si" ;
      fi
      done

      if [ $repe = "no" ];
      then
      #echo Cargando el archivo $n... ;
      dropbox_uploader.sh -q upload "$n" ;

      # else
      #echo El archivo $n ya esta sincronizado ;
      fi
      done
      echo COMPLETADO!

      -------------------------------------------
      (Creo, personalmente, que es horrible y estoy seguro que hay mejores formas de hacer esto.. Pero funciona! Y con eso me alcanza.)

      De esta forma, todo lo que se encuentre dentro de la carpeta /mnt/pendrive/dropbox, cuando el usuario o el cron lo disponga, se subirá al directorio raíz de la app en el dropbox (Esto fue por interes mio, hacerlo con una carpeta en particular, como lo hiciste vos en tu script requeriria de 2 o 3 modificaciones y podria resultar interesante también...).

      Aprovecho para agradecerte nuevamente, sin tu ayuda jamás lo hubiese logrado. Ahora a seguir recorriendo el blog e implementando tus otros "poderes" que me parecieron muy copados ;) Saludos!

      Eliminar
    2. gracias por el script, prometo robartelo ;)

      Eliminar
  9. Hola, soy el que pregunto como hacer esto para dos cuentas dropbox y creo que ya tengo la manera, que es creando dos archivos de configuracion, uno por cada cuenta, pero..... como no, me encuentro con pegas.(en serio que hay veces que odio profundamente a linux).
    Al hacer un dropbox_uploader.sh list "Carga de cámara" falla!! y todo porque mi carpeta esta en español y ACENTUADA!!!!, entonces el script la convierte en algo como /u00e001 o algo asi (solo la letra à) y como dice que no admite backslash / error al canto.

    Tras mucho luchar, me digo, renombro y le quito el acento, pasando a "Carga de camara" y funciona perfectamente. Pero...... el cliente android de dropbox, resulta que necesita la carpeta con acento, y cuando haces una nueva foto, crea la carpetita con el acento, asi que .... volvemos al principio.
    Alguna idea de como pasarle la palabra "cámara" acentuada como argumento?

    Gracias

    ResponderEliminar
    Respuestas
    1. ¿que locales tienes configuradas en el Raspberry? Ejecuta "locale" y pon aqui el resultado.

      Eliminar
  10. Hola juan
    Tengo es.ES UTF-8 o algo asi?
    Le he puesto un mail tambien, al que creo el script, ya que, en el propio dropbox, guarda la carpeta con el formato "Carga de C/u00e001mara".
    mira:
    "path": "/Cargas de c\u00e1mara/2003-06-10 09.58.24.jpg", "is_dir": false, "icon": "page_white_picture", "root": "dropbox", "mime_type": "image/jpeg", "size": "64.9 KB"

    Revisando el script, creo que se arreglaria si el comando Curl me dejara enviar \ (backslash)

    Un saludo.

    ResponderEliminar
    Respuestas
    1. A mi me pasa lo mismo, y no encuentro manera de arreglarlo. Es una pena porque es una idea genial y el script funciona perfecto, pero a los usuarios de android no nos vale para nada.
      locale
      LANG=es_ES@euro
      LANGUAGE=
      LC_CTYPE="es_ES@euro"
      LC_NUMERIC="es_ES@euro"
      LC_TIME="es_ES@euro"
      LC_COLLATE="es_ES@euro"
      LC_MONETARY="es_ES@euro"
      LC_MESSAGES="es_ES@euro"
      LC_PAPER="es_ES@euro"
      LC_NAME="es_ES@euro"
      LC_ADDRESS="es_ES@euro"
      LC_TELEPHONE="es_ES@euro"
      LC_MEASUREMENT="es_ES@euro"
      LC_IDENTIFICATION="es_ES@euro"
      LC_ALL=

      Dani, te ha contestado el desarrollador?

      Eliminar
  11. Resultado del locale:
    LANG=es_ES.UTF-8
    LANGUAGE=
    LC_CTYPE="es_ES.UTF-8"
    LC_NUMERIC="es_ES.UTF-8"
    LC_TIME="es_ES.UTF-8"
    LC_COLLATE="es_ES.UTF-8"
    LC_MONETARY="es_ES.UTF-8"
    LC_MESSAGES="es_ES.UTF-8"
    LC_PAPER="es_ES.UTF-8"
    LC_NAME="es_ES.UTF-8"
    LC_ADDRESS="es_ES.UTF-8"
    LC_TELEPHONE="es_ES.UTF-8"
    LC_MEASUREMENT="es_ES.UTF-8"
    LC_IDENTIFICATION="es_ES.UTF-8"
    LC_ALL=

    ResponderEliminar
    Respuestas
    1. hombre ... no es una solución pero yo tengo:
      LANG=en_GB.UTF-8
      LANGUAGE=
      LC_CTYPE="en_GB.UTF-8"
      LC_NUMERIC="en_GB.UTF-8"
      LC_TIME="en_GB.UTF-8"
      LC_COLLATE="en_GB.UTF-8"
      LC_MONETARY="en_GB.UTF-8"
      LC_MESSAGES="en_GB.UTF-8"
      LC_PAPER="en_GB.UTF-8"
      LC_NAME="en_GB.UTF-8"
      LC_ADDRESS="en_GB.UTF-8"
      LC_TELEPHONE="en_GB.UTF-8"
      LC_MEASUREMENT="en_GB.UTF-8"
      LC_IDENTIFICATION="en_GB.UTF-8"
      LC_ALL=

      ciertamente tendríamos que tener es_ES.UTF-8, pero ...

      Eliminar
  12. He conseguido que no me de error. Le instale las locale en_GB.utf-8, pero aun asi me daba error.
    Me puse a lanzar comando wget y curl para probar y al final usando Cargas%20de%20c%C3%A1mara
    en vez de Cargas de cámara, funciona.
    Es decir, el comando
    dropbox_uploader.sh list Cargas%20de%20c%C3%A1mara
    ya no me da error, ahora voy a por el download para bajarme los ficheros.

    Seguire informando, por si alguien mas se encuentra en esta tesitura.

    ResponderEliminar
  13. No me ha dejado poner el mismo nombre que tienes tu a la App poruqe dice que ya esta cogido y se lo he tendio que cambiar....donde debería de cambiarlo en el script???

    ResponderEliminar
  14. Si, como ponias que no se podía cambiar...

    ResponderEliminar
  15. Buenas soy nuevo en esto de linux,
    he puesto este script:

    #!/bin/bash
    echo Sincronizando con Dropbox...
    carpeta=/mnt/pendrive/dropbox
    listalocal=/tmp/local.txt
    listanube=/tmp/nube.txt
    repe="no"
    cd $carpeta
    ls > $listalocal
    dropbox_uploader.sh list > $listanube
    IFS=$'\n' ;

    for n in $(cat $listalocal)
    do
    repe="no";
    for m in $(cat $listanube | grep -v -e Listing -e DONE | sed 's/\ \[F\]\ //g');
    do
    if [ "$n" == "$m" ] ;
    then
    repe="si" ;
    fi
    done

    if [ $repe = "no" ];
    then
    #echo Cargando el archivo $n... ;
    dropbox_uploader.sh -q upload "$n" ;

    # else
    #echo El archivo $n ya esta sincronizado ;
    fi
    done
    echo COMPLETADO!

    tras configurar el .sh de "andreafabrizi" y listarme mi cuenta dropbox correctamente.
    Pero tras ejecutar el .sh de Gino (cambiando las variables correctamente), al ejecutarlo me da el siguiente error:

    /usr/local/bin/backup_dropbox.sh: line 18: repetido: command not found sed: -e expression #l, char 12: unterminated 's' command

    Sigue ejecutando el scrip pero no sube nada al dropbox.
    ¿Podria ser porque los nombres de las imagenes son largos y contienen numeros y letras? De ser asi como tendria que modificar el script para que funcionase correctamente.

    Tambien me gustaria saber que es lo que hace esta linea: sed 's/\ \[F\]\ //g'

    Muchas gracias
    MUY BUEN APORTE, SEGUIR ASI!!

    ResponderEliminar
  16. Buenas

    Mis conocimientos son nulos.

    No me funciona tu scrip, me introduce numeros delante del nombre del archivo y no lo reconoce cuando lo busca en dropbox. Me podrias dar alguna pista sobre el motivo para seguir buscando info????

    Muchas gracias de antemano

    ResponderEliminar