2010-12-18 42 views
18

Quiero poder leer un archivo actualmente abierto. El test.rb está enviando su salida a test.log, que quiero poder leer y finalmente enviar por correo electrónico.Cómo leer un archivo abierto en Ruby

Estoy funcionando esto usando cron:

*/5 * * * /tmp/test.rb > /tmp/log/test.log 2>&1 

tengo algo como esto en test.rb:

#!/usr/bin/ruby 

def read_file(file_name) 
    file = File.open(file_name, "r") 
    data = file.read 
    file.close 
    return data 
end 

puts "Start" 
puts read_file("/tmp/log/test.log") 
puts "End" 

Cuando ejecuta este código, sólo me da este resultado:

Start 

End 

Esperaría que la salida fuera algo como esto:

Start 
Start (from the reading of the test.log since it should have the word start already) 
End 
+1

me gusta decirlo, pero hay un montón de cosas mal con toda esta aplicación. ¿Puedes reformular lo que quieres hacer? Leer un archivo abierto no es lo que estás haciendo ni tiene mucho sentido, por lo que explicar tu objetivo con cuidado probablemente te ayude a comprender los pasos necesarios para llegar allí. –

+0

Mi objetivo es registrar el script (su resultado y cualquier error que ocurra) y al final del script, quiero que me envíe este registro por correo electrónico. – Carmen

Respuesta

4

En el trabajo cron ya ha abierto y borrado test.log (a través de la redirección) antes de haberlo leído en el script de Ruby.

¿Por qué no leer y escribir tanto en Ruby?

+0

Por favor, sea paciente ya que soy realmente un novato en esto. Pero, ¿cómo puedo hacer lo que sugeriste al leer y escribir en Ruby? – Carmen

3

El problema es, como puedo ver, ya resuelto por Slomojo. Yo sólo voy a añadir:
para leer e imprimir un archivo de texto en Ruby, simplemente:

puts File.read("/tmp/log/test.log") 
+0

Por lo tanto, probé esto pero sigo obteniendo el mismo resultado. ¿Se debe a que el resultado está en una especie de buffer para que nada permanezca en el archivo de registro cuando se lee el archivo? – Carmen

+0

@Carmen, soy un experto en Windows, lo siento, no sé nada sobre tu cron) – Nakilon

+0

@Carmen, no hay memoria intermedia involucrada. El cronjob se activa y el sistema operativo truncará cuando las redirecciones STDOUT y STDERR se configuren, lo que ocurre justo antes de que el SO inicie su aplicación. –

3

Puede ser un problema de permisos o no existir el archivo.

f = File.open("test","r") 
puts f.read() 
f.close() 

Lo anterior leerá la prueba del archivo. Si el archivo existe en el directorio actual

+0

No es un problema de permisos o existencia de archivos. Es un problema con el tiempo y el shell truncar el archivo inmediatamente antes de leerlo. –

38

Ok, estás tratando de hacer varias cosas a la vez, y sospecho que no has probado sistemáticamente antes de pasar de un paso al siguiente.

En primer lugar vamos a limpiar su código:

def read_file(file_name) 
    file = File.open(file_name, "r") 
    data = file.read 
    file.close 
    return data 
end 

puts "Start" 
puts read_file("/tmp/log/test.log") 
puts "End" 

se puede sustituir por:

puts "Start" 
puts File.read("./test.log") 
puts "End" 

Es así de simple; No hay necesidad de un método o algo complicado ... todavía.

Tenga en cuenta que para facilitar las pruebas estoy trabajando con un archivo en el directorio actual. Para poner un poco de contenido en ella, simplemente voy a hacer:

echo "foo" > ./test.log 

Ejecutar el código de prueba me da ...

Greg:Desktop greg$ ruby test.rb 
Start 
foo 
End 

así que sé que el código es la lectura y la impresión correctamente.

Ahora podemos probar lo que iría en el crontab, antes de que nos ocupamos de su locura:

Greg:Desktop greg$ ruby test.rb > ./test.log 
Greg:Desktop greg$ 

Hmm. Ninguna salida. Algo está roto con eso. Sabíamos que había contenido en el archivo anteriormente, entonces, ¿qué pasó?

Greg:Desktop greg$ cat ./test.log 
Start 

End 

Cat'ing el archivo de muestra que tiene el "Inicio" y "Fin" salida del código, pero la parte que debería haber leído y salida es ahora falta.

Lo que sucede es que el shell truncó "test.log" justo antes de pasar el control a Ruby, que luego abrió y ejecutó el código, que abrió el archivo ahora vacío para imprimirlo. En otras palabras, le está pidiendo al shell que lo trunque (vacío) justo antes de leerlo.

La solución es leer desde un archivo diferente al que va a escribir, si está intentando hacer algo con el contenido del mismo. Si no estás tratando de hacer algo con su contenido, no tiene sentido leerlo con Ruby solo para escribirlo en un archivo diferente: tenemos cp y/o mv para hacer esas cosas sin que se involucre Ruby. Por lo tanto, esto tiene más sentido si vamos a hacer algo con el contenido:

ruby test.rb > ./test.log.out 

Voy a restablecer el contenido del archivo usando echo "foo" > ./test.log y cat'ing se mostró 'foo', así que estoy listo para intentar la prueba de redireccionamiento de nuevo:

Greg:Desktop greg$ ruby test.rb > ./test.log.out 
Greg:Desktop greg$ cat test.log.out 
Start 
foo 
End 

Esa vez funcionó. Volver a intentarlo tiene el mismo resultado, por lo que no mostraré los resultados aquí.

Si va a enviar el archivo por correo electrónico, puede agregar ese código en este momento. Sustitución de la puts en la línea puts File.read('./test.log') con una asignación a una variable almacenará el contenido del archivo:

contents = File.read('./test.log') 

continuación, puede utilizar contents como el cuerpo de un correo electrónico. (Y, en lugar de utilizar Ruby para todo esto, probablemente lo haría usando mail o mailx o canalizándolo directamente a sendmail, usando la línea de comandos y el shell, pero esa es su llamada).

En este punto las cosas están en una buena posición para agregar el comando a crontab, usando el mismo comando que se usa en la línea de comandos. Debido a que se está ejecutando en cron, y pueden ocurrir errores que quisiéramos saber, agregaremos el redireccionamiento 2>&1 para capturar STDERR también, tal como lo hizo antes. Solo recuerda que puedes NOT escribir en el mismo archivo desde el que vas a leer o tendrás un archivo vacío para leer.

Eso es suficiente para que tu aplicación funcione.

+1

¡Positivamente expositivo! –

+0

Lo llamaría largo aliento. :-) –

15
class FileLineRead 
    File.open("file_line_read.txt") do |file| 
    file.each do |line| 
     phone_number = line.gsub(/\n/,'') 
     user = User.find_by_phone_number(line) 
     user.destroy unless user.nil? 
    end 
    end 
end 
  1. archivo abierto
  2. línea de lectura
  3. DB Seleccionar
  4. DB Actualización
Cuestiones relacionadas