How to suppress harmless warnings?

I have a nightly cron job that builds my site.
This is such that I can publish blog articles in advance and have them published when the publish date arrives…

I run jekyll and redirect STDOUT to /dev/null. This works for most messages. But I still get warnings in STDERR about posts in the future like:

[33m Skipping: _posts/ has a future datee[0

How do I fix this such that I do not get mails every day about this?

I can of course just redirect STDERR to /dev/null as well. However, I do not want to miss actual errors or warnings about stuff that is not harmless.

I am surprised that these messages are printed as warnings to begin with as having posts in the future seems to be built in functionality. So having them skipped should be the normal behavior and not something to warn about.

maybe by using the log level option?

Well, I can set JEKYLL_LOG_LEVEL=error

But then I will miss actual warnings…

Maybe the problem is that this is shown as a warning when it is something that is completely normal behavior… Oh, well. I guess I will just have to suppress all warnings then…

One work-around is to put a filter on the error output, so you’ll only see non-skipping messages:

Jekyll build 2>&1 >/dev/null | grep -v 'Skipping:'

EDIT: Change entire message as I accidentally changed the wrong crontab. Below message reflects reality.

I have a Makefile that does the jekyll build which is run via cron. So I added this to crontab entry:

 make 2>&1 >/dev/null | grep -v 'Skipping:'

Unfortunately, this did not stop the mails from being sent.
Now the mails does indeed no longer have the “Skipping:” lines in them. But instead they have all the STDERR data.

I originally understood the command like this:

After 2>&1 >/dev/null, STDERR is now where STDOUT used to be, and STDOUT is being discarded?
So thus, grep should filter entirely on STDERR

This seems to be incorrect. It seems that 2>&1 merges STDOUT and STDERR. grep then works on that. But that contains all the STDOUT as well which results in me getting mails from cron.

I guess what would solve this would be a way to grep only on STDERR while sending STDOUT to /dev/null. But I am not sure how to do this.

Huh, it looks like Make behaves differently depending on how its output is piped (probably detecting terminal vs non-terminal output). For example, the following two commands behave differently:

% make 2>&1 1>/dev/null               
          Skipping: _posts/2024-10-06-welcome-to-jekyll.markdown has a future date

% make 2>&1 1>/dev/null | cat
jekyll build
Configuration file: _config.yml
            Source: .
       Destination: _site
 Incremental build: disabled. Enable with --incremental
          Skipping: _posts/2024-10-06-post.markdown has a future date
       Jekyll Feed: Generating feed for posts
                    done in 0.192 seconds.
 Auto-regeneration: disabled. Use --watch to enable.

It seem like pushing the make down into a shell script produces the correct behavior. For example, a


make 2>&1 1>/dev/null | grep -v Skip

So you’re saying that the issue is that I invoke make directly in cron not in a terminal? And that having cron instead invoke a shellscript that in turn invokes make should fix this?
Or am I misunderstanding this?

I could not make the solution with pushing it down to a script work…
So I found out the issue seems to be related to the fact that I use zsh and not sh. My crontab also has SHELL=/bin/zsh

When I push it down to a shellscript that uses actual /bin/sh then it works. But with zsh it does not… I am not sure why 2>&1 1>/dev/null behaves differently in sh vs zsh?

I think I will just have to have an actual sh script then… Although, I am a bit nervous that the sh behaves too much differently and may even result in my not getting actual errors that I would like to get… But not sure how to test.