Ejecuté los siguientes comandos en el orden especificado:
$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b
Concluí de esta prueba que el comando en rm
realidad elimina solo el nombre de archivo ( a
en esta prueba) en lugar del archivo, ya que el inodo todavía existe y podría recuperarse a través de otro nombre de archivo ( b
).
Mi pregunta es, si un archivo está vinculado a un solo nombre de archivo, cuando rm
se ejecuta en el archivo, ¿se elimina por completo el archivo real (es decir, el inodo)? Y si no, ¿se puede recuperar un inodo de archivo sin un nombre de archivo y solo a través del inodo?
Respuestas:
Si intenta abrir un archivo a través de su inodo, esto omite cualquier recorrido del directorio. El recorrido del directorio es necesario para determinar los permisos del archivo y los directorios que lo conducen. Sin un recorrido de directorio, el núcleo no tiene forma de determinar si el proceso de llamada puede acceder al archivo.
Hubo un parche propuesto para el kernel de Linux para permitir crear un enlace a un archivo desde un descriptor de archivo . Era rechazado porque implementar esto de forma segura hubiera sido extremadamente difícil .
En Linux (y probablemente en otras variantes de Unix por el mismo motivo), no puede crear un enlace a un archivo eliminado, por lo que si un archivo ya no tiene un nombre, no puede volver a agregar uno. Puede abrir un enlace eliminado archivo abriendo los enlaces mágicos en
/proc/$pid/fd/
.Si un archivo ya no tiene ningún enlace y ya no está abierto, ya no existe y el espacio utilizado anteriormente por sus datos puede recuperarse en cualquier momento.
¹ Puede hacer esto girando los bytes directamente en el sistema de archivos de una manera dependiente del sistema de archivos, por ejemplo con
debugfs
para ext2 / ext3 / ext4. Esto requiere acceso al dispositivo en el que está montado el sistema de archivos (es decir, normalmente solo el root puede intentarlo). Sin embargo, aunque debugfs puede acceder a un archivo por inodo, esto no ayuda si se elimina el archivo: el archivo se eliminará realmente si la aplicación lo cierra, y ejecutar debugfs en modo lectura-escritura en un sistema de archivos montado es una receta para desastre.fuente
En Linux,
debugfs
el depurador interactivo del sistema de archivos ext2 / ext3 / ext4 proporciona unln
comando que puede tomar un número de inodo comofilespec
y crear un nuevo enlace duro al archivo correspondiente. Sin embargo, en la práctica, esto requiere que el archivo no vinculado se mantenga abierto mediante un proceso , manteniendo un descriptor de archivo abierto/proc/[pid]/fd/[n]
. Intentar esto está en un archivo eliminado muy probablemente conducirá a la corrupción del sistema de archivos.Esto se debe a que para garantizar que ext3 (y en la extensión ext4) pueda reanudar de forma segura un desvinculación después de un bloqueo, en realidad elimina los punteros de bloque en el inodo. , mientras que ext2 simplemente marca estos bloques como no utilizados en los mapas de bits de bloque y marca el inodo como "eliminado" y deja los punteros de bloque solos. Aun así, dado que el sistema de archivos necesita ser montado de lectura-escritura para crear el enlace rígido, los bloques reservados para el archivo eliminado podrían haber sido reasignados.
Antes de la versión del kernel 2.6.39, solía ser que la opción introducida en GNU coreutils v8.0 podía usarse para recuperar un archivo no vinculado a través de un descriptor de archivo abierto, si tanto el archivo no vinculado como el nuevo enlace rígido residían en un sistema de archivos tmpfs . Desde entonces, esta capacidad se ha deshabilitado debido a, como señaló Gilles , las consideraciones de seguridad involucradas en permitir la creación de enlaces duros directamente desde un descriptor de archivo.
ln
-L|--logical
/proc/[pid]/fd/[n]
fuente
ln -L
para recuperar un archivo eliminado de / proc y obtuve el error: "No existe tal archivo o directorio", por lo que no creo que realmente sea compatible con esto. Tengo coreutils 8.21.ln -L
no hace lo que dices que hace. Indicaln
que si la fuente es un enlace simbólico, debería vincular el destino. Los enlaces simbólicos en/proc/$pid/fd
son especiales, y vincular un(deleted)
enlace no funciona.debugfs
ayudará si el archivo se ha eliminado, a menos que quiera arriesgarse a ejecutarlo en modo de lectura-escritura en un sistema de archivos montado, que probablemente destrozará por completo todo el sistema de archivos.ln -L
. Solía ser posible crear enlaces duros al/proc/[pid]/fd/[n]
usarlo en ciertas circunstancias especiales, pero esto ya se ha solucionado.debugfs
'sln
es realmente de bajo nivel y solo crea un nombre, no actualiza el conteo ni desmarca los bloques como no utilizados, por lo que es muy peligroso . Preferirdebugfs
'sundel
, que des todo eso. Advertencia:debugfs
se que no se ejecuta en un sistema de archivos montado a menos que quiera tener una oportunidad en la quema de sus FS a cenizas.Los comandos 'ln' y 'rm' han funcionado exactamente así en todos los sistemas de archivos UNIX desde principios de los años setenta. Mac OSX, BSD y Linux heredan este diseño original.
Por sí mismo, un archivo UNIX no tiene nombre, solo un número de inodo o inum. Pero solo puede acceder a través de una entrada en un archivo especial de "directorio" que asocia un nombre con el inum en cuestión; No puede especificar el inum directamente.
Un directorio es en sí mismo un archivo, por lo que también debe acceder a él a través de (otro) directorio, etc., a través de una serie de nombres de directorio delimitados por barras diagonales (/) conocidas como "nombre de ruta". Una ruta comienza en el "directorio de trabajo actual" del proceso a menos que el nombre comience con un "/", en cuyo caso comienza con el directorio raíz del sistema de archivos. Por ejemplo, si el nombre de la ruta no contiene caracteres "/", se espera que sea una entrada en el directorio actual.
Un archivo que no es de directorio puede tener cualquier número de nombres de ruta, conocidos como "enlaces duros", y seguirá existiendo hasta que se hayan eliminado todos sus nombres de ruta y el último proceso haya cerrado el archivo. Luego, el archivo se elimina y su espacio se marca como disponible para su reutilización. Es decir, puede crear () o abrir () un archivo vinculado individualmente y luego desvincularlo () para que ya no aparezca en el espacio de nombre del sistema de archivos, pero el archivo seguirá existiendo hasta que lo cierre. Esto es útil para archivos temporales que no serán leídos por ningún otro programa.
Aunque los directorios tienen números de inodo, la mayoría de los sistemas de archivos no permiten enlaces duros a ellos; solo pueden aparecer en otro directorio. (Una excepción inusual es el sistema de archivos Mac OSX HFS +; esto permite que funcionen las copias de seguridad de Time Machine). Aún puede crear "enlaces suaves" a directorios (o cualquier otro archivo). Un enlace suave se asemeja a una entrada de directorio, excepto que contiene otro nombre de ruta en lugar de un inum.
Cada archivo UNIX tiene un propietario, un grupo y permisos de acceso. Es necesario pero no suficiente que le permitan abrir el archivo; También debe tener al menos permiso de ejecución para cada directorio en el nombre de ruta que utiliza para referirse a él. Es por eso que no hay una forma estándar de abrir un archivo UNIX por su número de inodo; eso evitaría un mecanismo de seguridad importante y ampliamente utilizado.
Pero esto no explica por qué no puede haber una forma estándar para que un usuario root (privilegiado) abra un archivo por número de inodo, ya que la verificación de permisos se omite de todos modos. Esto sería muy útil para ciertas funciones de administración del sistema, como las copias de seguridad. Que yo sepa, tales mecanismos existen, pero todos son específicos del sistema de archivos; no hay una forma general de hacerlo para ningún sistema de archivos UNIX.
fuente
/
es silencioso, por lo que se pronuncia "barra oblicua".La pregunta se puede tomar teóricamente (lo que se puede lograr con
debugfs
) o pragmáticamente (situación de emergencia). En el último caso, supongo que la intención es salvar el día y restaurar el contenido del archivo, posiblemente con urgencia (que es la forma en que llegué a esta pregunta, por lo que creo que sigue siendo relevante y útil).Como no hay una API de kernel,
debugfs
no debe ejecutarse en un sistema de archivos en vivo porque manipula la estructura FS directamente. Por lo tanto, para hacerlo en vivo, debe obtener otro nombre de archivo. Asumiendo que el archivo todavía está abierto por algún proceso (cualquier proceso), uno puede buscar los descriptores de archivo siempre convenientes en/proc
:Consejos:
file
en éltail -f < /proc/$pid/fd/$fd > /dev/null
, salga del proceso de escritura para que salga limpiamente y use el fd del nuevo proceso.fuente
tail -f < /proc/...
en el segundo consejo.tail -c +0 -f
para copiarlo en primer lugar en lugar de hacerlocat
, si el proceso de escritura solo se agrega (no se busca y reescribe). Salga del otro proceso antestail
, luego espere paratail
llegar al final del archivo.