29

When I run a command like this:

# systemctl status plexmediaserver

I get nicely colored output. But when I run the following command:

# watch -n300 --color systemctl status plexmediaserver

Is there any way I can do this watch command with color from systemctl? I've looked at the man page for systemctl but do not see reference to color anywhere.

cronburg
  • 696
  • 1
  • 7
  • 14
  • Please consider accepting towolf's [answer](https://superuser.com/a/1196178/664) which is much better than currently accepted one (yours). Thank you in advance. – Piotr Dobrogost Jun 19 '18 at 12:37

3 Answers3

34
watch -c  SYSTEMD_COLORS=1 systemctl status icinga2

man systemd says

   $SYSTEMD_COLORS
       Controls whether colorized output should be generated.

i.e., you can force color mode with that.

towolf
  • 456
  • 4
  • 2
  • … and of course, by now `SYSTEMD_COLORS` does more than the name suggests, because mid 2018 support for clickable links got introduced, littering output with some escape codes and urlified URLs – which fortunately can be turned off with `SYSTEMD_URLIFY=0` – eMPee584 Apr 20 '19 at 11:15
28

systemctl does not appear to have a mechanism for specifying when to color the output. A quick solution would be to shim isatty(3) to always return true, thus tricking systemctl into thinking stdout is interactive. Namely you could do:

# echo "int isatty(int fd) { return 1; }" | gcc -O2 -fpic -shared -ldl -o isatty.so -xc -
# LD_PRELOAD=./isatty.so watch -n300 --color systemctl status plexmediaserver

The -xc - at the end of the gcc command tells gcc to compile C code (-xc) from stdin (-). The rest of the flags tell gcc to create a shared object file named isatty.so. Note that this could very well break other programs which rely on isatty to return a legitimate value. It however appears to be fine for systemctl as isatty appears to be solely used for the purpose of determining if it should color its output.

cronburg
  • 696
  • 1
  • 7
  • 14
  • This is brilliant. I built a [script to automate the process](https://superuser.com/a/1245671/365890). – Tom Hale Aug 30 '17 at 06:08
  • 1
    After I read and voted towolf's answer (which is much better than this one) up I was going to downvote this but this is too perfect a hack so instead I'm voting this up with somehow mixed feelings :) – Piotr Dobrogost Jun 19 '18 at 12:35
  • You genius, it works with the clang-tidy color output issue with cmake, brilliant!!! – Sunding Wei Dec 02 '20 at 04:46
5

Based on @KarlC's answer, here is a script which generates and then includes the library at runtime:

#!/bin/bash
set -euo pipefail

function clean_up {
  trap - EXIT # Restore default handler to avoid recursion
  [[ -e "${isatty_so:-}" ]] && rm "$isatty_so"
}
# shellcheck disable=2154 ## err is referenced but not assigned
trap 'err=$?; clean_up; exit $err' EXIT HUP INT TERM

isatty_so=$(mktemp --tmpdir "$(basename "$0")".XXXXX.isatty.so)
echo "int isatty(int fd) { return 1; }" \
  | gcc -O2 -fpic -shared -ldl -o "$isatty_so" -xc -
# Allow user to SH=/bin/zsh faketty mycommand
"${SH:-$SHELL}" -c 'eval $@' - LD_PRELOAD="$isatty_so" "$@"
Tom Hale
  • 2,274
  • 2
  • 24
  • 35