Truncating a file while it's being used (Linux)
NickName:Hobo Ask DateTime:2009-06-11T17:55:58

Truncating a file while it's being used (Linux)

I have a process that's writing a lot of data to stdout, which I'm redirecting to a log file. I'd like to limit the size of the file by occasionally copying the current file to a new name and truncating it.

My usual techniques of truncating a file, like

cp /dev/null file

don't work, presumably because the process is using it.

Is there some way I can truncate the file? Or delete it and somehow associate the process' stdout with a new file?

FWIW, it's a third party product that I can't modify to change its logging model.

EDIT redirecting over the file seems to have the same issue as the copy above - the file returns to its previous size next time it's written to:

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

Copyright Notice:Content Author:「Hobo」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/980283/truncating-a-file-while-its-being-used-linux

Answers
Jono 2013-05-23T17:46:49

Redirect the output using >> instead of >. This will allow you to truncate the file without the file growing back to its original size. Also, don't forget to redirect STDERR (2>&1).\n\nSo the end result would be: myprogram >> myprogram.log 2>&1 &",


Robert Munteanu 2009-06-11T09:58:54

Try > file.\n\n\n\nUpdate regarding the comments: it works nicely for me:\n\nrobert@rm:~> echo \"content\" > test-file\nrobert@rm:~> cat test-file \ncontent\nrobert@rm:~> > test-file\nrobert@rm:~> cat test-file \n",


aish 2014-06-25T12:07:51

I had a similar issue on redhat v6, echo > file or > file was causing apache and tomcat to go faulty as log files would become inaccessible to them.\n\nAnd the fix was strange\n\necho \" \" > file\n\n\nwould clean the file and not cause any problem.",


Arthur Ulfeldt 2009-06-12T02:15:41

In Linux (actually all unicies) files are created when they are opened and deleted when nothing holds a reference to them. In this case the program that opened it and the directory it was opened 'in' hold references to the file. When the cp program wants to write to the file it gets a reference to it from the directory, writes a length of zero into the metadata stored in the directory (this is a slight simplification) and gives up the handle. Then the original program, still holding the original file handle, writes some more data to the file and saves what it thinks the length should be. \neven if you where to delete the file from the directory the program would continue to write data to it (and use up disc space) even though no other program would have any way of referencing it. \nin short once the program has a reference (handle) to a file nothing you do is going to change that. \nthere are in theory ways of modifying the programs behavior by setting LD_LIBRARY_PATH to include a program that intercepts all the file access system calls. I recall seeing something like this somewhere though cant recall the name. ",


Michiel Buddingh 2009-06-11T10:00:52

Take a look at the utility split(1), part of GNU Coreutils.",


Billy 2009-06-11T10:34:43

as the file is being used, if you try to nullify it or something like that, sometimes it might \"confuse\" the app that's writing into the log file and it might not log anything after that. \n\nWhat I'd try ot do is to set up a kind of proxy/filter for that log, instead of redirecting to file, redirect to a process or something that would get input and write to a rolling file.\n\nMaybe it can be done by script otherwise you could write a simple app for that ( java or something else ). The impact on app performance should be quite small, but you'll have to run some tests.\n\nBtw, your app, is it a stand-alone, web app, ... ? Maybe there are other options to be investigated.\n\nEdit: there's also an Append Redirection Operator >> that I've personally never used, but it might not lock the file.",


Larry Irwin 2011-06-20T18:30:03

I downloaded and compiled the latest coreutils so I could have truncate available.\n\nRan ./configure and make, but did not run make install.\n\nAll the compiled utilities appear in the \"src\" folder.\n\nI ran \n\n[path]/src/truncate -s 1024000 textfileineedtotruncate.log \n\non a 1.7 GB log file.\n\nIt did not change the size listed when using ls -l, but it did free up all the disk space - which is what I really needed to do before /var filled up and killed the process.\n\nThanks for the tip on \"truncate\"!",


Vex 2009-06-11T10:40:47

Did you check the behavior of any signals like SIGHUP to the third party product, to see if it will start logging a fresh file? You would move the old file to a permanent name, first.\n\nkill -HUP [process-id]\n\nAnd then it would start writing out again.\n\nAlternatively (as Billy suggested) maybe redirecting the output from the application to a logging program like multilog or the one that is commonly used with Apache, known as cronolog. Then you'll have more fine grained control of where everything goes before it is written to that initial file descriptor (file), which is really all it is.",


Peter Eisentraut 2010-07-16T11:03:40

As of coreutils 7.0, there is a truncate command.",


Arthur Ulfeldt 2009-06-12T17:18:31

instead of redirecting it to a file you could pipe it to a program that automatically rotates the file by closing it, moving it and opening a new one every time it gets too big. ",


Jonathan Leffler 2009-06-12T02:40:32

The interesting thing about those regrown files is that the first 128 KB or so will be all zeroes after you truncate the file by copying /dev/null over it. This happens because the file is truncated to zero length, but the file descriptor in the application still points immediately after its last write. When it writes again, the file system treats the start of the file as all zero bytes - without actually writing the zeroes to disk.\n\nIdeally, you should ask the vendor of the application to open the log file with the O_APPEND flag. This means that after you truncate the file, the next write will implicitly seek to the end of the file (meaning back to offset zero) and then write the new information.\n\n\n\nThis code rigs standard output so it is in O_APPEND mode and then invokes the command given by its arguments (rather like nice runs a command after adjusting its nice-level, or nohup runs a command after fixing things so it ignores SIGHUP).\n\n#include <stdlib.h>\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <errno.h>\n\nstatic char *arg0 = \"<unknown>\";\n\nstatic void error(const char *fmt, ...)\n{\n va_list args;\n int errnum = errno;\n fprintf(stderr, \"%s: \", arg0);\n va_start(args, fmt);\n vfprintf(stderr, fmt, args);\n va_end(args);\n if (errnum != 0)\n fprintf(stderr, \" (%d: %s)\", errnum, strerror(errnum));\n putc('\\n', stderr);\n fflush(0);\n exit(1);\n}\n\nint main(int argc, char **argv)\n{\n int attr;\n arg0 = argv[0];\n\n if (argc < 2)\n error(\"Usage: %s cmd [arg ...]\", arg0);\n if ((attr = fcntl(1, F_GETFL, &attr)) < 0)\n error(\"fcntl(F_GETFL) failed\");\n attr |= O_APPEND;\n if (fcntl(1, F_SETFL, attr) != 0)\n error(\"fcntl(F_SETFL) failed\");\n execvp(argv[1], &argv[1]);\n error(\"failed to exec %s\", argv[1]);\n return(1);\n}\n\n\nMy testing of it was somewhat casual, but just barely enough to persuade me that it worked.\n\n\n\nSimpler alternative\n\nBilly notes in his answer that '>>' is the append operator - and indeed, on Solaris 10, bash (version 3.00.16(1)) does use the O_APPEND flag - thereby making the code above unnecessary, as shown ('Black JL:' is my prompt on this machine):\n\nBlack JL: truss -o bash.truss bash -c \"echo Hi >> x3.29\"\nBlack JL: grep open bash.truss\nopen(\"/var/ld/ld.config\", O_RDONLY) Err#2 ENOENT\nopen(\"/usr/lib/libcurses.so.1\", O_RDONLY) = 3\nopen(\"/usr/lib/libsocket.so.1\", O_RDONLY) = 3\nopen(\"/usr/lib/libnsl.so.1\", O_RDONLY) = 3\nopen(\"/usr/lib/libdl.so.1\", O_RDONLY) = 3\nopen(\"/usr/lib/libc.so.1\", O_RDONLY) = 3\nopen(\"/platform/SUNW,Ultra-4/lib/libc_psr.so.1\", O_RDONLY) = 3\nopen64(\"/dev/tty\", O_RDWR|O_NONBLOCK) = 3\nstat64(\"/usr/openssl/v0.9.8e/bin/bash\", 0xFFBFF2A8) Err#2 ENOENT\nopen64(\"x3.29\", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3\nBlack JL:\n\n\nUse append redirection rather than the wrapper ('cantrip') code above. This just goes to show that when you use one particular technique for other (valid) purposes, adapting it to yet another is not necessarily the simplest mechanism - even though it works.",


Yogesh 2012-11-05T10:29:21

@Hobo use freopen(), it reuses stream to either open the file specified by filename or to change its access mode.\nIf a new filename is specified, the function first attempts to close any file already associated with stream (third parameter) and disassociates it. Then, independently of whether that stream was successfully closed or not, freopen opens the file specified by filename and associates it with the stream just as fopen would do using the specified mode.\n\nif a thirdparty binary is generating logs we need to write a wrapper which will rotate the logs, and thirdparty will run in proxyrun thread as below.\n\n#include <pthread.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <unistd.h>\n#include <string.h>\n\nusing namespace std;\n\nextern \"C\" void * proxyrun(void * pArg){\n static int lsiLineNum = 0;\n while(1) \n {\n printf(\"\\nLOGGER: %d\",++lsiLineNum);\n fflush(stdout);\n }\n return NULL;\n}\n\n\nint main(int argc, char **argv)\n{\n pthread_t lThdId;\n if(0 != pthread_create(&lThdId, NULL, proxyrun, NULL))\n {\n return 1;\n }\n\n char lpcFileName[256] = {0,};\n\n static int x = 0;\n\n while(1)\n {\n printf(\"\\n<<<MAIN SLEEP>>>\");\n fflush(stdout);\n sprintf(lpcFileName, \"/home/yogesh/C++TestPrograms/std.txt%d\",++x);\n freopen(lpcFileName,\"w\",stdout);\n sleep(10);\n }\n\n return 0;\n}\n",


More about “Truncating a file while it's being used (Linux)” related questions

StreamWriter truncating text while writing to a text file

I have a huge content in a string variable and I want to write that content to a text file using stream writer. But the stream writer is truncating the text and not writing the whole content to fil...

Show Detail

ORA-00911: invalid character error while truncating table

I have a table that name is _VERSION_HISTORY I got ORA-00911 error while truncating this table. Oracle allow the name start with underscore(_) but throws an error while truncating it. Is it a silly

Show Detail

truncating a text file does not change the file

When a novice (like me) asks for reading/processing a text file in python he often gets answers like: with open("input.txt", 'r') as f: for line in f: #do your stuff Now I would like to

Show Detail

Truncating a file while it's being used (Linux)

I have a process that's writing a lot of data to stdout, which I'm redirecting to a log file. I'd like to limit the size of the file by occasionally copying the current file to a new name and trun...

Show Detail

macos: different output of arrays truncating in commnad line and bash file

The same set of commands gives a different output while run directly on the command window and while written in a file: xxx-MacBook-Air ~ % bash b a b c b c b c xxx-MacBook-Air ~ % all=(a b c); ech...

Show Detail

Truncating file when using csvreader

I have a csv file that is 2.2M lines. However, when I try and read it with csvreader it truncates it to 170,000 lines. Why does this occur and how can I load the entire file into a csv reader? rea...

Show Detail

Is there any solution for avoiding data truncating in pdf export of rpt design file in eclipse?

There are about 15 columns in my report file in birt eclipse. I have been facing issue of data truncating/ column cutting while exporting to pdf. Is there any way we can avoid truncation and show f...

Show Detail

Truncating netCDF

I have a netCDF file of monthly surface air temperature from 1850-2005. How can I truncate the file in unix so that the new file has a time dimension from 1855 - 2005? And vice versa, truncating th...

Show Detail

Keep count of occurrences in a truncating file

Let's say I have a file called data.log. Data constantly gets appended to it which can contain 'flag' and it gets truncated by an external script: [13/Jan/2015:11:11:53 +0000] curabitur flag la...

Show Detail

Override data without truncating the file

When I make a growing file in php, I usually use the _file_put_contents_ function with FILE_APPEND and LOCK_EX flags. Non, I have a growing video file that I play with mplayer. To avoid that the f...

Show Detail