web-dev-qa-db-ja.com

tty以外から操作されたときにsystemctlをカラーで印刷するにはどうすればよいですか?

次のようなコマンドを実行すると:

# systemctl status plexmediaserver

きれいな色の出力が得られます。しかし、次のコマンドを実行すると:

# watch -n300 --color systemctl status plexmediaserver

watchの色を使用してsystemctlコマンドを実行する方法はありますか?私はsystemctlのmanページを見ましたが、どこにもcolorへの参照がありません。

19
cronburg
watch -c  SYSTEMD_COLORS=1 systemctl status icinga2

man systemd言います

   $SYSTEMD_COLORS
       Controls whether colorized output should be generated.

つまり、これでカラーモードを強制できます。

17
towolf

systemctlには、出力に色を付けるタイミングを指定するメカニズムがないようです。迅速な解決策は、常にtrueを返すようにisatty(3)をシムすることです。したがって、systemctlをだましてstdoutがインタラクティブであると考えます。つまり、次のことができます。

# 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

gccコマンドの最後の-xc -は、gccにstdin(-xc)からCコード(-)をコンパイルするように指示します。残りのフラグは、gccisatty.soという名前の共有オブジェクトファイルを作成するように指示します。これは、正当な値を返すためにisattyに依存する他のプログラムを非常にうまく壊す可能性があることに注意してください。ただし、systemctlは、出力に色を付ける必要があるかどうかを判断する目的でのみ使用されるため、isattyには問題がないようです。

23
cronburg

@ KarlCの回答 に基づいて、実行時にライブラリを生成してインクルードするスクリプトを次に示します。

#!/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" "$@"
2
Tom Hale