¿Recuperar archivo borrado mantenido por Apache?

10

Supongamos que un archivo de registro de apache se elimina pero apache lo mantiene abierto; entonces esto es lo que estoy haciendo:

pid=$(lsof | grep text.txt | awk '/deleted/ {print $2}')
fd=$(lsof | grep text.txt | awk '/deleted/ {print $4}' | grep -oE "[[:digit:]]{1,}")

cp /proc/$pid/fd/$fd directorytobecopied/testfile.txt

Esto es lo que estoy haciendo para recuperar el archivo y volver a colocarlo donde estaba. ¿Hay alguna manera más simple de hacer esto porque el código anterior no se ve bien? Además, ¿cómo sé de dónde se eliminó el archivo ( directorio a copiar ) para que no tenga que preguntar manualmente a alguien dónde se encontraba originalmente el archivo y volver a colocarlo allí.

munish
fuente
lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'
Rahul Patil

Respuestas:

14

Si un archivo se ha eliminado pero todavía está abierto, eso significa que el archivo todavía existe en el sistema de archivos (tiene un inodo ) pero tiene un recuento de enlaces duros de 0. Dado que no hay un enlace al archivo, no puede abrirlo por nombre . Tampoco hay posibilidad de abrir un archivo por inodo.

No hay forma de descubrir el archivo a través de su sistema de archivos, y especialmente no hay forma de buscar el archivo en el directorio donde estuvo por última vez. La entrada del directorio se ha ido. Todo lo que queda es el archivo en sí. Puede acceder al archivo con un depurador del sistema de archivos, pero eso requiere permisos de root y es difícil de usar y propenso a errores.

Linux expone archivos abiertos a través de enlaces simbólicos especiales en /proc. Estos enlaces se llaman /proc/12345/fd/42donde 12345 es el PID de un proceso y 42 es el número de un descriptor de archivo en ese proceso. Un programa que se ejecuta con el mismo usuario que ese proceso puede acceder al archivo (los permisos de lectura / escritura / ejecución son los mismos que tenía cuando se eliminó el archivo).

El nombre con el que se abrió el archivo todavía es visible en el destino del enlace simbólico: si el archivo estaba /var/log/apache/foo.log, entonces el destino del enlace es /var/log/apache/foo.log (deleted). (Si se cambió el nombre del archivo después de abrirlo, el destino del enlace simbólico puede reflejar el cambio de nombre).

Por lo tanto, puede recuperar el contenido de un archivo eliminado abierto dado el PID de un proceso que lo tiene abierto y el descriptor en el que está abierto de esta manera:

recover_open_deleted_file () {
  old_name=$(readlink "$1")
  case "$old_name" in
    *' (deleted)')
      old_name=${old_name%' (deleted)'}
      if [ -e "$old_name" ]; then
        new_name=$(TMPDIR=${old_name%/*} mktemp)
        echo "$oldname has been replaced, recovering content to $new_name"
      else
        new_name="$old_name"
      fi
      cat <"$1" >"$new_name";;
    *) echo "File is not deleted, doing nothing";;
  esac
}
recover_open_deleted_file "/proc/$pid/fd/$fd"

Si solo conoce la ID del proceso pero no el descriptor, puede recuperar todos los archivos con

for x in /proc/$pid/fd/*; do
  recover_open_deleted_file "$x"
done

Si tampoco conoce la ID del proceso, puede buscar entre todos los procesos:

for x in /proc/[1-9]*/fd/*; do
  case $(readlink "$x") in
    /var/log/apache/*) recover_open_deleted_file "$x";;
  esac
done

También puede obtener esta lista analizando la salida de lsof, pero no es más simple ni más confiable ni más portátil (de todos modos, esto es específico de Linux).

Gilles 'SO- deja de ser malvado'
fuente
Puede abrir / proc / x / fd / y para leer o escribir independientemente de si x lo tiene abierto para leer o escribir.
Stéphane Chazelas
¿Por qué el sistema operativo Unix permite la eliminación de archivos cuando está abierto ... mientras que no podemos hacerlo en Windows. Hay alguna explicación
Munish
@munish Windows comenzó a partir de un modelo cooperativo multitarea: si una aplicación se comporta mal, podría provocar la caída del sistema. La mayoría de los problemas ya se han solucionado, pero Windows todavía permite que una aplicación secuestre un archivo: mientras el archivo esté abierto, no se puede renombrar ni eliminar. Unix no permite esto: eliminar o renombrar un archivo es ortogonal de tenerlo abierto.
Gilles 'SO- deja de ser malvado'
1
¡Acabas de guardar Muse's Origin of Symmetry para mí! ¡Gracias mil veces!
dotancohen