I have just bumped myself to the same issue. Your error message:
error: error creating output file /var/log/syslog.1.gz: File exists
indicates that the file syslog.1.gz exists. @madduck can you check that the
file doesn't really exist?
In my case a previous logrotate command must have been interrupted while
gzipping, creating:
syslog
syslog.1
syslog.1.gz
syslog.2.gz
etc
where syslog.1.gz was of 0 size. Apparently, the compression error causes this
to not attempt rename and rotation.
I suggest adding some handling to logrotate so that it would check the
destination file's existance.
In the patch attached I am modifying the 'createOutputFile' function to stat
the destination file and either
remove it (if it's of size 0) or rename it to .garbage (otherwise).
I have given very little testing to this patch, please review&test it.
--- logrotate-3.8.7.orig/logrotate.c
+++ logrotate-3.8.7/logrotate.c
@@ -300,10 +300,34 @@ static int runScript(struct logInfo *log
int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, int force_mode)
{
int fd;
- struct stat sb_create;
- int acl_set = 0;
+ struct stat sb_create;
+ int acl_set = 0;
- fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
+ if (stat(fileName, &sb_create) == 0) {
+ /* this indicates that the destination file exists, while it should not */
+ if (sb_create.st_size == 0) {
+ /* the file is of zero size, so not needed */
+ if (unlink(fileName) != 0) {
+ message(MESS_ERROR, "output file %s exists and failed to remove it: %s\n",
+ fileName, strerror(errno));
+ return -1;
+ }
+ } else {
+ int fnlength=sizeof(fileName);
+ char* garbage=malloc(fnlength+8); /* 'garbage\0' */
+ strncpy(garbage, fileName, fnlength);
+ strncpy(garbage+fnlegth, "garbage\0");
+ if (rename(filename,garbage) != 0) {
+ message(MESS_ERROR, "output file %s exists and failed to rename it to %s: %s\n",
+ fileName, garbage, strerror(errno));
+ free(garbage);
+ return -1;
+ }
+ free(garbage);
+
+ }
+
+ fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
(S_IRUSR | S_IWUSR) & sb->st_mode);
if (fd < 0) {