Tronquer un fichier alors qu'il est utilisé (Linux)
J'ai un processus qui écrit un grand nombre de données sur la sortie standard, qui je suis rediriger vers un fichier journal. J'aimerais limiter la taille du fichier par parfois de copier le fichier en cours d'un nouveau nom et en la tronquant.
Mes techniques habituelles de la troncature d'un fichier, comme
cp /dev/null file
ne fonctionnent pas, sans doute parce que le processus est en l'utilisant.
Est-il une manière que je peux tronquer le fichier? Ou de le supprimer et en quelque sorte associé à la méthode " stdout avec un nouveau fichier?
FWIW, c'est un produit de tiers que je ne peux pas modifier son modèle d'enregistrement.
MODIFIER rediriger sur le fichier semble avoir le même problème que la copie ci - dessus le fichier revient à sa taille précédente prochaine fois:
ls -l sample.log ; echo > sample.log ; ls -l sample.log ; sleep 10 ; ls -l sample.log
-rw-rw-r-- 1 user group 1291999 Jun 11 2009 sample.log
-rw-rw-r-- 1 user group 1 Jun 11 2009 sample.log
-rw-rw-r-- 1 user group 1292311 Jun 11 2009 sample.log
Vous devez vous connecter pour publier un commentaire.
Prendre un coup d'oeil à l'utilitaire
split(1)
, une partie de GNU Coreutils.De coreutils 7.0, il est un
truncate
commande.truncate -s 0 GC.log
pendant quelques secondes, montre un "tronquée" du fichier, après ce temps (je suis à deviner lorsque l'application écrit plus) - le fichier est revenue à sa taille d'origine.La chose intéressante à propos de ces repoussé les fichiers, c'est que les premiers 128 KO ou seront tous les zéros après vous tronquer le fichier en le copiant
/dev/null
sur elle. Cela se produit parce que le fichier est tronqué à longueur de zéro, mais le fichier descripteur de l'application des points encore immédiatement après sa dernière écriture. Quand il écrit encore, le système de fichiers traite le début du fichier, comme tous les octets zéro - sans écrire des zéros sur le disque.Idéalement, vous devriez demander au fournisseur de l'application pour ouvrir le fichier journal avec le
O_APPEND
drapeau. Cela signifie que, après vous tronquer le fichier, l'écriture suivante sera implicitement à rechercher à la fin du fichier (sens retour à décalage de zéro), puis d'écrire les nouvelles informations.Ce code d'habillages de sortie standard, il est donc dans
O_APPEND
mode et invoque ensuite le commandement donné par ses arguments (un peu commenice
exécute une commande après le réglage de sa belle-niveau, ounohup
exécute une commande après la fixation de choses de sorte qu'il ignore SIGHUP).Mes tests d', c'était un peu désinvolte, mais à peine assez pour me convaincre qu'il a travaillé.
Alternative plus simple
Billy des notes dans son réponse que "
>>
' est l'ajout de l'opérateur - et en effet, sur Solaris 10, bash (version 3.00.16(1)) n'utiliser leO_APPEND
drapeau - ce qui rend le code ci-dessus inutiles, comme le montre ('Black JL:' est mon invite sur cette machine):Ajouter utiliser la redirection plutôt que de l'emballage ('cantrip') code ci-dessus. Cela va juste pour montrer que lorsque vous utilisez une technique particulière pour d'autres (valide) fins, en l'adaptant à un autre n'est pas forcément le plus simple mécanisme - même si cela fonctionne.
Rediriger la sortie à l'aide d' >> au lieu de >. Cela vous permettra de tronquer le fichier sans le fichier de revenir à sa taille d'origine. Aussi, n'oubliez pas de rediriger STDERR (2>,&1).
De sorte que le résultat final serait:
myprogram >> myprogram.log 2>&1 &
Essayer
> file
.Mise à jour concernant les commentaires: il fonctionne très bien pour moi:
J'ai eu un problème similaire sur redhat v6,
echo > file
ou> file
était à l'origine apache et tomcat pour aller défectueux comme les fichiers journaux deviendrait inaccessible.Et le correctif était étrange
de nettoyer le fichier et ne cause aucun problème.
que le fichier est utilisé, si vous essayez d'annuler ou quelque chose comme ça, il peut parfois "confondre" l'application qui est écrit dans le fichier journal et il pourrait ne pas connecter quoi que ce soit après que.
Ce que je voudrais essayer ot faire est de créer une sorte de proxy/filtre pour ce journal, au lieu de rediriger vers un fichier, de rediriger un processus ou quelque chose qui pourrait obtenir l'entrée et à écrire à un roulement de fichier.
Peut-être, il peut être fait par le script sinon, vous pouvez écrire une application simple pour que ( java ou autre ). L'impact sur les performances de l'application doit être assez petite, mais vous aurez à faire quelques tests.
Btw, votre application, c'est un stand-alone, web app, ... ? Peut-être il y a d'autres options à étudier.
Edit: il y a aussi un Ajouter la Redirection de l'Opérateur >> que je n'ai personnellement jamais utilisé, mais il pourrait ne pas verrouiller le fichier.
Sous Linux (en fait tous les unicies) les fichiers sont créés lorsqu'ils sont ouverts et supprimés lorsque rien n'est titulaire d'une référence à eux. Dans ce cas, le programme qui l'a ouvert et le répertoire, il a été ouvert 'à' conserver les références au fichier. Lorsque le programme de pc veut écrire dans le fichier, il obtient une référence à partir du répertoire, écrit une longueur de zéro dans les métadonnées stockées dans le répertoire (ce qui est une légère simplification) et donne de la poignée. Ensuite, le programme d'origine, tenant toujours le fichier d'origine de la poignée, écrit encore plus de données pour le fichier et enregistre ce qu'il pense que la longueur doit être.
même si vous supprimez le fichier à partir du répertoire, le programme continuera à écrire des données de (et l'utilisation de l'espace disque), même si aucun autre programme aurait aucun moyen de référence.
bref une fois que le programme a une référence (poignée) pour un fichier, rien ne va changer ça.
il y a, en théorie, les moyens de modifier le comportement de programmes par la mise en LD_LIBRARY_PATH pour inclure un programme qui intercepte tous les accès aux fichiers, les appels système. Je me souviens avoir vu quelque chose comme ça, quelque part, mais ne me souviens pas le nom.
J'ai téléchargé et compilé la dernière
coreutils
si je pouvais avoirtruncate
disponibles.Couru
./configure
etmake
, mais n'a pas courumake install
.Tous la compilation d'utilitaires de figurer dans le "src" le dossier.
J'ai couru
[path]/src/truncate -s 1024000 textfileineedtotruncate.log
sur un 1.7 GO de fichier journal.
Il ne modifie pas la taille inscrites lors de l'utilisation de
ls -l
, mais il l'a fait libérer tout l'espace disque - qui est ce que j'ai vraiment dû faire avant de/var
rempli et tué le processus.Merci pour l'astuce sur "tronquer"!
Avez-vous vérifier le comportement de tous les signaux comme un signal SIGHUP au produit de tiers, pour voir si elle va démarrer l'enregistrement d'une nouvelle fichier? Vous devez déplacer l'ancien fichier d'un nom, d'abord.
kill-HUP [id du processus]
Et puis il serait de commencer à écrire de nouveau.
Sinon (comme Billy suggéré) peut-être rediriger la sortie de l'application d'un programme d'enregistrement comme multilog ou celle qui est couramment utilisé avec Apache, connu comme cronolog. Ensuite, vous aurez plus de contrôle de précision, d'où tout va de l'avant, il est écrit initial descripteur de fichier (file), qui est vraiment tout ce qu'il est.
@Hobo utilisation freopen(), il réutilise les flux à ouvrir le fichier spécifié par filename ou de changer son mode d'accès.
Si un nouveau nom de fichier est spécifié, la fonction tente d'abord de fermer n'importe quel fichier qui est déjà associée à un flux de données (troisième paramètre) et dissocie il. Puis, indépendamment du fait que ce cours d'eau a été fermé avec succès ou non, freopen ouvre le fichier spécifié par filename, et l'associe avec le cours d'eau tout comme fopen ferait en utilisant le mode spécifié.
si un tiers binaire est la production de journaux, il nous faut écrire un wrapper qui va tourner les journaux, et d'un tiers, sera exécuté dans proxyrun fil comme ci-dessous.
au lieu de rediriger vers un fichier, vous pouvez le diriger vers un programme qui tourne automatiquement le fichier en clôture, le déplacer et d'en ouvrir un nouveau à chaque fois qu'il devient trop grand.
J'ai eu un problème similaire et a été incapable de faire un "tail-f" sur la sortie d'un script qui a été lancé par cron:
Je l'ai corrigé en modifiant le rediriger stderr: