Bug 1218106

Summary: Yast2 module to read systemd journal files crashes
Product: [openSUSE] openSUSE Tumbleweed Reporter: Frank McCormick <mccfrank>
Component: YaST2Assignee: E-mail List <yast2-maintainers>
Status: RESOLVED FIXED QA Contact: Jiri Srain <jsrain>
Severity: Normal    
Priority: P5 - None CC: ancor, mccfrank, mkoutny, systemd-maintainers
Version: Current   
Target Milestone: ---   
Hardware: x86-64   
OS: Other   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Attachments: The log which the module suggested be saved
y2log

Description Frank McCormick 2023-12-15 13:34:53 UTC
Created attachment 871390 [details]
The log which the module suggested be saved

The yast2 module for reading journal log files crashes with a ruby error.
It first says there are no dmesg logs, would I like to read journal files? Say yes and the module crashes.

This is the output:

Internal error. Please report a bug report with logs.
Run save_y2logs to get complete logs.

Caller: /usr/lib64/ruby/3.2.0/json/common.rb:216:in `parse'

Details: unexpected token at '{"[0;32mCONFIG_FILE[0m":"[0;32m/etc/xdg/autostart/user-dirs-update-mate.desktop[0m","[0;32m__SEQNUM[0m":"[0;32m7868730[0m","[0;32m_SYSTEMD_USER_SLICE[0m":"[0;32m-.slice[0m","[0;32m_PID[0m":"[0;32m3079[0m","[0;32m_SYSTEMD_SLICE[0m":"[0;32muser-1000.slice[0m","[0;32m_BOOT_ID[0m":"[0;32m8fab655c7f094316bfa0d4a19058768e[0m","[0;32m_CMDLINE[0m":"[0;32m/usr/lib/systemd/user-generators/systemd-xdg-autostart-generator /run/user/1000/systemd/generator /run/user/1000/systemd/generator.early /run/user/1000/systemd/generator.late[0m","[0;32mSYSLOG_IDENTIFIER[0m":"[0;32msystemd-xdg-autostart-generator[0m","[0;32mCODE_LINE[0m":"[0;32m238[0m","[0;32mMESSAGE[0m":"[0;32m/etc/xdg/autostart/user-dirs-update-mate.desktop:10: Key OnlyShowIn was already defined, ignoring.[0m","[0;32m_UID[0m":"[0;32m1000[0m","[0;32mTID[0m":"[0;32m3079[0m","[0;32m_EXE[0m":"[0;32m/usr/lib/systemd/user-generators/systemd-xdg-autostart-generator[0m","[0;32m_SYSTEMD_OWNER_UID[0m":"[0;32m1000[0m","[0;32m_RUNTIME_SCOPE[0m":"[0;32msystem[0m","[0;32m_AUDIT_SESSION[0m":"[0;32m2[0m","[0;32m_SYSTEMD_CGROUP[0m":"[0;32m/user.slice/user-1000.slice/user@1000.service/init.scope[0m","[0;32m__MONOTONIC_TIMESTAMP[0m":"[0;32m14948127[0m","[0;32m_SELINUX_CONTEXT[0m":"[0;32munconfined\n[0m","[0;32m_TRANSPORT[0m":"[0;32mjournal[0m","[0;32mCONFIG_LINE[0m":"[0;32m10[0m","[0;32mSYSLOG_FACILITY[0m":"[0;32m3[0m","[0;32mMESSAGE_ID[0m":"[0;32mc772d24e9a884cbeb9ea12625c306c01[0m","[0;32m_MACHINE_ID[0m":"[0;32m75aded7cca164d439bbdbeb3bacc4e28[0m","[0;32m_HOSTNAME[0m":"[0;32mdesktop-tumbleweed[0m","[0;32m_GID[0m":"[0;32m1000[0m","[0;32m__SEQNUM_ID[0m":"[0;32m29100c9518e84cd4a76a6c9bfa30017e[0m","[0;32m_COMM[0m":"[0;32msystemd-xdg-aut[0m","[0;32mCODE_FUNC[0m":"[0;32mxdg_config_parse_strv[0m","[0;32mCODE_FILE[0m":"[0;32msrc/xdg-autostart-generator/xdg-autostart-service.c[0m","[0;32m_SYSTEMD_UNIT[0m":"[0;32muser@1000.service[0m","[0;32m_SYSTEMD_USER_UNIT[0m":"[0;32minit.scope[0m","[0;32m_SOURCE_REALTIME_TIMESTAMP[0m":"[0;32m1702564544969485[0m","[0;32m_CAP_EFFECTIVE[0m":"[0;32m0[0m","[0;32m_AUDIT_LOGINUID[0m":"[0;32m1000[0m","[0;32mPRIORITY[0m":"[0;32m4[0m","[0;32m__CURSOR[0m":"[0;32ms=29100c9518e84cd4a76a6c9bfa30017e;i=78113a;b=8fab655c7f094316bfa0d4a19058768e;m=e4171f;t=60c7932e8fb1e;x=b5e073a5269cfd74[0m","[0;32m__REALTIME_TIMESTAMP[0m":"[0;32m1702564544969502[0m"}
'
Comment 2 Frank McCormick 2023-12-15 16:39:51 UTC
Created attachment 871394 [details]
y2log

Latest y2log
Comment 3 Ancor Gonzalez Sosa 2023-12-18 09:02:33 UTC
YaST calls something like this to get the journal entries from systemd:

> LANG=C /usr/bin/journalctl --output json --no-page

According to the attached logs, looks like systemd has decided to season that JSON output with TTY color control characters. Unsurprisingly JSON parsers don't like that.

I guess something have changed in systemd in that regard, since in the past when asked to return JSON it used to return... well... valid JSON.

We can likely put that under control from the YaST side by enforcing then environment variables SYSTEMD_LOG_COLOR and/or SYSTEMD_COLORS.

That being said, I would consider this to be a systemd misbehavior (or, at least, an unexpected change).
Comment 4 Lukas Ocilka 2023-12-18 09:51:31 UTC
(In reply to Ancor Gonzalez Sosa from comment #3)
> I guess something have changed in systemd in that regard, since in the past
> when asked to return JSON it used to return... well... valid JSON.

Let's then ask systemd maintainers ^^^
Comment 5 Ancor Gonzalez Sosa 2023-12-18 10:00:58 UTC
It doesn't happen in my system. But I was able to force the error adding this to the journalctl call (which is exactly the opposite we actually wanna do, of course):

> SYSTEMD_LOG_COLOR=1 SYSTEMD_COLORS=256 LANG=C /usr/bin/journalctl [...]

So I guess forcing those variables to zero/false would actually fix the problem for this user (and others potentially facing the same).
Comment 6 Ancor Gonzalez Sosa 2023-12-18 10:42:21 UTC
BTW, I also found we could improve this regular expression[1] since I detected a case in which the output of journalctl doesn't fit what we expect.

It's more robust like this:

> /^\s*(-*\d+)\s+(\w+)\s+(#{TIMESTAMP_RX})[— ]+(#{TIMESTAMP_RX})$/

It's almost equal to the current one. Just note the extra plus sign before the second timestamp.

[1] https://github.com/yast/yast-journal/blob/dee50dacb1b9100865f4d096f0a99d668ee1a877/src/lib/y2journal/query.rb#L102
Comment 7 Michal Koutný 2023-12-18 14:16:07 UTC
(In reply to Ancor Gonzalez Sosa from comment #5)
> But I was able to force the error adding
> this to the journalctl call (which is exactly the opposite we actually wanna
> do, of course):

What systemd version do you have?

Interestingly, I can see the colored output regardless of SYSTEMD_LOG_COLOR={0,1} with
> SYSTEMD_LOG_COLOR=0 SYSTEMD_COLORS=256 LANG=C journalctl -ojson
both with
> systemd-254.5-6.1.x86_64
or
> systemd-249.16-150400.8.35.5.x86_64
.
Comment 8 Ancor Gonzalez Sosa 2023-12-18 14:48:19 UTC
(In reply to Michal Koutný from comment #7)
> 
> What systemd version do you have?

I have systemd 254.5.

I did more experiments and SYSTEMD_LOG_COLOR seems to be irrelevant for this.

Running this I get monochrome output in my tty

> SYSTEMD_COLORS=0 LANG=C /usr/bin/journalctl --output json

Running either of these in my tty I get colored JSON:

> SYSTEMD_COLORS=1 LANG=C /usr/bin/journalctl --output json
>
> LANG=C /usr/bin/journalctl --output json

In any case, I didn't expect YaST to need to force any of those variables, since those color codes should only be inserted if systemd is printing to the tty, which is not the case in YaST (we are executing the command and parsing the output).
Comment 9 Ancor Gonzalez Sosa 2023-12-18 14:49:47 UTC
(In reply to Ancor Gonzalez Sosa from comment #8)
> 
> I have systemd 254.5.

To be precise, 254.5-5.1
Comment 10 Stefan Hundhammer 2024-01-03 14:50:57 UTC
I can confirm that the 'dmesg' output of TW from 2023-12-25 is *very* colorful, but only when I view it in a terminal window.

When I redirect its output to a file, there are no escape sequences.
Comment 11 Stefan Hundhammer 2024-01-03 15:14:49 UTC
Even with all latest TW updates, I don't get escape sequences when I redirect the output of 'journalctl' or 'dmesg' to a file. In a terminal, yes, there is some color, but never in a file.

% journalctl --version 
systemd 254 (254.5+suse.21.g071ac409a0)
+PAM +AUDIT +SELINUX +APPARMOR +IMA -SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK -XKBCOMMON -UTMP +SYSVINIT default-hierarchy=unified

% dmesg --version
dmesg from util-linux 2.39.3
Comment 12 Stefan Hundhammer 2024-01-03 17:09:48 UTC
I can understand the ratioale for color output to a tty, but why in the JSON format, too? The purpose of JSON is to be machine-readable, and escape sequences pretty much defeat that.
Comment 13 Michal Koutný 2024-01-04 10:34:45 UTC
(In reply to Ancor Gonzalez Sosa from comment #8)
> I did more experiments and SYSTEMD_LOG_COLOR seems to be irrelevant for this.

Right. (It's a gotcha since it applies to log-level coloring, not JSON coloring.)

> which is not the case in YaST (we are executing the command and
> parsing the output).

I was previously focused on the env variables but the coloring based on tty/nontty output works for me. (Curiously, I don't see any recent changes in this area.)

systemd-249.16-150400.8.35.5.x86_64
systemd-254.5-8.1.x86_64


(In reply to Stefan Hundhammer from comment #12)
> The purpose of JSON is to be machine-readable, and escape
> sequences pretty much defeat that.

The reading machine parses a pipe or a saved file and those should be without color escapes. (The logic [1] should boil down to isatty(3).)

Is it possible that something adds SYSTEMD_COLORS > 0 to the environment?
(The variable seems to override tty detection.)


[1] https://github.com/openSUSE/systemd/blob/071ac409a0564863657d8f8a5a35e6a4f914695f/src/basic/terminal-util.c#L1336
Comment 14 Stefan Hundhammer 2024-01-04 13:08:57 UTC
I found an easy way to reproduce this, even on Leap 15.5:

  xhost +

  sudo SYSTEMD_COLORS=256 yast2 journal

-> the observed crash


  SYSTEMD_COLORS=256 journalctl --output json

-> colored output

  SYSTEMD_COLORS=256 journalctl --output json >/tmp/x

-> escape sequences in the file

It's the same with or without 'sudo', with 'bash' or with 'zsh' which is my standard.

AFAICS the tty detection fails with '--output json'.
Comment 15 Michal Koutný 2024-01-04 13:20:54 UTC
(In reply to Stefan Hundhammer from comment #14)
> AFAICS the tty detection fails with '--output json'.

The code comment under link in comment 13 suggests that SYSTEMD_COLORS > 0 is
meant to override tty detection. Even journalctl(1) says:

> This can be specified to override the automatic decision based on $TERM and
> what the console is connected to.

I don't know why such a twisted logic but it's documented ¯\_(ツ)_/¯                                                                                                                                                                                                                                                                        

Thus, could have something changed in yast2 invocations that would leak the SYSTEMD_COLORS into the environment?
Comment 16 Stefan Hundhammer 2024-01-04 13:27:11 UTC
That code is unchanged since 6 years:

https://github.com/yast/yast-journal/blob/master/src/lib/y2journal/journalctl.rb#L62
Comment 17 Michal Koutný 2024-01-04 13:40:00 UTC
I guess that `Yast::SCR.Execute(BASH_SCR_PATH, command)` retains environment.

Frank, do you tweak SYSTEMD_COLORS in your environment?
Comment 18 Stefan Hundhammer 2024-01-04 13:49:42 UTC
Simple solution:

  https://github.com/yast/yast-journal/pull/52
Comment 19 Stefan Hundhammer 2024-01-04 13:51:13 UTC
Normally, YaST modules are called as root. But this is one of the few that can actually also be run as a normal user; and when that user account has environment variables set, they may actually arrive in the YaST calling environment.

But whatever, the fix is easy enough - see comment #18.
Comment 20 Frank McCormick 2024-01-04 13:51:48 UTC
Not as far as I know. 

this is from root xterm (yast runs as root)

desktop-tumbleweed root /home/frank> echo $SYSTEMD_COLORS

desktop-tumbleweed root /home/frank> 


What else should I check ?
Comment 21 Stefan Hundhammer 2024-01-04 13:57:04 UTC
The fix will arrive in Factory / Tumbleweed as yast2-journal-5.0.1.
Comment 22 Stefan Hundhammer 2024-01-04 14:09:27 UTC
Frank, if you want to test / have this fix immediately, simply download this file

https://raw.githubusercontent.com/yast/yast-journal/d9d29dc3e709eab54dc2fb17e1f7530e82008742/src/lib/y2journal/journalctl.rb

and copy it to 

  /usr/share/YaST2/lib/y2journal/journalctl.rb
Comment 23 Frank McCormick 2024-01-04 14:16:54 UTC
At the same time I put SYSTEMD_COLORS='' export SYSTEMD_COLORS
into my .bashrc, and ran the YAST module for the journal and there was not
any crash, it displayed perfectly.

As to where the variable was coming from I have absolutely no idea.
Comment 24 Frank McCormick 2024-01-04 14:19:05 UTC
Thank you for this !
Comment 25 Stefan Hundhammer 2024-01-04 14:27:14 UTC
Environment variables can come from the weirdest of places; your ~/.bashrc, your ~/.profile, their global counterparts from /etc or /usr/etc or other global files like /etc/environment (or today probably /usr/etc/environment).

I've seen login managers overriding my LANG / LC_xxx variables with stuff selected on the login manager page, then written (without telling or asking me) to a file that I had never seen or heard of before (but what do I know, I've only worked in Linux/Unix environments since 1990) ~/.pam-environment .

People come up with the weirdest of places where they can sabotage normal users with new environment variables overriding their explicit wishes, and then they blame those users for never having read a brand-new documentation or man page in some obscure place.  ;-}
Comment 26 Stefan Hundhammer 2024-01-04 14:54:42 UTC
Merged https://github.com/yast/yast-journal/pull/52.