Comment créer un fichier temporaire en RAM?


29

J'ai un script qui dirigera sa sortie vers |tee scriptnameYYMMDD.txt. Après chaque cycle de la boucle for dans laquelle la sortie est générée, je vais inverser le contenu du fichier avec tac scriptnameYYYYMMDD.txt > /var/www/html/logs/scriptname.txtpour que la sortie du journal soit visible dans une fenêtre de navigateur avec les lignes les plus récentes en haut.

J'aurai plusieurs scripts faisant cela en parallèle. J'essaie de minimiser l'activité du disque, donc la sortie de |tee scriptnameYYYYMMDD.txtvers un RAMdisk serait la meilleure. mktempcrée un fichier dans le /tmpdossier, mais qui ne semble pas être hors disque.


Il doit s'agir d'un ramfs ou d'un tmpfs (le second est préférable). Vérifiez si un tel fs est déjà monté sur votre système, si oui, vous pouvez l'utiliser. Si non, vous devez le monter.
peterh dit réintégrer Monica

Je mets à jour fstabafin de monter un tmpfssur /tmppuis redémarrer la machine.
kasperd

1
vous pourriez envisager d'incrémenter tailles fichiers (ou de les lancer via CGI sur demande ou quelque chose) plutôt que d' tacingérer le tout.
mikeserv

Cela semble fonctionner dans les tests (désolé pour la mise en forme diminuée): TEMPPATH="/ramdisk" LOGPATH="/var/www/html/log" ... echo <various calls to echo> | tee -a $TEMPPATH/moveKRT$(date '+%Y%m%d').txt ... à la fin de la boucle 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 je suis conscient de la possibilité minuscule que le changement de 23: 59: 59.999 à 00:00: 00 peut affecter certains fichiers, mais la chance est acceptable.
user208145

Mise à jour sur mes progrès à ce sujet: J'ai un volume tmpfs de 1 Go monté sur / ramdisk. J'ai des fichiers qui arrivent dans les dossiers personnels des utilisateurs via FTP. Ils sont déplacés vers un sous-dossier / ramdisk / queues / xyz / à traiter et sont supprimés par la suite. Au démarrage, j'ai un script qui recrée ma structure de répertoires nécessaire sous / ramdisk. Cela devrait entraîner une activité disque minimale pour les fichiers entrants. Jusqu'à présent, la seule autre façon que je vois de réduire les E / S disque pour ces scripts serait de créer ces dossiers utilisateur dans un tmpfs créé au démarrage, avant que tous les fichiers arrivent via FTP vers ces dossiers utilisateur. Merci a tous.
user208145

Réponses:


22

Vous pouvez monter une tmpfspartition et y écrire le fichier:

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

Cette partition est désormais limitée à 500 Mo. Si votre fichier temporaire grossit de 500 Mo une erreur se produit: no space left on device. Mais peu importe lorsque vous spécifiez une plus grande quantité d'espace que la RAM de votre système. tmpfsutilise également l'espace d'échange, vous ne pouvez donc pas forcer un plantage du système, contrairement à ramfs.

Vous pouvez maintenant écrire votre fichier dans /mountpoint:

command | tee /mountpoint/scriptnameYYYYMMDD.txt

3
size=[num]%est également très bien - un tmpfs peut être limité à un pourcentage de mémoire disponible. C'est généralement plus facile de cette façon si les commandes ne sont pas toujours ciblées pour la même machine (réelle / virtuelle) . Aussi pratique est qu'un tmpfs ne laisse pas tomber le contenu w / -o remount,size=newsize.
mikeserv

1
Étant donné que la question tourne autour d'un script bash, que nous n'avons aucune raison de supposer qu'il est exécuté par root, pouvez-vous spécifier si l'on peut contourner le problème en mountn'autorisant pas les utilisateurs non root à utiliser -tou -o? Autrement dit, comment peut-on créer des scripts qui utilisent tmpfs(ou de la RAM de toute autre manière) pour économiser sur les opérations sur disque, si un système de fichiers approprié n'existe pas déjà sur le système?
Jonathan Y.

Pas une bonne réponse. Échouera si vous n'êtes pas root.
Alex

11

Essayez ceci avec Ubuntu:

ramtmp="$(mktemp -p /dev/shm/)"
tac scriptnameYYYYMMDD.txt > "$ramtmp"

3
dans quelle mesure l'écriture est-elle stable /run/shm/? Puis-je appliquer des chmodmodifications au fichier temporaire si nécessaire? J'ai remarqué que les bits de mode du dossier sont identiques au /tmpdossier. Merci.
user208145

1
Comme pour les autres répertoires, les fichiers générés dans /run/shm(lien symbolique vers /dev/shm) mktempont également une autorisation par défaut de -rw-------(600) et vous pouvez le modifier si nécessaire avec sudo chmod.
KrisWebDev

9

La réponse suivante a été découverte en examinant les réponses précédentes et les informations de cette question ici et n'aurait pas été trouvée sans elles. Cudos à eux.

Sur mon système linuxmint (et je suppose que la plupart des systèmes basés sur Ubuntu et éventuellement sur Debian aussi) il y a un tmpfs appartenant à l'utilisateur monté automatiquement sur /run/user/1000/

Utilisez df -Tpour vérifier.

11:41:11 jesse @ Limbo: ~ $ df -T
Type de système de fichiers Blocs 1K utilisés disponibles disponibles% montés sur
udev devtmpfs 15904812 4 15904808 1% / dev
tmpfs tmpfs 3184120 1700 3182420 1% / exécution
/ dev / sdb2 ext4 14248880 11464788 2037240 85% /
aucun tmpfs 4 0 4 0% / sys / fs / cgroup
aucun tmpfs 5120 0 5120 0% / run / lock
aucun tmpfs 15920584 848 15919736 1% / run / shm
aucun tmpfs 102400 12 102388 1% / exécution / utilisateur
/ dev / sdb3 ext4 100861352 90755700 4959136 95% / mnt / data

Sous /run/user/il y a un répertoire pour chaque utilisateur normal du système

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

Ces répertoires sont nommés d'après les identifiants de leurs utilisateurs respectifs. Nous pouvons obtenir l'ID utilisateur avec id -uvoir man idpour plus de détails sur cette commande.

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

Nous pouvons ensuite utiliser la mktempcommande avec l' --tmpdiroption pour créer des fichiers et des répertoires temporaires dans ce système de fichiers temporaires, créant ainsi des fichiers temporaires dans la RAM.

En suivant les conseils donnés ici, je crée d'abord un répertoire temporaire, puis je crée mes fichiers temporaires en cela:

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

pour créer un répertoire temporaire /run/user/1000/bash.w42BYxbG/puis

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

pour y créer un fichier temporaire.

Cela facilite le nettoyage de ces fichiers car tout ce que j'ai à faire est rm -r $mydir.

Par défaut, tous ces fichiers sont détenus et lisibles uniquement par l'utilisateur qui les a créés.

Remarque: La $(basename $0)partie de la commande extrait le nom du script / processus qui a exécuté mktemp. Si j'ai un script, /home/jesse/scripts/myScript.shil $(basename $0)revient myScript.shlorsqu'il est exécuté par ce script. Ainsi, les commandes ci-dessus créeraient /run/user/1000/myScript.sh.w42BYxbG/et /run/user/1000/myScript.sh.w42BYxbG/myScript.sh.BCzSmq06respectivement.


/run/user/1000est disponible sur chaque linux qui utilise systemd, il est donc non seulement disponible sur les systèmes basés sur Debian, mais aussi sur la plupart des autres distributions linux. Sinon, / tmp doit être utilisé à la place. Vous pouvez simplifier vos commandes en utilisant la variable $ XDG_RUNTIME_DIR qui conserve déjà le répertoire correct pour chaque utilisateur. Pour plus d'informations, consultez par exemple cette réponse: unix.stackexchange.com/questions/162900/…
Alex

1
Utilisez mkstemp sur mktemp !! Raison de: linux.die.net/man/3/mktemp : dans la section Bugs "... chaque utilisation de mktemp () est un risque pour la sécurité, La course est évitée par mkstemp (3)."
Alex

0

Si je comprends bien, les objectifs sont les suivants : (1) ne stocke le fichier sur le disque inversé, pour être servi au navigateur (note: cela pourrait être tmpfs, etc, comme toutes les autres réponses déjà détail); mais, (2) évitez d'écrire le premier fichier tmp sur le disque, avec la sortie d'origine; et pourtant, (3) affiche toujours la sortie d'origine sur stdout.

Si c'est le cas, les éléments suivants pourraient répondre à vos besoins, en utilisant la substitution de processus bash (c'est-à-dire, essentiellement un canal nommé):

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

Notez que cela imprime en continu la sortie vers stdout et lorsque la commande se termine (lorsque votre boucle se termine), inverse cette sortie et l'écrit dans le fichier de sortie. Illustré via ce qui suit, qui imprime une ligne par seconde, et après la fin, le fichier /tmp/foo.txtcontient les lignes inversées:

i=0
while [ $i -lt 10 ]; do
    ((i = i+1))
    echo "==$i== $(date)"
    sleep 1
done | tee >( tac >> /tmp/foo.txt ) 
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.