¿Cómo hago para que systemctl imprima en color cuando interactúo con un no-tty?

19

Cuando ejecuto un comando como este:

# systemctl status plexmediaserver

Obtengo una salida bien coloreada. Pero cuando ejecuto el siguiente comando:

# watch -n300 --color systemctl status plexmediaserver

¿Hay alguna forma de hacer este watchcomando con color systemctl? He buscado la página de manual systemctlpero no veo ninguna referencia al color en ninguna parte.

cronburg
fuente
Considere aceptar la respuesta de Towolf, que es mucho mejor que la respuesta actualmente aceptada (la suya). Gracias de antemano.
Piotr Dobrogost

Respuestas:

17
watch -c  SYSTEMD_COLORS=1 systemctl status icinga2

man systemd dice

   $SYSTEMD_COLORS
       Controls whether colorized output should be generated.

es decir, puede forzar el modo de color con eso.

Towolf
fuente
... y, por supuesto, por ahora SYSTEMD_COLORShace algo más que el nombre sugiere, debido a mediados 2.018 soporte para hacer clic en enlaces consiguió introdujo, salida de basura con algunos códigos de escape y URLs urlified - que, afortunadamente, se puede apagar conSYSTEMD_URLIFY=0
eMPee584
23

systemctlno parece tener un mecanismo para especificar cuándo colorear la salida. Una solución rápida sería calzar isatty(3)para volver siempre verdadero, por lo que engañar systemctla pensar que stdout es interactivo. A saber, podrías hacer:

# 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

Al -xc -final del gcccomando le dice gccque compile el código C ( -xc) a partir de stdin ( -). El resto de las banderas le indican gccque cree un archivo de objeto compartido llamado isatty.so. Tenga en cuenta que esto podría muy bien romper otros programas que dependen isattypara devolver un valor legítimo. Sin embargo, parece estar bien, systemctlya que isattyparece ser utilizado únicamente con el fin de determinar si debe colorear su salida.

cronburg
fuente
Esto es brillante. Creé un script para automatizar el proceso .
Tom Hale
1
Después de leer y votar la respuesta de Towolf (que es mucho mejor que esta), iba a rechazar esto, pero este es un truco demasiado perfecto, así que en lugar de votarlo con sentimientos encontrados :)
Piotr Dobrogost
2

Basado en la respuesta de @ KarlC , aquí hay un script que genera y luego incluye la biblioteca en tiempo de ejecución:

#!/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
fuente
... qué truco 😅
eMPee584