23

can anybody give me a solution to truncate all logfile in /var/log/ directory?

and a question just for knowledge, is it a good idea or not?

#!/bin/bash
LOGDIR="/var/log"
for logfile in $(ls $LOGDIR/*log)
do
  truncate -s 0 $logfile
done
1
  • 1
    It's NOT a good idea - /var/log is where the system puts messages you might need later. Ubuntu has encountered the problem before. Read man 8 logrotate;man logrotate.conf.
    – waltinator
    Feb 9, 2019 at 1:55

5 Answers 5

47

try this:

truncate -s 0 /var/log/*log

EDIT:

if you want to do this more than once you should use logrotate to handle your logs. Usually it's installed in ubuntu. Have a look at man logrotate (or if you do not have it installed look at the online manpage or install it with sudo apt-get install logrotate)

from the manpage:

logrotate is designed to ease administration of systems that generate large numbers of log files. It allows automatic rotation, compression, removal, and mailing of log files. Each log file may be handled daily, weekly, monthly, or when it grows too large.

1
  • 1
    also you can empty them by using echo "" > *log
    – Astm
    Dec 23, 2018 at 14:05
11

If you want to clear all your log files, not just those in the first-level log folder, you could use:

shopt -s globstar                  # if needed
truncate -s 0 /var/log/*.log       # first-level logs
truncate -s 0 /var/log/**/*.log    # nested folders, like /var/log/nginx/access.log

Noting that if you already have logrotate running, you'll need to clear out the rotated .gz logs as well:

find /var/log -type f -name '*.[0-99].gz' -exec rm {} +

A valid use for this could be building a VM appliance container for distribution, for example.

You should not need to do this as part of routine maintenance: as D-E-N quite correctly suggested, use logrotate for that.

3

As follow up to @D-E-N answer

This will find all log files in /var/log and truncate them to 0 bytes.

find /var/log -type f -iname '*.log' -print0 | xargs -0 truncate -s0
1
  • 1
    I would use *.log* instead but I'm not sure if it's 100% safe, so I haven't included it in the answer. Because there are files like dovecot.log-20180930 and dovecot.log-20180923.gz.
    – Luka
    Oct 2, 2018 at 18:12
0

There's couple methods to fully truncating a file, generally applicable to most POSIX-compliant OS. Most common that you'll see with shell scripting is something like true > file.txt or : > file.txt ( and in case of bash shell, > redirection alone is sufficient ). That's due to the way how > opens files via open() or openat() syscall with O_WRONLY|O_CREAT|O_TRUNC flags - that reads write-only OR create if filename doesn't exist, OR truncate existing filename.

With that in mind, we can implement something like that in C ourselves:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv){
    if (argc == 2){
        int fd = open(argv[1],O_TRUNC);
        close(fd);
    }

    return 0;
}

Name the file that stores this code as trunc.c and compile that with gcc trunc.c -o trunc, and you have yourself a small utility that will truncate a filename argument it's provided as in trunc ./foobar.txt. Of course, this code doesn't do other checks, it only truncates first positional parameter. I'll leave it up to the readers to figure out how to deal with more than one positional parameter. On side note, there is truncate() syscall which we could use as well, and truncate a file to variable length.

Now, if you are not a fan of C, Python might be easier for you. open() command operates on the same principle in Python - opening file for writing and truncating if filename exists. Thus we can do

python -c 'import sys;open(sys.argv[1],"w").close()' passwd.copy 

As for finding all .log files, that's been covered in other answers already - use * glob or extended glob in bash. There's also find -type f -name "*.log" , which has -exec flag for running commands (in this particular case sh -c '' to take advantage of > because > is a shell operator and not an external executable). Thus you can do

find /var/log -type f -name "*.log" -exec sh -c 'true > "$1"' sh {} \;

It's also worth noting that log files in directory such as /var/log often are rotated by logrotate service, so there will be filenames such as /var/log/service.log, /var/log/service.log.1, etc , so you may want to use *.log.[1-9] pattern instead


Among other things, we can copy /dev/null into the desired file. Oddly enough, even though /dev/null is a special character device type of file, when you copy that elsewhere the result is empty regular file, at least with GNU cp. Thus we can do

cp /dev/null foo.txt

or

dd if=/dev/null of=foo.txt

Other suggested reading:

0

It is good practice to rotate the logs in /var/logs to rotate with logrotate functionality but not whenever we wish to do. System logs will be printed her and they will be handy to debug any failures.

If it is a requirement not to use logrotate, then options can be explored. Though truncate is easy option in few flavors of unix system this command is not available readily, need to be installed.If not allowed to install the new command then below loop can be used.

for logfile $(ls /path/*.log)
do 
  cat /dev/null > $logfile
done
1
  • Bash Pitfall #1: Don't write for loops that way. Use for logfile in /path/*.log instead.
    – PerlDuck
    May 10, 2019 at 11:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .