Comment puis-je faire en sorte que systemctl s'imprime en couleur lorsque j'interagis avec un non-tty?

19

Lorsque j'exécute une commande comme celle-ci:

# systemctl status plexmediaserver

J'obtiens une sortie joliment colorée. Mais lorsque j'exécute la commande suivante:

# watch -n300 --color systemctl status plexmediaserver

Existe-t-il un moyen de faire cette watchcommande avec la couleur de systemctl? J'ai regardé la page de manuel systemctlmais je ne vois aucune référence à la couleur nulle part.

Cronburg
la source
Veuillez envisager d'accepter la réponse de towolf qui est bien meilleure que celle actuellement acceptée (la vôtre). Merci d'avance.
Piotr Dobrogost

Réponses:

17
watch -c  SYSTEMD_COLORS=1 systemctl status icinga2

man systemd dit

   $SYSTEMD_COLORS
       Controls whether colorized output should be generated.

c'est-à-dire que vous pouvez forcer le mode couleur avec cela.

towolf
la source
... et bien sûr, fait maintenant SYSTEMD_COLORSplus que son nom ne le suggère, car la prise en charge des liens cliquables à la mi-2018 a été introduite, jonçant la sortie avec des codes d'échappement et des URL urlifiées - qui, heureusement, peuvent être désactivéesSYSTEMD_URLIFY=0
eMPee584
23

systemctlne semble pas avoir de mécanisme pour spécifier quand colorer la sortie. Une solution rapide serait de caler isatty(3)pour toujours retourner vrai, donc tromper systemctlen pensant que la sortie standard est interactive. À savoir, vous pourriez faire:

# 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

Le -xc -à la fin de la gcccommande indique gccde compiler le code C ( -xc) à partir de stdin ( -). Les autres indicateurs indiquent gccde créer un fichier d'objet partagé nommé isatty.so. Notez que cela pourrait très bien casser d'autres programmes qui comptent isattypour renvoyer une valeur légitime. Elle semble cependant convenir systemctlcar elle isattysemble être uniquement utilisée dans le but de déterminer si elle doit colorer sa sortie.

Cronburg
la source
C'est génial. J'ai construit un script pour automatiser le processus .
Tom Hale
1
Après avoir lu et voté la réponse de Towolf (qui est bien meilleure que celle-ci), j'allais voter contre, mais c'est un hack trop parfait, alors je vote plutôt avec des sentiments mitigés :)
Piotr Dobrogost
2

Basé sur la réponse de @ KarlC , voici un script qui génère puis inclut la bibliothèque au moment de l'exécution:

#!/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
la source
... quel hack 😅
eMPee584