From echo to syslog: Smarter logging for your scripts

… or: how to use the logger command to send messages into the system log.

If you are monitoring or troubleshooting a Linux system, then one of the most important things to check is the logfiles.

Running services like Postfix or Apache write them, tiny tools like sudo write logs - and even the system itself, the kernel, tells you what it’s doing and what didn’t go so smoothly.

What if your cronjobs or scripts could do the same? You could simply use your known toolbox - grep, less, tail, and friends - to see what’s going on, or use the more modern journalctl.

Here’s the thing: you can easily write your own logs from the command line (and therefore from cronjobs or scripts) and inject your own messages into those central log repositories.

And if you know a few basic concepts, you can even filter your messages into certain files or “sections” of your system log.

But first: why not just append your messages to your own log file?

You could, of course, log messages yourself by just appending them to a file:

echo "my message" >> my-logfile

That works - but it misses some smart benefits you get when you log messages the way I’ll show you next:

  • Automatic timestamping and tagging
    Messages written via the syslog protocol (RFC 5424 / 3164) - that’s what we’ll use - include timestamps, hostnames, and tags automatically.
  • Centralized handling
    Your messages become part of the system’s managed logs, so they rotate, compress, and get archived together with the rest.
  • Remote logging integration
    Syslog already supports forwarding logs to a central host. So if your system’s rsyslog or syslog-ng is configured for remote forwarding, your messages will follow automatically.

Once you use the existing log infrastructure, your messages show up in the same places as the rest of the system - viewable with grep, less, or journalctl.

So, how can you tap into that same system yourself? Let’s look at the command that makes this easy.

Say hello to logger

The essential tool for writing to the local log system is logger.

To log a simple test message, just append it as a parameter:

logger "test message"

Instantly you’ll find this message somewhere within /var/log/*. On my Ubuntu system, it shows up in /var/log/syslog:

grep "test message" /var/log/syslog
2025-10-17T09:55:17.645712+00:00 demo robert: test message

And if your system runs systemd (who doesn’t these days), you can see the same message via journalctl:

[robert@demo ~]$ journalctl | grep "test message"
Oct 17 09:55:17 demo robert[2451]: test message

Anyone who has write access to /dev/log (or “/run/systemd/journal/dev-log”, where “/dev/log” usually points to) can inject messages this way - and typically, that means everyone.

Side note: To be more technically accurate - while any user appears to have write access to “/dev/log” (or the socket it links to), the log system only accepts messages if they come from root or a local user with a UID ≥ 1000. In practice, that means that any “normal” local user can write to the system log.

Need to log the output from a command or tool? Just pipe it to logger:

# write the output of "w" to logger
w | logger

# write the output of top to logger
top -b -n1 | logger

Mark your messages for easier discovery later

If you want to recognize or filter your messages later, it’s helpful to mark them.
You can do this in two ways: by adding a tag, or by setting a facility and a level.

Set a tag

Every message that flows through the syslog system has a tag associated with it.

logger uses, by default, the name of the user who sent the message. You can see this as the string robert: within the test message:

[robert@demo ~]$ grep "test message" /var/log/syslog
2025-10-17T09:55:17.645712+00:00 demo robert: test message
                                      ^^^^^^^

To set your own tag - so you can later grep your messages out of the chaos - use the parameter -t followed by a tag name of your choice:

[robert@demo ~]$ logger -t BACKUP "test message 2"
[robert@demo ~]$ grep "test message 2" /var/log/syslog
2025-10-17T10:03:20.941254+00:00 demo BACKUP: test message 2

From now on, you can find all your tagged messages easily:

grep "BACKUP:" /var/log/syslog

And of course,journalctl can also filter messages by their tag:

[robert@demo ~]$ journalctl -t BACKUP
Oct 17 10:03:20 demo BACKUP[3380]: test message 2

Side note: Notice how journalctl shows the number “3380” next to the tag? That’s the process ID (PID) of the “logger” command that sent the message.

Set a facility and level

Sometimes you want to mark your message as belonging to a certain category (facility) or priority (level). This could be great if you want your message to finally appear in a specific predefined log file - for example /var/log/mail.err for email-related errors.

If you wanna to this, you need to know that with syslog, both the facility and the level must be chosen from a predefined set of values:

Facilities:
auth, authpriv, cron, daemon, ftp, kern (kernel messages, not usable from userspace),
lpr, mail, news, syslog, user, uucp, and local0local7.

Priorities (levels), sorted by importance:
debug, info, notice, warning, err, crit, alert, emerg.

To use them with logger, specify both together - connected with a dot - using the -p option.

example: send an error message regarding the mail system:

logger -p mail.err "email doesn't work"

On my Ubuntu system with a default rsyslog configuration, this message goes straight into /var/log/mail.err:

[robert@demo ~]$ grep "email doesn't work" /var/log/mail.err 
2025-10-17T10:15:53.702791+00:00 demo robert: email doesn't work

And of course, you can filter these messages in the journal too:

[robert@demo ~]$ journalctl --facility=mail --priority=err
Oct 17 10:15:53 demo robert[3972]: email doesn't work

Use it in cron or from your scripts

Now let’s use this in the real world.

Here’s a cronjob that logs the output of w (who’s logged in and from where) every full hour:

0 * * * * nobody w | logger -t STATUS

Or, imagine you use rsync in a script to create a backup of important data.

Then logger can be the perfect add-on to log the success or failure of every run:

#!/bin/bash
if rsync -a /data /backup; then
    logger -t BACKUP -p local0.info "Backup completed successfully"
else
    logger -t BACKUP -p local0.err "Backup failed!"
fi

From now on, every script you write can talk to the same logging system as your kernel - clean, timestamped, and easy to search.