7

I like the idea of using systemd's journal to view and manage the logs of my own scripts. I have become aware you can log to journal from my user scripts on a per message basis..

echo 'hello' | systemd-cat -t myscript -p emerg

Is there a way to redirect all messages to journald, even those generated by other commands? Like..

exec &> systemd-cat

Update:

Some partial success. Tried Inian's suggestion from terminal.

~/scripts/myscript.sh 2>&1 | systemd-cat -t myscript.sh

and it worked, stdout and stderr were directed to systemd's journal. Curiously,

~/scripts/myscript.sh &> | systemd-cat -t myscript.sh

didn't work in my Bash terminal.

I still need to find a way to do this inside my script for when other programs call my script.

I tried..

exec 2>&1 | systemd-cat -t myscript.sh

but it doesn't work.

Update 2:

From terminal

systemd-cat ~/scripts/myscript.sh

works. But I'm still looking for a way to do this from within the script.

deanresin
  • 1,466
  • 2
  • 16
  • 31
  • Which application generates these logs? A shell script or another user application? – Inian Jan 28 '19 at 03:07
  • from my personal shell scripts – deanresin Jan 28 '19 at 03:28
  • Is running it as `your-script.sh &> | systemd-cat -t myscript` not working? – Inian Jan 28 '19 at 03:30
  • hmmm. I didn't try that... – deanresin Jan 28 '19 at 03:33
  • It isn't working. `~/scripts/test.sh &> | systemd-cat -t test.sh bash: syntax error near unexpected token \`|'` – deanresin Jan 28 '19 at 03:36
  • 2
    Not sure where the error is from, may be instead of `&>`, could you try `~/scripts/test.sh 2>&1 | systemd-cat -t test.sh` – Inian Jan 28 '19 at 03:38
  • Yeah wow that worked. Forgot I wasn't using bash in the terminal. Thanks. Is there a way to do this inside the script? Because, for example, I have a torrent-done-script in Transmission and I'm not sure I can give it that command. I'll try though. – deanresin Jan 28 '19 at 03:50
  • `&> |` is not well-defined redirection syntax. (Some version of?) Bash 4 has `|&` for what you are apparently trying to say. I don't see why you'd want to use that instead of the portable and reasonably transparent `2>&1 |` though. – tripleee Jan 29 '19 at 07:12

3 Answers3

5

A pipe to systemd-cat is a process which needs to run concurrently with your script. Bash offers a facility for this, though it's not portable to POSIX sh.

exec > >(systemd-cat -t myscript -p emerg) 2>&1

The >(command) process substitution starts another process and returns a pseudo-filename (something like /dev/fd/63) which you can redirect into. This is basically a wrapper for the mkfifo hacks you could do if you wanted to port this to POSIX sh.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • 2
    You can use your script path as the tag: ```-t $(realpath "$0")``` You can set a different priority for your stderr: ```2> >(... -p err)``` Resulting into: ```exec > >(systemd-cat -t "$(realpath "$0")" -p info ) 2> >(systemd-cat -t "$(realpath "$0")" -p err )``` – jehon Jan 26 '20 at 20:05
1

If your script happens to not be a shell script, but some other programming language that allows loading extension modules linked to -lsystemd, there is another way. There is a library function sd_journal_stream_fd that quite precisely matches the task at hand. Calling it from bash itself (as opposed to some child) seems difficult at best. In Python for instance, it is available as systemd.journal.stream. What this function does in essence is connecting a unix domain stream socket and communicating what kind of data is being transmitted (e.g. priority). The difficult part with a shell here is making it connect a unix domain socket (as opposed to connecting in a child).

The key idea to this answer was given by Freenode/libera.chat user grawity.

Helmut Grohne
  • 6,578
  • 2
  • 31
  • 67
0

Apparently, and for reasons that are beyond me, you can't really redirect all stdout and stderr to journald from within a script because it has to be piped in. To work around that I found a trick people were using with syslog's logger which works similarly.

You can wrap all your code into a function and then pipe the function into systemd-cat.

#!/bin/bash

mycode(){
  echo "hello world"
  echor "echo typo producing error"
}
mycode | systemd-cat -t myscript.sh

exit 0

And then to search journal logs..

journalctl -t myscript.sh --since yesterday

I'm disappointed there isn't a more direct way of doing this.

deanresin
  • 1,466
  • 2
  • 16
  • 31