Konstantin Khomoutov found two problems in ejabberd reopen-log command, and wrote a preliminary patch:
Now I rewrite his explanations:
1. erlang.log for some reason only gets reopened each second call to `ejabberdcl reopen-log`
2. After reopening the same files (that is, when the files were not renamed before reopening, by logrotate or whoever), erlang.log gets truncated, and ejabberd.log gets renamed to "ejabberd-old.log". Both behaviours break the "reopening of log files" contract common in Unix.
In ejabberd, when you do `ejabberdctl reopen-log`, your log files (at least ejabberd.log) end up being renamed to ejabberd-old.log. This is definitely not the expected behaviour of "reopening log files", which must be idempotent on Unix. ejabberd must not mess with log names in any way.
Reopening should work this way:
i) Remember the name of log file.
ii) Close it.
iii) Open it by name.
And who takes care to rename the old log file? The system log rotation software (typically Logrotate). This program usually rotates the log file of a program this way:
1) Renames the log file. ejabberd continues to write to that file, as it uses file descriptor which doesn't care about renames/deletions.
2) Call ejabberd to reopen its logs.
3) ejabberd performs the steps i, ii, iii mentioned before: ejabberd reopens its log files by name and starts to write to its "usually named" files
4) The system log rotation script stores the old closed log files.
The patch fixes these problems in the following way:
- The SASL application is started with its built-in file logger disabled. After this a custom module is inserted to handle SASL messages; this module does not truncate its log file when reopening it.
- Built-in ejabberd's "log rotation" (renaming original log files by appending the "-old" suffix to their base names) is disabled.
- Both ejabberd's logging module and the custom SASL logging module now respond to a custom event which instructs them to reload their respective log files; this event is synchronously sent to these modules when `ejabberdctl reopen-log` is being run.
The scheme previously mentioned does not work on Windows because in 99% of cases the program which opens a file for writing locks it at least for writing and sometimes it locks it for reading as well.
A solution is to implement an ejabberd command to reopen the logs and also rename them: rotate-log.
This is useful not only for Windows, but also for Unix machines where Logrotate isn't avaiable, or the admin doesn't know to setup it, or the ejabberd Binary Installer can't configure it.