この記事では、Linuxの
tput コマンドを使ったカラー出力ライブラリの設計方法を解説します。ANSI 直書きより可搬性が高く、非対話環境でも安全に動くフォールバック設計まで、RHEL 9.4 / Ubuntu 24.04 LTS で動作確認した実装パターンを一通り紹介します。この記事のポイント
・ tput は terminfo を参照して端末種別ごとに適切なエスケープコードを生成する
・ カラー変数をスクリプト冒頭に宣言し、log_error 等の関数に集約して再利用する
・ [ -t 1 ] と tput colors で非対話環境を検出し、色変数を空文字にしてクリーンな出力を保つ
・ trap で EXIT 時に必ずリセットシーケンスを送り、プロンプト着色を防ぐ
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ ANSI 直書きを避けて tput を使うのか
ANSI エスケープコード(\e[31m 等)を直書きすると、次の2つの問題が発生することがあります。・ ターミナル非対応環境での文字化け:一部のシリアルコンソールや最小インストールコンテナではANSIシーケンスが解釈されず、制御文字がそのままテキスト表示される
・ 非対話実行時の汚染:cron・パイプ・ファイルリダイレクト経由で実行したとき、エスケープコードがそのまま出力に混入し、grep によるログ解析を妨げる
tput コマンドは terminfo(端末能力データベース)を参照して、$TERM 変数に応じた正しいエスケープシーケンスを返します。スクリプト側でエスケープコードをハードコードする必要がなくなり、ターミナル種別の違いをシステムに吸収させられます。# ANSI コードの直書き(非推奨) echo -e "\e[31mERROR: ディスク容量不足\e[0m" # tput を使った書き方(推奨) RED=$(tput setaf 1) RESET=$(tput sgr0) echo "${RED}ERROR: ディスク容量不足${RESET}"
tput コマンドの基本|色番号・スタイル・リセットの仕組み
1. 利用可能色数の確認と setaf による文字色指定
まず、ターミナルが何色に対応しているかを確認します。$ tput colors 256
文字色を指定する
tput setaf N の色番号(標準 8 色)は以下の通りです。・ 0:黒(Black)
・ 1:赤(Red)— エラー表示に使う
・ 2:緑(Green)— 成功表示に使う
・ 3:黄(Yellow)— 警告表示に使う
・ 4:青(Blue)
・ 5:マゼンタ(Magenta)
・ 6:シアン(Cyan)— 情報表示に使う
・ 7:白(White)
背景色を変えたい場合は
tput setab N を使います。256 色対応端末では色番号 0 から 255 の範囲が利用できます。2. 太字・下線などのテキストスタイル
色以外に以下のスタイルが指定できます。・ tput bold:太字
・ tput dim:薄いテキスト(暗い)
・ tput smul / tput rmul:下線開始 / 下線終了
・ tput rev:反転表示(前景と背景の色を入れ替える)
# 組み合わせ例(黄色の太字) echo "$(tput setaf 3)$(tput bold)WARNING: 重要な警告$(tput sgr0)" echo "$(tput smul)アンダーラインテキスト$(tput rmul)"
3. sgr0 でリセットする
色やスタイルを適用した後は必ずtput sgr0 でリセットします。リセットを忘れると、以降のすべての出力が同じ色・スタイルで表示され続けます。tput sgr0 はすべての属性(色・太字・下線・反転等)を一括でリセットする命令です。\e[0m と同等ですが、端末種別に依存しないため運用環境を問わず安全に使えます。カラー出力ライブラリの設計|log_error・log_success 関数を作る
1. カラー変数を宣言する
スクリプトの先頭でカラー変数を宣言しておくと、関数内で何度でも再利用できます。関数のたびにtput setaf を呼ぶと実行コストがかかるため、変数化しておくのが実務上の基本パターンです。# カラー変数(スクリプト冒頭で宣言) RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) CYAN=$(tput setaf 6) BOLD=$(tput bold) RESET=$(tput sgr0)
2. ログレベル別の出力関数を定義する
カラー変数を使ったログ関数を定義することで、本体ロジックではlog_error "メッセージ" と書くだけになり、色の制御が本体ロジックから分離されます。log_info() { echo "${CYAN}[INFO]${RESET} $*"; } log_ok() { echo "${GREEN}[OK]${RESET} $*"; } log_warn() { echo "${YELLOW}[WARN]${RESET} $*" >&2; } log_error() { echo "${RED}${BOLD}[ERROR]${RESET} $*" >&2; }
>&2)に送ることで、ログファイルとエラーストリームを分けて扱えます。実機(RHEL 9.4)でのターミナル実行例:
$ log_info "バックアップ開始: /var/www/html" [INFO] バックアップ開始: /var/www/html $ log_ok "完了: /backup/html_20261012.tar.gz" [OK] 完了: /backup/html_20261012.tar.gz $ log_warn "/backup の使用率が 85% を超えています" [WARN] /backup の使用率が 85% を超えています $ log_error "rsync が終了コード 23 で失敗しました" [ERROR] rsync が終了コード 23 で失敗しました
カラー出力設計を含む実践的なシェルスクリプト技術については、シェルスクリプト実践ガイドでも詳しく解説しています。
非対話環境でのフォールバック設計|cron やパイプで色コードが混入しないようにする
ここが tput を使ったカラー出力設計の核心です。cron 実行時やパイプ先に渡す出力では、色コードがテキストとして混入します。これを防ぐフォールバック設計を組み込みます。1. [ -t 1 ] で端末かどうかを判定する
Bash の[ -t N ] テストは、ファイルディスクリプタ N が端末(TTY)に接続されているかを判定します。・ -t 0:標準入力が端末に接続されているか
・ -t 1:標準出力が端末に接続されているか
・ -t 2:標準エラー出力が端末に接続されているか
# 標準出力が端末かどうかを判定 if [ -t 1 ]; then echo "対話ターミナルで実行中" else echo "パイプまたはリダイレクト中(cron を含む)" fi
[ -t 1 ] は偽になります。2. TERM 環境変数と tput colors によるチェック
$TERM が未設定または "dumb" の場合、tput が正しく動作しません。より確実な方法として、tput colors の終了コードで判定します。# tput が使用可能かチェック(終了コード 0 かつ色数が 8 以上か) if tput colors 2>/dev/null && [ "$(tput colors)" -ge 8 ]; then echo "カラー出力を有効化" else echo "カラーなしで実行" fi
3. ライブラリへのフォールバック組み込み
端末判定に応じてカラー変数を空にするフォールバック付きのライブラリ全体を以下に示します。color_lib.sh として保存し、他のスクリプトから source して使います。#!/bin/bash # color_lib.sh - tput カラー出力ライブラリ(フォールバック対応版) # 対話ターミナルかつ tput が使えるときだけカラーを有効化 if [ -t 1 ] && tput colors 2>/dev/null && [ "$(tput colors)" -ge 8 ]; then RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) CYAN=$(tput setaf 6) BOLD=$(tput bold) RESET=$(tput sgr0) else # 非対話環境ではすべて空文字にしてクリーンな出力を維持 RED="" GREEN="" YELLOW="" CYAN="" BOLD="" RESET="" fi log_info() { echo "${CYAN}[INFO]${RESET} $*"; } log_ok() { echo "${GREEN}[OK]${RESET} $*"; } log_warn() { echo "${YELLOW}[WARN]${RESET} $*" >&2; } log_error() { echo "${RED}${BOLD}[ERROR]${RESET} $*" >&2; }
log_error 等の関数自体はコードを変更しなくてもよいため、ライブラリを読み込む側のスクリプトは環境に関係なく同一コードを使い回せます。注意:POSIX シェル(/bin/sh)で使う場合は
2>/dev/null を明示してください(bash 拡張の &> は使えません)。実践:バックアップスクリプトへの組み込み
color_lib.sh を実際のバックアップスクリプトに組み込む例を示します。#!/bin/bash set -euo pipefail # カラーライブラリを読み込む source /usr/local/lib/color_lib.sh # EXIT 時に必ずリセットシーケンスを送る(プロンプト着色の防止) trap 'printf "%s" "${RESET}"' EXIT BACKUP_SRC="/var/www/html" BACKUP_DEST="/backup" TIMESTAMP=$(date +%Y%m%d_%H%M%S) OUTFILE="${BACKUP_DEST}/html_${TIMESTAMP}.tar.gz" log_info "バックアップ開始: ${BACKUP_SRC}" if tar -czf "${OUTFILE}" "${BACKUP_SRC}" 2>/dev/null; then SIZE=$(du -sh "${OUTFILE}" | cut -f1) log_ok "完了: ${OUTFILE} (${SIZE})" else log_error "tar が失敗しました(終了コード: $?)" exit 1 fi
cron 実行ログの出力例(/var/log/backup.log より抜粋・RHEL 9.4 実機確認):
# /var/log/backup.log(cron 実行・色コードなし) [INFO] バックアップ開始: /var/www/html [OK] 完了: /backup/html_20261012_020001.tar.gz (124M)
set -euo pipefail と組み合わせることで、tar が途中で失敗した場合も log_error が確実に呼ばれ、問題箇所を素早く特定できます。トラブルシュート|色が出ない・tput エラーのよくある原因と対処
「tput: No value for $TERM and no -T specified」が出る
$TERM 変数が設定されていない環境(Docker 最小イメージ・SSH 直接コマンド実行等)で発生します。・ 対処 1:環境変数を明示する
export TERM=xterm-256color
-T オプションでターミナル種別を直接指定するRED=$(tput -T xterm-256color setaf 1)
256 色を指定したのに 8 色しか表示されない
端末が 256 色対応でも$TERM が xterm(256 なし)になっていると 8 色のみになります。# 確認 echo $TERM # xterm-256color になっているか tput colors # 256 が表示されれば OK # 修正 export TERM=xterm-256color
スクリプト終了後もシェルプロンプトが着色されたまま
スクリプト内でtput sgr0(または $RESET)を出力せずに終了すると発生します。実務では trap を使って確実にリセットするのが鉄則です。# スクリプト冒頭に追加しておくと終了時に必ずリセットされる trap 'printf "%s" "${RESET}"' EXIT
printf "%s" を使うのは、echo の一部の実装が改行を付け足すためです。本記事のまとめ
tput を使ったカラー出力ライブラリの設計ポイントをまとめます。| 設計ポイント | 内容 |
|---|---|
| カラー変数 | RED=$(tput setaf 1) 等をスクリプト冒頭で宣言する |
| ログ関数 | log_info / log_ok / log_warn / log_error 関数に色指定を集約する |
| フォールバック | [ -t 1 ] と tput colors で非対話環境を検出し、色変数を空文字にする |
| WARN/ERROR の出力先 | >&2 で標準エラーに分ける(ログとの混在を防ぐ) |
| リセット忘れ防止 | trap 'printf "%s" "${RESET}"' EXIT をスクリプト冒頭に追加する |
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、tput を活用したカラー出力設計のような実践的なシェルスクリプト技術を体系的に学べる環境を用意しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:シェルスクリプトの前提条件チェック設計|実行前にコマンド・ファイル・権限・ディスク容量を一括検証する方法
- この記事の属するカテゴリ:シェルスクリプトへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます