¿Cómo hacer un archivo temporal en RAM?

29

Tengo un script que canalizará su salida a |tee scriptnameYYMMDD.txt. Después de cada ciclo del ciclo for en el que se genera la salida, invertiré el contenido del archivo tac scriptnameYYYYMMDD.txt > /var/www/html/logs/scriptname.txtpara que la salida del registro sea visible en una ventana del navegador con las líneas más nuevas en la parte superior.

Tendré varios scripts haciendo esto en paralelo. Estoy tratando de minimizar la actividad del disco, por lo que la salida de |tee scriptnameYYYYMMDD.txtun disco RAM sería lo mejor. mktempcrea un archivo en la /tmpcarpeta, pero eso no parece estar fuera del disco.

usuario208145
fuente
Tiene que ser un ramfs o un tmpfs (el segundo es mejor). Verifique si tal fs ya está montado en su sistema, si es así, puede usarlo. Si no, necesita montarlo.
Peter dice reinstalar a Monica el
Me actualizo fstabcon el fin de montar un tmpfssobre /tmpy luego reiniciar la máquina.
Kasperd
1
puede considerar aumentar gradualmente taillos archivos (o iniciarlos a través de CGI a pedido o algo así) en lugar de hacerlo tactodo.
mikeserv
Esto parece funcionar en las pruebas (perdón por el formato reducido): TEMPPATH="/ramdisk" LOGPATH="/var/www/html/log" ... echo <various calls to echo> | tee -a $TEMPPATH/moveKRT$(date '+%Y%m%d').txt ... al final del ciclo for, cp $TEMPPATH/moveKRT$(date '+%Y%m%d').txt $LOGPATH/moveKRT$(date '+%Y%m%d').txt tac $TEMPPATH/moveKRT$(date '+%Y%m%d').txt > $LOGPATH/moveKRT.txt tengo conocimiento de la minúscula posibilidad de que el cambio de 23: 59: 59.999 a 00:00: 00 puede afectar algunos archivos, pero la posibilidad es aceptable.
user208145
Actualización sobre mi progreso en esto: tengo un volumen tmpfs de 1 GB montado en / ramdisk. Tengo archivos que entran en las carpetas de inicio de los usuarios a través de FTP. Se mueven a una subcarpeta / ramdisk / queues / xyz / para procesar y luego se eliminan. En el inicio, tengo un script que recrea mi estructura de directorio necesaria en / ramdisk. Esto debería dar como resultado una actividad de disco mínima para los archivos entrantes. Hasta ahora, la única otra forma en que veo reducir la E / S de disco para estos scripts sería crear esas carpetas de usuario en un tmpfs creado al inicio, antes de que cualquier archivo ingrese a través de FTP a esas carpetas de usuario. Gracias a todos.
user208145

Respuestas:

22

Puede montar una tmpfspartición y escribir el archivo allí:

mount -t tmpfs -o size=500m tmpfs /mountpoint

Esta partición ahora está limitada a 500 MB. Si su archivo temporal crece más de 500 MB se producirá un error: no space left on device. Pero, no importa cuando especifique una mayor cantidad de espacio que la RAM de su sistema. tmpfsusos intercambian espacio demasiado, por lo que no se puede obligar a un fallo del sistema, en contraposición a ramfs.

Ahora puede escribir su archivo en /mountpoint:

command | tee /mountpoint/scriptnameYYYYMMDD.txt
caos
fuente
3
size=[num]%también está bien: un tmpfs puede limitarse a un porcentaje de memoria disponible. Por lo general, es más fácil de esa manera si los comandos no siempre están dirigidos a la misma máquina (real / virtual) . También es útil que un tmpfs no suelte contenido w / -o remount,size=newsize.
mikeserv
1
Dado que la pregunta gira en torno a un script bash, que no tenemos ninguna razón para suponer que se ejecuta desde la raíz, ¿puede especificar si se puede evitar mountno permitir el uso de usuarios no root -to -o? Es decir, ¿cómo se pueden crear scripts que usen tmpfs(o RAM de cualquier otra manera) para guardar en operaciones de disco, si un sistema de archivos adecuado no existe en el sistema?
Jonathan Y.
No es una buena respuesta. Fallará si no eres root.
Alex
11

Prueba esto con Ubuntu:

ramtmp="$(mktemp -p /dev/shm/)"
tac scriptnameYYYYMMDD.txt > "$ramtmp"
Ciro
fuente
3
¿ /run/shm/Qué tan estable es escribir ? ¿Puedo aplicar chmodcambios al archivo temporal si es necesario? Noté que los bits de modo de la carpeta son idénticos a la /tmpcarpeta. Gracias.
user208145
1
En cuanto a otros directorios, los archivos generados en /run/shm(enlace simbólico a /dev/shm) mktemptambién tienen un permiso predeterminado de -rw-------(600) y puede cambiarlo si es necesario con sudo chmod.
KrisWebDev
9

La siguiente respuesta fue descubierta al investigar las respuestas anteriores y la información en esta pregunta aquí y no se habría encontrado sin ellas. Cudos a ellos.

En mi sistema linuxmint (y supongo que la mayoría de los sistemas basados ​​en ubuntu y posiblemente también basados ​​en debian) hay un tmpfs propiedad del usuario montado automáticamente en /run/user/1000/

Use df -Tpara verificar.

11:41:11 jesse @ Limbo: ~ $ df -T
Tipo de sistema de archivos 1K-blocks Usado Disponible Uso% Montado en
udev devtmpfs 15904812 4 15904808 1% / dev
tmpfs tmpfs 3184120 1700 3182420 1% / carrera
/ dev / sdb2 ext4 14248880 11464788 2037240 85% /
ninguno tmpfs 4 0 4 0% / sys / fs / cgroup
ninguno tmpfs 5120 0 5120 0% / carrera / bloqueo
ninguno tmpfs 15920584 848 15919736 1% / run / shm
ninguno tmpfs 102400 12 102388 1% / ejecución / usuario
/ dev / sdb3 ext4 100861352 90755700 4959136 95% / mnt / data

Debajo /run/user/hay un directorio para cada usuario normal en el sistema

12:07:35 jesse@Limbo:~$ ls -l /run/user
total 0
drwx------ 2 root  root   40 Aug  7 09:50 0
drwx------ 8 jesse jesse 180 Aug  7 11:38 1000

Estos directorios llevan el nombre de sus respectivos identificadores de usuario. Podemos obtener la identificación de usuario con id -uver man idpara obtener detalles sobre este comando.

12:07:43 jesse@Limbo:~$ ls -l /run/user/$(id -u)
total 0
drwx------ 2 jesse jesse  60 Aug  7 09:50 dconf
dr-x------ 2 jesse jesse   0 Aug  7 09:50 gvfs
drwx------ 2 jesse jesse  80 Aug  7 09:50 pulse
lrwxrwxrwx 1 root  root   17 Aug  7 09:50 X11-display -> /tmp/.X11-unix/X0

Luego podemos usar el mktempcomando con la --tmpdiropción de crear archivos temporales y directorios en este sistema de archivos temporales, creando así archivos temporales en la RAM.

Siguiendo los consejos dados aquí , primero creo un directorio temporal y luego creo mis archivos temporales en eso:

mydir=$(mktemp -dt "$(basename $0).XXXXXXXX" --tmpdir=/run/user/$(id -u))

para crear un directorio temporal /run/user/1000/bash.w42BYxbG/entonces

myfile=$(mktemp -t "$(basename $0).XXXXXXXX" --tmpdir=$mydir)

para crear un archivo temporal en él.

Esto facilita la limpieza de estos archivos, ya que todo lo que tengo que hacer es rm -r $mydir.

Por defecto, todos estos archivos son propiedad y solo los puede leer el usuario que los creó.

Nota: La $(basename $0)parte del comando extrae el nombre del script / proceso que ejecutó mktemp. Si tengo un script, /home/jesse/scripts/myScript.shluego $(basename $0)regresa myScript.shcuando lo ejecuta este script. Por lo tanto, los comandos anteriores crearían /run/user/1000/myScript.sh.w42BYxbG/y /run/user/1000/myScript.sh.w42BYxbG/myScript.sh.BCzSmq06respectivamente.

Jesse el Errante del Viento
fuente
/run/user/1000está disponible en cada Linux que usa systemd, por lo que no solo está disponible en sistemas basados ​​en Debian, sino también en la mayoría de las otras distribuciones de Linux. Si no, se debe usar / tmp en su lugar. Puede simplificar sus comandos utilizando la variable $ XDG_RUNTIME_DIR que ya mantiene el directorio correcto para cada usuario. Para obtener más información, consulte, por ejemplo, esta respuesta: unix.stackexchange.com/questions/162900/…
Alex
1
Utilice mkstemp sobre mktemp !! Motivo de: linux.die.net/man/3/mktemp : en la sección Errores "... cada uso de mktemp () es un riesgo de seguridad, mkstemp (3) evita la carrera".
Alex
0

Como yo lo entiendo, los objetivos son: (1) no almacenar el archivo en el disco invertida, para ser servido al navegador (nota: esto podría ser tmpfs, etc, ya que todas las otras respuestas ya detalle); pero, (2) evite escribir el primer archivo tmp en el disco, con la salida original; y, sin embargo, (3) aún muestra la salida original en stdout.

Si es así, lo siguiente podría satisfacer sus necesidades, utilizando la sustitución del proceso bash (es decir, básicamente una tubería con nombre):

command | tee >( tac > /var/www/html/logs/scriptname.txt )

Tenga en cuenta que esto está imprimiendo continuamente la salida en stdout, y cuando finaliza el comando (cuando finaliza su ciclo), invierte esa salida y la escribe en el archivo de salida. Ilustrado a través de lo siguiente, que imprime una línea por segundo, y después de la terminación, el archivo /tmp/foo.txtcontiene las líneas invertidas:

i=0
while [ $i -lt 10 ]; do
    ((i = i+1))
    echo "==$i== $(date)"
    sleep 1
done | tee >( tac >> /tmp/foo.txt ) 
Miguel
fuente