tput命令用于查询和操作终端功能,可以控制终端属性、移动光标、改变文本颜色、清除屏幕等,是Shell脚本中终端控制的重要工具。
tput主要通过终端数据库(terminfo)来操作终端功能:
tput [选项] 功能名
# 常用选项
-T type # 指定终端类型
-S # 从标准输入读取参数(一行一个)
-V # 显示版本信息
# 示例
tput cols # 获取终端列数
tput setaf 2 # 设置前景色为绿色
tput bold # 设置为粗体
tput cup 10 20 # 移动光标到第10行第20列
# 1. 设置前景色(文本颜色)
tput setaf 0 # 黑色
tput setaf 1 # 红色
tput setaf 2 # 绿色
tput setaf 3 # 黄色
tput setaf 4 # 蓝色
tput setaf 5 # 洋红色
tput setaf 6 # 青色
tput setaf 7 # 白色
tput setaf 8 # 亮黑色(灰色)
tput setaf 9 # 亮红色
# 2. 设置背景色
tput setab 0 # 黑色背景
tput setab 1 # 红色背景
tput setab 2 # 绿色背景
tput setab 3 # 黄色背景
tput setab 4 # 蓝色背景
tput setab 5 # 洋红色背景
tput setab 6 # 青色背景
tput setab 7 # 白色背景
# 3. 重置颜色
tput sgr0 # 重置所有属性(包括颜色)
# 4. 颜色代码变量(在脚本中使用)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
RESET=$(tput sgr0)
# 使用示例
echo "${RED}这是红色文本${RESET}"
echo "${GREEN}这是绿色文本${RESET}"
echo "${YELLOW}这是黄色文本${RESET}"
# 1. 文本样式
tput bold # 粗体
tput dim # 暗淡(低亮度)
tput smul # 下划线开始
tput rmul # 下划线结束
tput rev # 反显(反转前景和背景)
tput smso # 突出模式开始(通常为反显)
tput rmso # 突出模式结束
tput blink # 闪烁(可能不支持)
tput invis # 隐藏文本
# 2. 样式代码变量
BOLD=$(tput bold)
UNDERLINE=$(tput smul)
NO_UNDERLINE=$(tput rmul)
REVERSE=$(tput rev)
RESET=$(tput sgr0)
# 3. 组合使用
echo "${BOLD}粗体文本${RESET}"
echo "${UNDERLINE}下划线文本${NO_UNDERLINE}"
echo "${REVERSE}反显文本${RESET}"
# 4. 组合颜色和样式
echo "${BOLD}${RED}粗体红色文本${RESET}"
echo "${UNDERLINE}${GREEN}绿色下划线文本${RESET}"
# 5. 完整示例
TITLE="${BOLD}${BLUE}"
SUCCESS="${BOLD}${GREEN}"
ERROR="${BOLD}${RED}"
WARNING="${BOLD}${YELLOW}"
INFO="${BOLD}${CYAN}"
RESET=$(tput sgr0)
echo "${TITLE}=== 系统信息 ===${RESET}"
echo "${INFO}主机名:$(tput sgr0) localhost"
echo "${SUCCESS}状态:$(tput sgr0) 运行正常"
| 命令 | 说明 | 示例 |
|---|---|---|
cup Y X |
移动光标到第Y行第X列 | tput cup 10 20 |
sc |
保存当前光标位置 | tput sc |
rc |
恢复保存的光标位置 | tput rc |
home |
移动光标到左上角 | tput home |
civis |
隐藏光标 | tput civis |
cnorm |
显示光标 | tput cnorm |
cuu N |
光标上移N行 | tput cuu 2 |
cud N |
光标下移N行 | tput cud 2 |
cuf N |
光标右移N列 | tput cuf 10 |
cub N |
光标左移N列 | tput cub 10 |
#!/bin/bash
# 光标控制示例
# 保存光标位置
tput sc
# 移动到第5行第10列
tput cup 5 10
echo "位置1"
# 移动到第7行第30列
tput cup 7 30
echo "位置2"
# 恢复之前保存的位置
tput rc
echo "回到保存的位置"
# 隐藏光标
tput civis
sleep 2
# 显示光标
tput cnorm
# 光标移动动画
for i in {1..20}; do
tput cup 10 $i
echo -n ">"
sleep 0.1
done
# 清除动画行
tput cup 10 1
tput el # 清除到行尾
echo "动画完成"
| 命令 | 说明 | 示例 |
|---|---|---|
clear |
清除整个屏幕(同clear命令) | tput clear |
ed |
清除从光标到屏幕末尾 | tput ed |
el |
清除从光标到行尾 | tput el |
el1 |
清除从光标到行首 | tput el1 |
smcup |
进入备用屏幕缓冲区 | tput smcup |
rmcup |
退出备用屏幕缓冲区 | tput rmcup |
bell |
终端响铃(发出声音) | tput bell |
flash |
屏幕闪烁(可能不支持) | tput flash |
# 1. 设置制表符宽度
tput tabs # 设置制表符为8个空格(默认)
tput hts # 设置制表位
tput ht # 跳转到下一个制表位
# 2. 字符属性
tput smacs # 进入备用字符集模式
tput rmacs # 退出备用字符集模式
tput enacs # 启用备用字符集
tput smkx # 启用键盘传输模式
tput rmkx # 禁用键盘传输模式
# 3. 文本对齐(某些终端支持)
tput csr 5 15 # 设置滚动区域为5-15行
tput wind # 获取窗口大小
# 4. 完整格式化示例
echo "正常文本"
tput bold
echo "粗体文本"
tput sgr0 # 重置
tput smul
echo "下划线文本"
tput rmul
tput rev
echo "反显文本"
tput sgr0
# 5. 表格格式化
echo "$(tput smul)列1$(tput rmul) $(tput smul)列2$(tput rmul)"
echo "数据1 数据2"
echo "$(tput setaf 2)成功$(tput sgr0) $(tput setaf 1)失败$(tput sgr0)"
# 1. 获取终端尺寸
tput cols # 获取终端列数
tput lines # 获取终端行数
tput longname # 获取终端完整名称
# 2. 获取其他属性
tput colors # 获取终端支持的颜色数
tput pairs # 获取颜色对数量
tput cbt # 后退制表符
tput bel # 响铃字符
tput cr # 回车字符
tput ind # 换行字符
# 3. 综合信息获取脚本
echo "终端信息:"
echo "列数: $(tput cols)"
echo "行数: $(tput lines)"
echo "终端名: $(tput longname)"
echo "支持颜色数: $(tput colors)"
# 4. 检查功能是否支持
check_terminal_capability() {
if tput longname >/dev/null 2>&1; then
echo "终端信息查询支持"
else
echo "终端信息查询不支持"
fi
}
# 5. 使用-S选项从标准输入读取
echo "cols\nlines\ncolors" | tput -S
# 输出:
# 80
# 24
# 256
#!/bin/bash
# 彩色日志输出脚本
# 文件名:color_logger.sh
# 定义颜色和样式
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
BOLD=$(tput bold)
UNDERLINE=$(tput smul)
NO_UNDERLINE=$(tput rmul)
RESET=$(tput sgr0)
# 日志级别样式
LOG_INFO="${CYAN}"
LOG_SUCCESS="${GREEN}${BOLD}"
LOG_WARNING="${YELLOW}${BOLD}"
LOG_ERROR="${RED}${BOLD}"
LOG_DEBUG="${MAGENTA}"
LOG_TITLE="${BLUE}${BOLD}${UNDERLINE}"
# 日志函数
log() {
local level="$1"
local message="$2"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
case $level in
title)
echo "${LOG_TITLE}=== $message ===${RESET}"
;;
info)
echo "[${timestamp}] ${LOG_INFO}INFO:${RESET} $message"
;;
success)
echo "[${timestamp}] ${LOG_SUCCESS}SUCCESS:${RESET} $message"
;;
warning)
echo "[${timestamp}] ${LOG_WARNING}WARNING:${RESET} $message"
;;
error)
echo "[${timestamp}] ${LOG_ERROR}ERROR:${RESET} $message" >&2
;;
debug)
if [ "${DEBUG:-false}" = "true" ]; then
echo "[${timestamp}] ${LOG_DEBUG}DEBUG:${RESET} $message"
fi
;;
*)
echo "[${timestamp}] $message"
;;
esac
}
# 进度条函数
progress_bar() {
local duration=${1:-10}
local width=${2:-50}
local progress=0
# 隐藏光标
tput civis
for ((i=0; i<=duration; i++)); do
# 计算进度百分比
progress=$((i * 100 / duration))
bar_length=$((i * width / duration))
# 创建进度条字符串
bar="["
for ((j=0; j/dev/null || true
log info "开始处理任务..."
progress_bar 5 40
log success "所有检查完成"
log debug "调试信息:当前用户 $(whoami)"
}
# 运行主函数
main
#!/bin/bash
# 交互式终端菜单
# 文件名:terminal_menu.sh
# 颜色定义
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
BOLD=$(tput bold)
RESET=$(tput sgr0)
# 清屏并显示标题
clear_screen() {
tput clear
tput cup 0 0
}
# 显示标题
show_title() {
local title="$1"
local width=$(tput cols)
local padding=$(( (width - ${#title} - 4) / 2 ))
echo ""
printf "%${padding}s" ""
echo "${BOLD}${BLUE}[ $title ]${RESET}"
echo ""
}
# 显示菜单项
show_menu_item() {
local number="$1"
local text="$2"
local selected="$3"
if [ "$selected" = "true" ]; then
echo " ${BOLD}${GREEN}>${RESET} ${BOLD}[$number]${RESET} $text"
else
echo " ${WHITE}[$number]${RESET} $text"
fi
}
# 显示菜单
show_menu() {
local selected_item="$1"
clear_screen
show_title "系统管理菜单"
echo "请使用上下箭头选择,回车确认"
echo ""
# 菜单项
items=(
"系统信息"
"磁盘使用"
"内存信息"
"网络状态"
"服务状态"
"用户管理"
"退出"
)
# 显示所有菜单项
for i in "${!items[@]}"; do
local item_num=$((i + 1))
if [ "$item_num" -eq "$selected_item" ]; then
show_menu_item "$item_num" "${items[$i]}" "true"
else
show_menu_item "$item_num" "${items[$i]}" "false"
fi
done
echo ""
echo "${YELLOW}当前选择: ${items[$((selected_item - 1))]}${RESET}"
}
# 执行菜单项
execute_menu_item() {
local item="$1"
clear_screen
case $item in
1)
echo "${BOLD}${CYAN}=== 系统信息 ===${RESET}"
echo ""
echo "${GREEN}主机名:${RESET} $(hostname)"
echo "${GREEN}内核版本:${RESET} $(uname -r)"
echo "${GREEN}系统版本:${RESET} $(lsb_release -d 2>/dev/null | cut -f2 || cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2 | tr -d '\"')"
echo "${GREEN}运行时间:${RESET} $(uptime -p | sed 's/up //')"
echo "${GREEN}当前用户:${RESET} $(whoami)"
;;
2)
echo "${BOLD}${CYAN}=== 磁盘使用 ===${RESET}"
echo ""
df -h | grep -E "^/dev/" | while read line; do
echo "$line" | awk '{printf "%-20s %-10s %-10s %-10s %s\n", $1, $2, $3, $4, $6}'
done
;;
3)
echo "${BOLD}${CYAN}=== 内存信息 ===${RESET}"
echo ""
free -h | awk '
NR==1 {printf "%-15s %-10s %-10s %-10s %-10s\n", "类型", "总量", "已用", "可用", "使用率"}
NR==2 {printf "%-15s %-10s %-10s %-10s %-10s\n", "内存:", $2, $3, $4, $3/$2*100"%"}
NR==3 {printf "%-15s %-10s %-10s %-10s %-10s\n", "交换:", $2, $3, $4, $3/$2*100"%"}
'
;;
4)
echo "${BOLD}${CYAN}=== 网络状态 ===${RESET}"
echo ""
ip -br addr show | head -5
echo ""
echo "${GREEN}网络连接:${RESET}"
ss -tunlp | head -10
;;
5)
echo "${BOLD}${CYAN}=== 服务状态 ===${RESET}"
echo ""
systemctl list-units --type=service --state=running 2>/dev/null | head -10 || \
echo "无法获取服务状态"
;;
6)
echo "${BOLD}${CYAN}=== 用户管理 ===${RESET}"
echo ""
echo "${GREEN}当前登录用户:${RESET}"
who -H
echo ""
echo "${GREEN}系统用户:${RESET}"
cut -d: -f1 /etc/passwd | head -10
;;
7)
echo "${GREEN}感谢使用,再见!${RESET}"
exit 0
;;
esac
echo ""
read -p "按回车键返回菜单..." -n1
}
# 主函数
main() {
local current_selection=1
local key
# 隐藏光标并设置终端为字符模式
tput civis
stty -echo -icanon
while true; do
show_menu "$current_selection"
# 读取单个按键
key=$(dd bs=1 count=1 2>/dev/null)
case $key in
# 上箭头(ANSI序列:ESC [ A)
$'\e')
# 读取序列的其余部分
read -s -n 2 key
case $key in
'[A') # 上箭头
if [ "$current_selection" -gt 1 ]; then
current_selection=$((current_selection - 1))
fi
;;
'[B') # 下箭头
if [ "$current_selection" -lt 7 ]; then
current_selection=$((current_selection + 1))
fi
;;
esac
;;
# 回车键
'')
execute_menu_item "$current_selection"
;;
# 数字键
[1-7])
current_selection=$key
execute_menu_item "$current_selection"
;;
# q键退出
q|Q)
tput cnorm
stty echo icanon
clear
exit 0
;;
esac
done
}
# 清理函数
cleanup() {
tput cnorm # 显示光标
stty echo icanon # 恢复终端设置
tput sgr0 # 重置所有属性
clear
}
# 设置陷阱以确保清理
trap cleanup EXIT INT TERM
# 运行主函数
main
#!/bin/bash
# 终端动画效果示例
# 文件名:terminal_animation.sh
# 颜色定义
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
BOLD=$(tput bold)
RESET=$(tput sgr0)
# 清屏
clear_screen() {
tput clear
}
# 显示闪烁标题
blink_title() {
local title="$1"
for i in {1..5}; do
clear_screen
if [ $((i % 2)) -eq 0 ]; then
echo "${BOLD}${BLUE}$title${RESET}"
else
echo "${BOLD}${CYAN}$title${RESET}"
fi
sleep 0.3
done
}
# 打字机效果
typewriter() {
local text="$1"
local delay="${2:-0.1}"
for ((i=0; i<${#text}; i++)); do
echo -n "${text:$i:1}"
sleep "$delay"
done
echo ""
}
# 进度条动画
animated_progress() {
local width=40
local frames=("▏" "▎" "▍" "▌" "▋" "▊" "▉" "█")
local frame_count=${#frames[@]}
echo -n "加载中: "
for i in {0..100}; do
# 计算进度条位置
local pos=$((i * width / 100))
# 构建进度条
local bar="["
for ((j=0; j/dev/null; do
i=$(( (i+1) %4 ))
tput sc
echo -n "${spin:$i:1} $message"
sleep 0.1
tput rc
tput el
done
# 显示光标
tput cnorm
tput sc
echo "${GREEN}✓ 完成${RESET}"
tput rc
tput el
}
# 文本雨效果
text_rain() {
local width=$(tput cols)
local height=$(tput lines)
local chars="01"
clear_screen
# 初始化雨滴位置
declare -a rain_pos
declare -a rain_speed
for ((i=0; i
# 问题:bash: tput: command not found 或颜色不显示
# 原因:ncurses包未安装或终端不支持颜色
# 解决方案:
# 1. 安装ncurses包
# Debian/Ubuntu:
sudo apt-get update
sudo apt-get install ncurses-bin
# CentOS/RHEL:
sudo yum install ncurses
# 2. 检查终端是否支持颜色
echo $TERM
# 应为xterm-256color、xterm-color、screen-256color等
# 3. 设置正确的TERM环境变量
export TERM=xterm-256color
# 或添加到~/.bashrc
echo 'export TERM=xterm-256color' >> ~/.bashrc
# 4. 检查终端颜色支持
tput colors
# 如果返回8或256,则支持颜色
# 5. 使用infocmp检查终端能力
infocmp $TERM | grep -E "colors|setaf|setab"
# 6. 对于不支持颜色的终端(如dumb)
if [ "$TERM" = "dumb" ]; then
echo "当前终端不支持颜色"
# 可以使用纯文本替代
fi
# 问题:光标移动不正确或屏幕闪烁异常
# 原因:终端能力不匹配或序列错误
# 解决方案:
# 1. 检查终端类型
echo $TERM
# 确保与实际终端匹配
# 2. 重置终端
tput reset
# 或
reset
# 3. 使用正确的坐标(从0开始)
# tput cup 行 列,行和列都是从0开始计数
# 例如:tput cup 0 0 是左上角
# 4. 保存和恢复光标位置
tput sc # 保存位置
# ... 执行操作 ...
tput rc # 恢复位置
# 5. 清除屏幕的正确方法
tput clear # 清除整个屏幕
tput cup 0 0 # 移动到左上角
# 6. 对于闪烁问题,避免快速连续更新
# 添加适当的延迟
sleep 0.1
# 7. 检查脚本是否在正确的终端运行
# 避免在管道或重定向中使用tput
if [ -t 1 ]; then
echo "在终端中运行"
tput setaf 2
echo "绿色文本"
tput sgr0
else
echo "不在终端中(可能是管道或重定向)"
fi
# 问题:设置颜色或格式后未正确重置,影响后续输出
# 原因:忘记调用tput sgr0
# 解决方案:
# 1. 总是重置格式
RED=$(tput setaf 1)
RESET=$(tput sgr0)
echo "${RED}红色文本${RESET} 正常文本"
# 2. 使用trap确保重置
cleanup() {
tput sgr0
tput cnorm
stty echo # 如果禁用了回显
}
trap cleanup EXIT INT TERM
# 3. 函数封装
print_color() {
local color="$1"
local text="$2"
tput setaf "$color"
echo -n "$text"
tput sgr0
}
# 使用
print_color 2 "绿色文本"
echo "正常文本"
# 4. 检查当前设置
# 可以使用tput -S查询多个属性
echo "sgr0" | tput -S
# 这会重置所有属性
# 5. 避免嵌套格式
# 错误的做法:
echo "$(tput setaf 1)$(tput bold)粗体红色$(tput sgr0)文本"
# 这里sgr0重置了所有,包括bold
# 正确的做法:
RED=$(tput setaf 1)
BOLD=$(tput bold)
RESET=$(tput sgr0)
echo "${BOLD}${RED}粗体红色${RESET}文本"
# 问题:脚本在不同终端上表现不一致
# 原因:不同终端支持的能力不同
# 解决方案:
# 1. 检测终端能力
detect_terminal_capabilities() {
# 检查颜色支持
if tput colors >/dev/null 2>&1; then
COLORS=$(tput colors)
if [ "$COLORS" -ge 256 ]; then
echo "支持256色"
elif [ "$COLORS" -ge 8 ]; then
echo "支持8色"
else
echo "不支持颜色"
fi
else
echo "无法确定颜色支持"
fi
# 检查光标移动支持
if tput cup 0 0 >/dev/null 2>&1; then
echo "支持光标移动"
else
echo "不支持光标移动"
fi
}
# 2. 使用条件判断
if tput colors >/dev/null 2>&1 && [ "$(tput colors)" -ge 8 ]; then
# 支持颜色,使用彩色输出
SUCCESS="$(tput setaf 2)"
ERROR="$(tput setaf 1)"
RESET="$(tput sgr0)"
else
# 不支持颜色,使用纯文本
SUCCESS=""
ERROR=""
RESET=""
fi
echo "${SUCCESS}成功信息${RESET}"
echo "${ERROR}错误信息${RESET}"
# 3. 回退方案
safe_tput() {
local capability="$1"
local default="$2"
if tput "$capability" >/dev/null 2>&1; then
tput "$capability"
else
echo -n "$default"
fi
}
# 使用
CLEAR=$(safe_tput clear "")
echo "${CLEAR}清屏"
# 4. 测试脚本
test_terminal() {
echo "测试终端能力:"
echo "1. 颜色测试:"
for i in {0..7}; do
tput setaf "$i"
echo -n "■"
done
tput sgr0
echo
echo "2. 光标移动测试:"
tput sc
tput cup 2 20
echo "光标位置测试"
tput rc
echo "3. 清除测试:"
read -p "按回车清除行末尾..." -n1
tput el
echo "已清除"
}
# 5. 使用标准ANSI序列作为备选
if command -v tput >/dev/null 2>&1; then
# 使用tput
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
RESET=$(tput sgr0)
else
# 使用ANSI转义序列
RED='\033[0;31m'
GREEN='\033[0;32m'
RESET='\033[0m'
fi
setaf N - 设置前景色(0-7)setab N - 设置背景色(0-7)sgr0 - 重置所有属性bold - 粗体smul - 下划线开始rmul - 下划线结束cup Y X - 移动光标sc - 保存位置rc - 恢复位置civis - 隐藏光标cnorm - 显示光标clear - 清除屏幕# 获取信息
cols # 列数
lines # 行数
colors # 颜色数
longname # 终端名称
# 脚本中常用变量定义
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
BOLD=$(tput bold)
RESET=$(tput sgr0)
tput sgr0重置TERM环境变量,确保终端支持所需功能tput -S一次执行多个操作提高效率tput sc和tput rc保存/恢复光标位置civis),结束时显示(cnorm)tput sgr0会重置所有属性,包括颜色和样式tput可能无法正常工作