ver son que procesos ficheros comando abiertos ruby file-io io file-descriptor filehandle

son - ¿Dónde realiza un seguimiento Ruby de sus descriptores de archivos abiertos?



que son ficheros abiertos (1)

De qué no se trata esta pregunta

Esta pregunta no es sobre cómo cerrar automáticamente un archivo con Archivo # cerrado o con la sintaxis de bloque de archivo # abierto. Es una pregunta acerca de dónde Ruby almacena su lista de descriptores de archivos abiertos en tiempo de ejecución.

La pregunta actual

Si tiene un programa con descriptores abiertos, pero no tiene acceso al objeto Archivo o IO relacionado, ¿cómo puede encontrar una referencia a los descriptores de archivos abiertos actualmente? Tomemos este ejemplo:

filename=''/tmp/foo'' %x( touch "#{filename}" ) File.open(filename) filehandle = File.open(filename)

La primera instancia de archivo se abre, pero la referencia al objeto no se almacena en una variable. La segunda instancia se almacena en el identificador de archivo, donde puedo acceder fácilmente con #inspect o #close.

Sin embargo, el objeto File descartado no se ha ido; Simplemente no es accesible de ninguna manera obvia. Hasta que se finalice el objeto, Ruby debe seguirlo en algún lugar ... ¿pero dónde?


TL; DR

Todos los objetos File y IO se almacenan en ObjectSpace.

Responder

La clase ObjectSpace dice:

El módulo ObjectSpace contiene varias rutinas que interactúan con la instalación de recolección de basura y le permiten atravesar todos los objetos vivos con un iterador.

Como probé esto

He probado esto en la consola en Ruby 1.9.3p194.

El accesorio de prueba es realmente simple. La idea es tener dos objetos de archivo con diferentes identidades de objeto, pero solo uno es accesible directamente a través de una variable. El otro es "por ahí en alguna parte".

# Don''t save a reference to the first object. filename=''/tmp/foo'' File.open(filename) filehandle = File.open(filename)

Luego exploré diferentes formas en las que podía interactuar con los objetos del Archivo incluso si no usaba una referencia de objeto explícita. Esto fue sorprendentemente fácil una vez que supe sobre ObjectSpace.

# List all open File objects. ObjectSpace.each_object(File) do |f| puts "%s: %d" % [f.path, f.fileno] unless f.closed? end # List the "dangling" File object which we didn''t store in a variable. ObjectSpace.each_object(File) do |f| unless f.closed? printf "%s: %d/n", f.path, f.fileno unless f === filehandle end end # Close any dangling File objects. Ignore already-closed files, and leave # the "accessible" object stored in *filehandle* alone. ObjectSpace.each_object(File) {|f| f.close unless f === filehandle rescue nil}

Conclusión

Puede haber otras formas de hacer esto, pero esta es la respuesta que se me ocurrió para rascarme la picazón. Si conoces una manera mejor, por favor publica otra respuesta. El mundo será un lugar mejor para ello.