You are not logged in.

#1 2020-01-15 18:54:15

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,047

[Solved]AWK, lose pipe

This function prints which services have failed.

The function

sf() {
  nofail=$( systemctl --failed | awk 'NR==1{print $1}')
  [ "$nofail" = 0 ] || systemctl --failed | awk '/\●/{printf "%s ",$2}'
}

Say the next services are failing 'logrotate.service mpd.service mpd1.service systemd-timesyncd.service' and I only want to mask
'logrotate.service and mpd.service I would use:

systemctl --failed | awk "!/logrotate|mpd.service/" | awk '/\●/{printf "%s ",$2}'

and the output will be 'mpd1.service systemd-timesyncd.service'

Is it possible to do do that with one awk, instead of piped to a new one?

Last edited by qinohe (2020-01-15 21:00:05)

Offline

#2 2020-01-15 19:43:21

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 24,222
Website

Re: [Solved]AWK, lose pipe

Do you mean can it be done with one awk instead of three awks with one in a subshell, and two others in a pipe behind a conditional?  Then the answer is still yes.

systemctl --failed | awk '
   NR==1 && $1 == "0" { exit; }
   !/logrotate|mpd.service/ && /\●/ { printf "%s ", $2; }
'

Although this also higlights that there is no reason to even have the conditional at all.  It does nothing as the only way it would pass is if there is nothing that would match other rules anyways:

systemctl --failed | awk '!/logrotate|mpd.service/ && /\●/ { printf "%s ", $2; }'

Last edited by Trilby (2020-01-15 19:48:13)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#3 2020-01-15 20:19:54

eschwartz
Trusted User/Bug Wrangler
Registered: 2014-08-08
Posts: 3,616

Re: [Solved]AWK, lose pipe

$ systemctl --failed | awk 'NR==1{print $1}'
UNIT
$ systemctl --failed | awk 'NR==1{print $0}'
  UNIT           LOAD   ACTIVE SUB    DESCRIPTION                                 
$ systemctl --failed --no-legend | awk 'NR==1{print $1}'
shadow.service
$ systemctl --failed --no-legend | awk 'NR==1{print $0}'
shadow.service loaded failed failed Verify integrity of password and group files

Why are you doing heuristic parsing of the systemctl legend, and why are you then filtering out actual units from the legend by doing line matches on the unicode character Black Circle (U+25CF)? systemctl has an option to give you machine-readable output -- use that option.


Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

#4 2020-01-15 20:29:15

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 24,222
Website

Re: [Solved]AWK, lose pipe

He's not intending to parse the legend.  It's just a half-baked but effective way to check if any services failed.  If not services failed, the command would indeed return "0" as the first line would also be the last line, and it would report "0 units listed" or similar (I don't have any failed units to confirm with that flag).  The important thing is that this check doesn't even do anything.  Check if it's zero or not zero ... then do the same thing in either case.  So there's no point in checking in the first place.

As for the black circle - I don't even have that in any of my output - so I wasn't sure where that came from, I just worked with what was already there.

Out of curiosity, what flag provides machine-readable output?  The only mention of that in the man page is specific for the `show` command which is a machine-readable form of `status`, but that's not what would be wanted here.

Last edited by Trilby (2020-01-15 20:32:36)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#5 2020-01-15 20:40:33

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,047

Re: [Solved]AWK, lose pipe

Output from my Debian server, where I have intensionally let some services 'crash':

systemctl --failed
  UNIT              LOAD   ACTIVE SUB    DESCRIPTION                          
● logrotate.service loaded failed failed Rotate log files                     
● mpd1.service      loaded failed failed Music Player Daemon                  

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

2 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.

Thank you so much guys, @Trilby for helping me understand how to wrap things up with AWK. You nailed it it, I use this on my tmux bar BTW.
@ eschwartz for showing me I need to read the man (in this case 'systemctl') more thoroughly
Thank you both,

Offline

#6 2020-01-15 20:47:59

eschwartz
Trusted User/Bug Wrangler
Registered: 2014-08-08
Posts: 3,616

Re: [Solved]AWK, lose pipe

Trilby wrote:

He's not intending to parse the legend.  It's just a half-baked but effective way to check if any services failed.

... by parsing the legend to see if it begins with "0" or "UNIT".

If not services failed, the command would indeed return "0" as the first line would also be the last line, and it would report "0 units listed" or similar (I don't have any failed units to confirm with that flag).  The important thing is that this check doesn't even do anything.  Check if it's zero or not zero ... then do the same thing in either case.  So there's no point in checking in the first place.

That is true, but by correctly modeling it as a series of no-legend lines listing each failed unit (or no output, if there are no failed units), it is much easier to come to the correct conclusion "how do I check if certain units failed".

As for the black circle - I don't even have that in any of my output - so I wasn't sure where that came from, I just worked with what was already there.

The full output with legend and all is this:

$ systemctl --failed --no-pager
  UNIT           LOAD   ACTIVE SUB    DESCRIPTION                                 
● shadow.service loaded failed failed Verify integrity of password and group files

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

1 loaded units listed.

Out of curiosity, what flag provides machine-readable output?  The only mention of that in the man page is specific for the `show` command which is a machine-readable form of `status`, but that's not what would be wanted here.

The --no-legend flag removes all output other than the one-line-per-failed-unit output (and no unicode list bullets). Which may not be explicitly --machinereadable but it seems like a much more stable, controlled output format, which I figure is the same thing.

Last edited by eschwartz (2020-01-15 20:49:12)


Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

#7 2020-01-15 20:53:26

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 24,222
Website

Re: [Solved]AWK, lose pipe

In that case, the end result would just be

systemctl --failed --no-legend | awk '!/logrotate|mpd.service/ { print $1; }'
#or
systemctl --failed --no-legend | sed '/logrotate/d;mpd.service/d;s/ .*//'

"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#8 2020-01-15 20:56:12

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,047

Re: [Solved]AWK, lose pipe

wink @Trilby, Yes that's what I have right now.

edit; I don't mind I you keep discussing here, but I'm marking solved;)

Last edited by qinohe (2020-01-15 20:59:45)

Offline

#9 2020-01-15 21:26:20

qinohe
Member
From: Netherlands
Registered: 2012-06-20
Posts: 1,047

Re: [Solved]AWK, lose pipe

Just as an addition if you want to use it on a bar like tmux you need something like:

systemctl --failed --no-legend | awk '!/logrotate|mpd.service/ { printf "%s ". $1; }'

It won't print the CR..

Offline

Board footer

Powered by FluxBB