Jak sprawić, aby systemctl drukował w kolorze, gdy wchodzi w interakcję z non-tty?

19

Kiedy uruchamiam takie polecenie:

# systemctl status plexmediaserver

Dostaję ładnie kolorowe wydruki. Ale kiedy uruchomię następujące polecenie:

# watch -n300 --color systemctl status plexmediaserver

Czy jest jakiś sposób, aby wykonać to watchpolecenie z kolorem systemctl? Szukałem strony podręcznika, systemctlale nigdzie nie widzę odniesienia do koloru.

Cronburg
źródło
Zastanów się nad odpowiedzią towolfa, która jest znacznie lepsza niż obecnie akceptowana (twoja). Z góry dziękuję.
Piotr Dobrogost

Odpowiedzi:

17
watch -c  SYSTEMD_COLORS=1 systemctl status icinga2

man systemd mówi

   $SYSTEMD_COLORS
       Controls whether colorized output should be generated.

tzn. możesz wymusić za pomocą tego tryb koloru.

towolf
źródło
… I oczywiście do tej pory SYSTEMD_COLORSrobi więcej, niż sugeruje nazwa, ponieważ wprowadzono obsługę klikalnych linków w połowie 2018 r., Zaśmiecając dane wyjściowe niektórymi kodami specjalnymi i URL-ami adresów URL - które na szczęście można wyłączyćSYSTEMD_URLIFY=0
eMPee584,
23

systemctlwydaje się, że nie ma mechanizmu określania, kiedy należy pokolorować wydruk. Szybkim rozwiązaniem byłoby odsunięcie się, isatty(3)aby zawsze zwracać wartość true, dlatego podstępne systemctlmyślenie jest standardowe. Mianowicie możesz zrobić:

# 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

Na -xc -końcu gccpolecenia mówi, gccaby skompilować kod C ( -xc) z stdin ( -). Reszta flag informuje gcco utworzeniu udostępnionego pliku obiektu o nazwie isatty.so. Zauważ, że może to zepsuć inne programy, które polegają na isattyzwróceniu uzasadnionej wartości. Wydaje się jednak, że jest w porządku, systemctlponieważ isattywydaje się być używany wyłącznie w celu ustalenia, czy powinien pokolorować swój wynik.

Cronburg
źródło
To jest genialne. Zbudowałem skrypt do automatyzacji procesu .
Tom Hale,
1
Po przeczytaniu i głosowaniu odpowiedzi towolfa (która jest znacznie lepsza od tej), postanowiłem to zagłosować, ale jest to zbyt idealny hack, więc zamiast tego głosuję z nieco mieszanymi uczuciami :)
Piotr Dobrogost
2

W oparciu o odpowiedź @ KarlC , oto skrypt, który generuje, a następnie dołącza bibliotekę w czasie wykonywania:

#!/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
źródło
... co za hack 😅
eMPee584,