Recuperar archivos borrados aún abiertos /Experto


YouTube
Este truco, que aprendí hace poco de un compañero de trabajo, sirve para cosas tan mundanas como guardar el archivo de Youtube que estamos viendo (tema que usaré de ejemplo para ilustrar esta entrada), como para cosas problemáticas como eliminar archivos por error. La entrada está más bien enfocada a expertos por los términos y conceptos que aparecen involucrados en la explicación, como por la utilidad general que se le puede dar, aunque la finalidad de copiar el video de Youtube puede ser aprovechada por alguien con conocimientos Básicos como una simple receta. Empezaremos por repasar algunos conceptos para luego pasar a ejecutar la tarea de ejemplo.
  • Todo en Linux es considerado un archivo, lo que uno normalmente reconoce como tal (contenedor de datos digitales) como así también la entrada y salida estándar de datos, los dispositivos, las conexiones a puertos, los sockets, etc.
  • Un mismo archivo puede tener varios puntos de acceso (referencias): el nombre ubicado en un directorio, estar abierto por una aplicación, poseer hardlinks, etc.
  • Para que un archivo sea eliminado del file system, no debe poseer referencias al mismo.
  • Si uno elimina un archivo con por ejemplo el comando rm, si dicho archivo esta abierto por alguna aplicación, todavía posee referencias y por lo tanto se puede recuperar.
  • Muchos programas, crean un archivo el cual manipularan y para evitar que otro lo pueda modificar, lo borran a nivel ubicación en el árbol de directorios. Este es el caso de lo que hace actualmente el flashplugin con por ejemplo los video de Youtube que va descargando. Hace tiempo, uno miraba un video y lo encontraba en /tmp, pero actualmente dicho archivo es borrado y mantenido únicamente mientras el navegador tiene abierta la página donde se está reproduciendo.
Bueno, ya sabemos que tenemos una forma de acceder al archivo... ¿cómo lo encontramos? Haciendo uso del comando lsof, el cual lista (ls) los archivos abiertos (open files). Sin opciones, arrojará un listado muy extenso de todos los archivos abiertos actualmente, pero podemos indicarle que liste únicamente los pertenecientes a la aplicación que nos interesa. Para eso, con la opción -p, hay que suministrarle el PID (Process ID) de dicha aplicación. De la ejecución del lsofobtendremos el fd (file descriptor) del archivo en el que estamos interesados. Luego, en el directorio /proc//fd, estarán los accesos a todos los archivos que la aplicación posee abiertos.

Hasta acá la teoría. Vamos a ver ahora los pasos prácticos aplicados a obtener un video de Youtube siendo reproducido en el Firefox.

Obtener el PID del flasplugin

Con el comando pslistaremos los procesos en ejecución y con el comando grepfiltraremos la salida para que sólo muestre los procesos relacionados al plugin de flash:

$ ps -efa | grep flashplugin

ram       2070  2008 17 12:19 ?        00:21:22 /usr/lib/firefox-9.0.1/plugin-container /usr/lib/flashplugin-installer/libflashplayer.so -greomni /usr/lib/firefox-9.0.1/omni.jar 2008 true plugin
ram       5839  2798  0 14:25 pts/0    00:00:00 grep --color=auto firefox

La línea que nos interesa es la resaltada en rojo. El PID es el correspondiente a la segunda columna, en este caso 2070.

Obtener el file descriptor (fd) del archivo de video

Esto lo conseguimos pidiendo el listado de archivos abiertos de la aplicación con lsof y filtrando con grep que aparezca la palabra Flash:

$ lsof -p 2070 | grep Flash

plugin-co 2070  ram   16w   REG        8,3 26456407    1911 /tmp/FlashXX18vKJz (deleted)

Vemos que el archivo buscado es /tmp/FlashXX18vKJz. Observar que entre paréntesis nos indica que está borrado. El fd será la cuarta columna, en este caso 16.

Obtener el archivo

Ahora que ya tenemos el PID (2070) y el fd (16), encontramos el archivo en el directorio proc:

$ ls /proc/2070/fd/16 -l

l-wx------ 1 ram ram 64 2012-01-07 12:19 /proc/2070/fd/16 -> /tmp/FlashXX18vKJz (deleted)

Vemos que /proc/2070/fd/16 es un link simbólico al archivo eliminado que estábamos buscando. Ahora podemos directamente reproducirlo o copiarlo. En caso de copiarlo, conviene renombrarlo:

$ cp /proc/2070/fd/16 video.flv

Y eso es todo.

Receta para obtener el video de Youtube

  1. Ejecutar $ ps -efa | grep flashplugin y obtener el PID.
  2. Ejecutar $ lsof -p 2070 | grep Flash y obtener el fd. 2070 es el PID encontrado en el punto 1.
  3. Ejecutar $ cp /proc/2070/fd/16 video.flv donde 2070 es el PID y 16 el fd.

Conclusión

Este truco es sencillo de aplicar para conseguir un video de Youtube. Otras utilidades, pueden ser recuperar archivos eliminados por error (siempre y cuando estén siendo utilizados por alguna aplicación) o ver que es lo que hace una aplicación con los archivos que abre (que puede servir entre otras cosas para aprender). Esperando que les resulte interesante, los saludo hasta la próxima.





No hay comentarios:

Publicar un comentario