84

I was wondering if there was a proper way to clear logs in general?

I'm new to Ubuntu and I'm trying to set up Postfix. The log in question is /var/log/mail.log. I was wondering if there was a correct way to clear it, rather than me going in it and deleting all the lines and saving it. I find that sometimes errors don't get written to it immediately after I clear the log and save it.

Side note: I'm having trouble setting up Postfix and am trying to make it easier for me to read the logs hoping it can help me out, instead of having to scroll all the way down.

mastofact
  • 943
  • 1
  • 7
  • 5
  • 3
    if you want to just see the end of the file then [**tail**](http://linux.die.net/man/1/tail) is your friend. tail /var/log/mail.log to display the last 5 lines. tail -f /var/log/mail.log to see all lines written to the end of the file. – user9517 Jun 30 '11 at 16:25
  • http://serverfault.com/questions/285843/is-there-a-proper-way-to-clear-logs/381380#comment391549_285847 – poige Apr 20 '12 at 01:29

9 Answers9

92

You can use:

> /var/log/mail.log

That will truncate the log without you having to edit the file. It's also a reliable way of getting the space back.

In general it's a bad thing to use rm on the log then recreating the filename, if another process has the file open then you don't get the space back until that process closes it's handle on it and you can damage it's permissions in ways that are not immediately obvious but cause more problems later on.

Yasar has a nice answer using truncate

Also if you are watching the contents of the log you might like to use the tail command:

tail -f /var/log/mail.log

Ctrl-C will break off the tailing.

gm3dmo
  • 9,632
  • 1
  • 40
  • 35
  • 2
    `/bin/csh` (common for FreeBSD) would bail out this with "Invalid null command", meanwhile `zsh` (popular replacement for `bash`) would wait EOF. See http://serverfault.com/a/381380/67675 – poige Apr 20 '12 at 01:29
  • how can I schedule it ? putting `>` syntax in crontab is not running as it may not be recognising it as a syntax – ishandutta2007 Mar 06 '19 at 11:03
  • 1
    note that `sudo "> /var/log/mail.log"` will not work, see https://stackoverflow.com/a/82278/3025740 – Cédric Van Rompay Nov 10 '19 at 12:48
  • Rather than a proper way, I'd call it a when-can't-free-space way :) And not sure if it matters, but you might want to `service syslog restart`. See also [this answer](https://stackoverflow.com/a/62490004/52499). – x-yuri Jun 30 '21 at 11:48
38

You can use this too..

truncate /opt/package/logs/*.log --size 0

Here all log files in the /opt/package/logs will become empty..

HBruijn
  • 72,524
  • 21
  • 127
  • 192
Yasar
  • 491
  • 4
  • 2
  • I don't see how this could be any better than the older answers. – kasperd Jun 25 '15 at 06:42
  • 14
    This is actually a very good answer, and really the only one that directly answers the question of if there's a proper way to truncate logfiles. HOW it's better than the other answers is that is doesn't DELETE the logfile, it zeros the contents properly, thus permission errors and missing logfiles which cause some daemons to panic will not occur in this case. – hmedia1 Jun 12 '17 at 02:51
  • Best answer, for the reasons that hmedia1 laid out. – MiloDC Mar 27 '21 at 02:30
30

Yes, there's a proper way: You don't clear logs at all. You rotate them. Rotation involves switching log output to a new file, under the same name, with the previous N log files kept under a set of N related filenames.

How one rotates logs depends from how one is writing them in the first place. This is an oft-overlooked point. Some of the answers here touch upon it at least, mentioning that some logging programs keep an open file descriptor for the log file, so just deleting the file won't free up the space, or indeed even switch output to a fresh log file.

If the program writing the log file is multilog from the daemontools package, for example, then you don't do anything to rotate the logs at all — no manual scripts, no cron jobs. Simply tell multilog that log output is to a directory, and it will itself maintain an automatically rotated and size-capped set of N log files in that directory.

If the program writing the log files is svlogd from the runit package, for another example, then much the same applies. You don't do anything at all apart from point the tool at a directory. It will itself maintain an automatically rotated and size-capped set of N log files in that directory.

If you are using rsyslog to write log files, then the logging program can be told to stop after the log file reaches a certain size and run a script. You have to write the meat of the script, to actually rename the log file and delete old log files based upon total size constraints, but at least the logging program has closed the file and paused log writing whilst this is happening.

The old syslogd way of rotating logs, still expected by logging programs such as syslog-ng and as exemplified by tools such as logrotate mentioned by djangofan in another answer here, is somewhat more haphazard. One runs a cron job that periodically renames the log files, and restarts the logging daemon (using whatever daemon supervisor it is running under). The problem with this, of course is that it doesn't enforce an overall size cap. On slow weeks one can get N very small daily log files, whereas on busy days one can get 1 very big log file that's well over the size limit.

This is why later and better tools like multilog and svlogd have file size configuration options and actually check the log file sizes themselves, of course. The world has learned that polling the logs on a schedule with cron jobs, or even a logrotate daemon, leaves windows for the size to be wrong, and that the proper place to have these checks, and so rigourously enforce administrator-defined size caps so that one's log files don't ever swallow the partition that they are on, is in the program that is actually writing the files out in the first place.

JdeBP
  • 3,970
  • 17
  • 17
  • As for rsyslog, it can be easily configured so to rely on filenames described by a "pattern" including, for example, YEAR, MONTH, and DAY. This is as easy as having a `template(name="DYNmail" type="string" string="/var/log/%$YEAR%/%$MONTH%/%$DAY%/mail.log")` directive, followed by a `if ($syslogfacility-text == 'mail') then -?DYNmail;TraditionalFormat`. In this way, log-rotation is simply a non-problem, at least when a single file per-day is ok. For very high-volumes of log (needing multiple rotation per-day), there is `$HOUR` as well. – Damiano Verzulli Jul 01 '15 at 20:02
11

Yes, there is a tool for linux called LogRotate .

gWaldo
  • 11,887
  • 8
  • 41
  • 68
djangofan
  • 4,172
  • 10
  • 45
  • 59
  • 9
    Just a small correction: this is not a service, this is a tool, usually running from cron service. – rvs Jun 30 '11 at 16:38
10

If the reason you clear the log is to free space, you can cat /dev/null to them, without interrupting programs writing into it. Never delete them ! some software might complain by stop working or ignoring the log completely until next restart

cat /dev/null > /path/to/logfile

# to empty all the logs in a directory
for i in /var/log/*; do cat /dev/null > $i; done
Elvis
  • 201
  • 2
  • 4
  • 3
    To clear log files recursively: `for i in $(find /var/log -type f); do cat /dev/null > $i; done` – Iurie Feb 20 '17 at 07:50
4

Short and compatible content overwriting: : > /dest/file

But there's also truncate(2) system call, and corresponding userspace tool truncate on many *NIX'es.

poige
  • 9,171
  • 2
  • 24
  • 50
1

If you want to keep the file before cleaning it up, you can do:

cp /var/log/mail.log /var/log/mail.log.1 && echo -n "" > /var/log/mail.log

If you want to do search for an specific text or email in the log you can use grep. If you want to keep some graphics about mail usage you can use AWStats.

ghm1014
  • 944
  • 1
  • 5
  • 14
1

Here's how I do it, and this is just for NGINX, you can remove that to make it work on all log files.

# Clear nginx logs.
# @usage delnginxlogs
function delnginxlogs() {
  echo "--------------- ⏲  Clearing logs... ---------------"

  # Clear logs.
  for i in /var/log/nginx/*; do cat /dev/null > $i; done

  echo "--------------- ⏲  Deleting .gz log files... ---------------"

  # Delete .gz files.
  find /var/log/nginx -type f -regex ".*\.gz$" -delete

  echo "---------------  DONE: NGINX logs cleared ... ---------------"
}
Ahmad Awais
  • 111
  • 3
-2

cat /dev/null > /path/to/logfile

Works for me