I believe I have a solution, but it is only tested halfway. Unfortunately, I couldn't test
/dev/xconsole, because I don't have that device on my systems, and I admit that I even don't know what it is and that I don't have the time to research it.
However, there are two good things: First, the following method is generic; that is, you nearly sure can use
/dev/xconsole instead of the file name I have used. Second, I have just tested it on Debian Buster, so it really should work out-of-the-box for you.
I'll first show the (surprisingly simple) solution, then explain how it works, and then show some possible problems and how to circumvent them.
As a precaution, first check whether you have
/usr/sbin/sendmail. This should not be the case, because this program usually belongs to an MTA, but you said you didn't have installed an MTA. If it exists, uninstall the package where it is from.
Now, create a script
/usr/sbin/sendmail with the following content:
Set the permissions accordingly:
chmod a+rx,u+w,og-w /usr/sbin/sendmail
systemctl restart cron
That was it. All error messages
cron would normally send via email are now going into
Of course, you must perform the steps above as root user.
In your case, you probably want to replace
/dev/xconsole (but please remember that I haven't tested this, as outlined above :-)), and you eventually should replace
> (but since I know exactly nothing about
/dev/xconsole, this might be wrong).
How does it work?
Definition: In the following text, I'll use SENDMAIL to denote the SENDMAIL software package, and I'll use
sendmail to denote an application.
Most (or at least, many) programs which send email messages do not themselves implement an SMTP protocol stack which would be needed to talk to an MTA directly via a socket or a network connection, and also don't incorporate SMTP libraries; making mistakes there would be fatal security-wise, and it's just not necessary because in most cases specialized applications come to rescue.
One of those specialized applications is
/usr/bin/sendmail, which is capable of SMTP (and much more), and can be used very easily. A common pattern is:
cat MyMailMessage | /usr/bin/sendmail [sendmail-options]
# OR, even shorter
That is, the application constructs a mail message (which is very easy since it only needs a few headers plus the actual body) and pipes it to
sendmail, which in turn does the SMTP wizardry.
Historically, SENDMAIL was the predominant MTA for a while. SENDMAIL contains not only an MTA, but also an MSP (message submission program). The MSP part is implemented in
/usr/sbin/sendmail. For a long time, nobody got away without SENDMAIL, and therefore many applications still literally rely on
/usr/sbin/sendmail or at least
sendmail to be usable as mail submission program. This is the reason that even SENDMAIL's competitors like POSTFIX still also provide that program as a compatibility wrapper.
cron behaves like other applications in this respect. It is not capable of SMTP. Instead, it relies on
sendmail to actually send messages; it just constructs the raw messages, including headers and body, and pipes them to
sendmail, which in turn actually sends them.
So I just had to replace
/usr/sbin/sendmail by the script shown above (since I have an MTA installed, this was just for testing).
/usr/sbin/sendmail when it tries to send mail, and this now is our script. The script just takes its standard input and redirects it to the file.
As a side note, I actually don't know whether
cron pipes the raw email message directly to
sendmail, or whether it puts it into a temporary file first and then calls
stdin redirected from that file, or whether it does something else.
But that's not important here: The key point is that the raw email message in every case is constructed by
cron, and that
cron puts it into
stdin (however this may be accomplished).
Disadvantages, Problems, Improvements
Please note that using
cat in the script might not be the best choice efficiency-wise, but this depends on your expected output. There are myriads of articles out there which explain how you best can put a script's
stdin into a file; I don't think that this in your question's scope.
One disadvantage of my solution is obvious: Should you ever need the "real"
/usr/sbin/sendmail, we have a problem. I could imagine something subtle: There might be applications which change their behavior (especially, error and status reporting) depending on whether they find
For example, an application may decide to email errors if it finds that executable, but write errors to log files otherwise. This application will now change its behavior. What then happens heavily depends on circumstances. First, you might not find error messages at the usual place. Second, since
sendmail now is our simple script and does not work as the application expects, weird things might happen.
There is a remedy, though: You mentioned that you would accept recompiling
cron. I believe (but can't verify right now) that in its source code, in
config.h, there is a
#define which defines the MSP's name it uses. Then the remedy is clear: Rename our script to
abcd1234, and use that as the value of the
#define, or -probably better- put the script into another directory which is not in the system's search path, and use the complete path to the script as value of the
And while you're at it, you eventually should correct the command line options as well, which are in a separate
#define; they don't hurt our script because it just ignores them, though. Possibly you even could dump the script and direct
cron's error output directly to the file or device you want. Telling whether that would be possible would require further analysis of the source code, which I haven't conducted. I would stick with the script anyway; see the next paragraph for an important reason.
[ Update per 2021-10-20:
As outlined in my comment to your original question from 2021-10-20, there is an alternative way around the problem which saves you from recompiling: Move the "real"
sendmail elsewhere and install the scripts in its place. Then, whenever the script is executed, make it figure out who called it. If
cron has called it, make it behave as shown above; if not, make it call the "real"
sendmail with the same
stdin and parameters, i.e. "relay"
stdin and the parameters to the "real"
Another problem is that you don't see only the error messages you're interested in, but each time see the whole raw email message
cron would send, including the headers. The remedy would be to add some code to our script which filters out the lines you are not interested in, e.g. using
sed and their friends. But this also is outside the scope of this question.