history命令用于显示和操作命令行历史记录,可以快速查看、搜索、重复执行之前使用过的命令,是提高Linux工作效率的重要工具。
history命令主要用于管理shell会话历史记录:
不同shell的历史记录文件位置:
history [选项] [数字]
# 或使用快捷方式:
!数字 # 执行指定编号的历史命令
!! # 执行上一条命令
!字符串 # 执行最近以指定字符串开头的命令
| 选项 | 说明 |
|---|---|
n |
显示最近n条历史记录 |
-c |
清除所有历史记录 |
-d 数字 |
删除指定编号的历史记录 |
-a |
将当前会话的历史记录追加到历史文件 |
-w |
将当前历史记录写入历史文件(覆盖) |
-r |
从历史文件读取历史记录到当前会话 |
-s 字符串 |
将字符串添加到历史记录,但不执行 |
--help |
显示帮助信息 |
# 1. 查看所有历史记录(默认显示最近的500-1000条)
history
# 2. 查看最近N条历史记录
history 10 # 查看最近10条
history 20 # 查看最近20条
history 50 | less # 分页查看最近50条
# 3. 查看完整历史记录(包括时间戳)
# 先设置HISTTIMEFORMAT环境变量
export HISTTIMEFORMAT='%F %T '
history
# 4. 永久设置时间戳(添加到~/.bashrc)
echo "export HISTTIMEFORMAT='%F %T '" >> ~/.bashrc
source ~/.bashrc
# 5. 查看历史记录文件
cat ~/.bash_history
wc -l ~/.bash_history # 统计历史记录条数
# 6. 带行号显示历史记录
history | nl # 添加行号
history | cat -n # 另一种添加行号的方式
# 7. 统计最常用的命令
history | awk '{print $2}' | sort | uniq -c | sort -rn | head -10
# 8. 查看今天执行的命令
history | grep "$(date +%Y-%m-%d)"
# 9. 按时间范围查看
# 需要先启用HISTTIMEFORMAT
history | grep "2023-10-01"
# 10. 格式化输出
history | awk '{printf "%-5s %s %s\n", NR, $2, $3}'
# 1. !! - 执行上一条命令
!! # 重新执行上一条命令
sudo !! # 用sudo执行上一条命令
# 2. !数字 - 执行指定编号的命令
!100 # 执行历史记录中编号为100的命令
!-1 # 执行上一条命令(同!!)
!-2 # 执行倒数第二条命令
!-3 # 执行倒数第三条命令
# 3. !字符串 - 执行最近以指定字符串开头的命令
!ls # 执行最近以ls开头的命令
!git # 执行最近以git开头的命令
!sudo # 执行最近以sudo开头的命令
# 4. !?字符串 - 执行最近包含指定字符串的命令
!?config # 执行最近包含config的命令
!?error # 执行最近包含error的命令
# 5. ^原字符串^新字符串 - 修改上一条命令并执行
# 将上一条命令中的"old"替换为"new"
^old^new
# 6. !# - 引用当前命令行已输入的部分
echo !# # 输出当前命令行已输入的内容
# 7. !$ - 上一条命令的最后一个参数
ls /etc/passwd
cat !$ # 等同于 cat /etc/passwd
# 8. !* - 上一条命令的所有参数
ls file1 file2 file3
cat !* # 等同于 cat file1 file2 file3
# 9. !:n - 上一条命令的第n个参数
ls file1 file2 file3
echo !:2 # 等同于 echo file2
# 10. 组合使用
# 执行倒数第三条命令,并替换其中的字符串
!-3:s/old/new/
# 11. 仅显示而不执行(预览)
!100:p # 显示编号100的命令,但不执行
!!:p # 显示上一条命令,但不执行
# 12. 安全模式(防止意外执行危险命令)
# 使用:p预览后再执行
!!:p # 先查看
!! # 确认后执行
# 1. Ctrl+R - 反向搜索(最常用)
# 按Ctrl+R,输入关键词,按Enter执行
# 按Ctrl+R继续搜索更早的匹配
# 按Enter执行,按Esc取消
# 2. Ctrl+S - 正向搜索(需要设置stty)
# 先启用正向搜索:stty -ixon
# 然后可以使用Ctrl+S向前搜索
# 3. grep搜索历史记录
history | grep "ssh"
history | grep -i "docker"
history | grep -E "git (pull|push)"
history | grep -v "password" # 排除包含password的命令
# 4. 使用fc命令搜索和编辑
fc -l # 列出历史记录
fc -l 100 # 从第100条开始列出
fc -l git # 列出所有包含git的命令
# 5. 使用HISTSIZE和HISTFILESIZE控制搜索范围
# 在~/.bashrc中设置
export HISTSIZE=10000 # 内存中保存10000条
export HISTFILESIZE=20000 # 文件中保存20000条
# 6. 使用HISTCONTROL忽略重复命令
export HISTCONTROL=ignoredups # 忽略连续重复的命令
export HISTCONTROL=ignorespace # 忽略以空格开头的命令
export HISTCONTROL=ignoreboth # 同时忽略重复和空格开头
# 7. 快速搜索并编辑(使用fc命令)
fc # 编辑上一条命令
fc 100 # 编辑第100条命令
fc -e vim # 使用vim编辑历史命令
# 8. 使用向上/向下箭头键搜索
# 在命令行输入部分命令后按上箭头,会匹配以该部分开头的历史命令
# 9. 使用history命令配合其他工具
history | awk '/ssh/ && /root/ {print $0}' # 同时包含ssh和root
history | grep "2023-10" | grep "apt" # 特定日期的apt命令
# 10. 创建搜索函数
# 添加到~/.bashrc
hsearch() {
history | grep "$1"
}
# 使用:hsearch keyword
# 11. 使用外部工具搜索
# 安装fzf进行模糊搜索
# sudo apt-get install fzf
# 然后使用Ctrl+R配合fzf进行更强大的搜索
# 1. 清除所有历史记录
history -c # 清除当前会话的历史记录
# 注意:这只清除内存中的历史,文件中的历史仍然存在
# 2. 删除指定编号的历史记录
history -d 100 # 删除编号为100的历史记录
history -d 100-150 # 删除100到150之间的记录(某些shell不支持范围)
# 3. 删除多条记录
for i in {100..110}; do history -d 100; done # 循环删除100-110
# 4. 清空历史文件
> ~/.bash_history # 清空历史文件
history -c && history -w # 清空内存和文件中的历史
# 5. 保存当前历史记录到文件
history -w # 写入历史文件(覆盖)
history -a # 追加当前会话的历史记录
# 6. 从文件读取历史记录
history -r # 读取历史文件到当前会话
# 7. 永久删除包含敏感信息的命令
# 手动编辑~/.bash_history文件
nano ~/.bash_history
# 或使用sed删除包含密码的行
sed -i '/password/d' ~/.bash_history
# 8. 导出历史记录
history > history_backup.txt # 导出到文件
history | gzip > history_backup.gz # 压缩导出
# 9. 导入历史记录
# 如果文件格式正确,可以合并到现有历史
cat history_backup.txt >> ~/.bash_history
# 10. 备份历史记录文件
cp ~/.bash_history ~/.bash_history.backup.$(date +%Y%m%d)
# 11. 统计历史记录信息
echo "总命令数: $(wc -l < ~/.bash_history)"
echo "去重后命令数: $(sort ~/.bash_history | uniq | wc -l)"
# 12. 查找最长的命令
history | awk '{print length($0), $0}' | sort -rn | head -5
# 13. 会话间共享历史(实时同步)
# 在~/.bashrc中添加
shopt -s histappend
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# 以下配置通常添加到 ~/.bashrc 文件
# 1. HISTSIZE - 内存中保存的历史记录数量
export HISTSIZE=10000 # 设置内存保存10000条记录
# 2. HISTFILESIZE - 历史文件中保存的记录数量
export HISTFILESIZE=20000 # 设置文件保存20000条记录
# 3. HISTTIMEFORMAT - 历史记录时间格式
export HISTTIMEFORMAT='%Y-%m-%d %H:%M:%S '
# 格式说明:
# %Y - 年,%m - 月,%d - 日
# %H - 时,%M - 分,%S - 秒
# 4. HISTCONTROL - 历史记录控制
export HISTCONTROL=ignoredups # 忽略连续重复的命令
export HISTCONTROL=ignorespace # 忽略以空格开头的命令
export HISTCONTROL=ignoreboth # 同时忽略重复和空格开头
export HISTCONTROL=erasedups # 删除所有重复的命令
# 5. HISTIGNORE - 忽略特定命令(不保存到历史)
export HISTIGNORE="ls:ll:la:cd:pwd:exit:history"
# 多个命令用冒号分隔
export HISTIGNORE="ls:cd:history:exit:* --help"
# 6. HISTFILE - 指定历史记录文件位置
export HISTFILE=~/.my_custom_history # 自定义历史文件
# 7. 启用历史记录追加模式(而不是覆盖)
shopt -s histappend
# 8. 实时保存历史记录(每个命令后立即保存)
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# 9. 完整配置示例
cat >> ~/.bashrc << 'EOF'
# History Configuration
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTTIMEFORMAT="%F %T "
export HISTCONTROL=ignoreboth:erasedups
export HISTIGNORE="ls:ll:cd:pwd:clear:history"
shopt -s histappend
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
EOF
# 10. 为root用户单独配置
sudo tee -a /root/.bashrc << 'EOF'
# Root user history settings
export HISTSIZE=5000
export HISTFILESIZE=10000
export HISTTIMEFORMAT="%F %T (root) "
export HISTCONTROL=ignoreboth
EOF
# 11. 系统范围的配置(影响所有用户)
sudo tee -a /etc/bash.bashrc << 'EOF'
# System-wide history settings
export HISTSIZE=1000
export HISTFILESIZE=2000
export HISTCONTROL=ignoredups
EOF
# 12. 检查当前配置
echo "HISTSIZE: $HISTSIZE"
echo "HISTFILESIZE: $HISTFILESIZE"
echo "HISTTIMEFORMAT: $HISTTIMEFORMAT"
echo "HISTCONTROL: $HISTCONTROL"
echo "HISTIGNORE: $HISTIGNORE"
echo "HISTFILE: $HISTFILE"
#!/bin/bash
# 历史记录分析脚本
# 文件名:history_analyzer.sh
HISTORY_FILE="${1:-$HOME/.bash_history}"
OUTPUT_FILE="/tmp/history_analysis_$(date +%Y%m%d_%H%M%S).txt"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 检查文件是否存在
if [ ! -f "$HISTORY_FILE" ]; then
echo -e "${RED}错误: 历史文件不存在: $HISTORY_FILE${NC}"
exit 1
fi
echo -e "${BLUE}=== 历史记录分析报告 ===${NC}"
echo "分析文件: $HISTORY_FILE"
echo "生成时间: $(date)"
echo "输出文件: $OUTPUT_FILE"
echo ""
analyze_history() {
echo -e "${GREEN}1. 基本信息${NC}"
total_commands=$(wc -l < "$HISTORY_FILE")
unique_commands=$(sort "$HISTORY_FILE" | uniq | wc -l)
echo "总命令数: $total_commands"
echo "去重后命令数: $unique_commands"
echo "重复率: $(( (total_commands - unique_commands) * 100 / total_commands ))%"
echo ""
echo -e "${GREEN}2. 最常用命令 (Top 10)${NC}"
awk '{print $1}' "$HISTORY_FILE" | sort | uniq -c | sort -rn | head -10 | \
awk '{printf "%-5s %s\n", $1, $2}'
echo ""
echo -e "${GREEN}3. 最长命令${NC}"
awk '{print length($0), $0}' "$HISTORY_FILE" | sort -rn | head -5 | \
awk '{printf "%-5s字符: %s\n", $1, substr($0, index($0,$2))}'
echo ""
echo -e "${GREEN}4. 命令分类统计${NC}"
echo "系统管理:"
grep -c -E "^(sudo|apt|yum|dnf|systemctl|service)" "$HISTORY_FILE" || true
echo "文件操作:"
grep -c -E "^(ls|cd|cp|mv|rm|mkdir|touch)" "$HISTORY_FILE" || true
echo "网络相关:"
grep -c -E "^(ping|ssh|scp|curl|wget|netstat|ifconfig)" "$HISTORY_FILE" || true
echo "开发工具:"
grep -c -E "^(git|docker|kubectl|npm|python|java)" "$HISTORY_FILE" || true
echo ""
echo -e "${GREEN}5. 每日命令统计${NC}"
if grep -q "^#[0-9]" "$HISTORY_FILE"; then
# 如果有时戳信息
grep "^#[0-9]" "$HISTORY_FILE" | awk '{print strftime("%Y-%m-%d", $2)}' | \
sort | uniq -c | tail -10
else
echo "未启用时间戳记录 (设置 HISTTIMEFORMAT)"
fi
echo ""
echo -e "${GREEN}6. 潜在危险命令${NC}"
dangerous_patterns=("rm -rf" "chmod 777" "dd if=" "mkfs" ":(){:|:&};:")
for pattern in "${dangerous_patterns[@]}"; do
count=$(grep -c "$pattern" "$HISTORY_FILE")
if [ "$count" -gt 0 ]; then
echo -e "${RED}警告: 找到 $count 个包含 '$pattern' 的命令${NC}"
fi
done
echo ""
echo -e "${GREEN}7. 最近活动${NC}"
tail -20 "$HISTORY_FILE" | nl -ba | sed 's/^/ /'
}
# 运行分析并保存到文件
analyze_history | tee "$OUTPUT_FILE"
echo -e "${BLUE}=== 分析完成 ===${NC}"
echo "详细报告已保存到: $OUTPUT_FILE"
echo ""
echo -e "${YELLOW}建议:${NC}"
echo "1. 定期清理历史记录: history -c && history -w"
echo "2. 忽略无用命令: export HISTIGNORE='ls:cd:pwd:history'"
echo "3. 启用时间戳: export HISTTIMEFORMAT='%F %T '"
#!/bin/bash
# 历史命令备份和恢复工具
# 文件名:history_backup_tool.sh
BACKUP_DIR="$HOME/.history_backups"
CONFIG_FILE="$HOME/.history_tool_config"
# 初始化
init_tool() {
mkdir -p "$BACKUP_DIR"
if [ ! -f "$CONFIG_FILE" ]; then
cat > "$CONFIG_FILE" << EOF
# History Backup Tool Configuration
BACKUP_ENABLED=true
AUTO_BACKUP_DAYS=7
MAX_BACKUPS=30
COMPRESS_BACKUPS=true
ENCRYPT_BACKUPS=false
EOF
fi
source "$CONFIG_FILE"
}
# 显示菜单
show_menu() {
echo "=== 历史命令管理工具 ==="
echo "1. 备份当前历史记录"
echo "2. 恢复历史记录"
echo "3. 列出所有备份"
echo "4. 清理旧备份"
echo "5. 比较不同备份"
echo "6. 统计信息"
echo "7. 配置工具"
echo "8. 自动备份设置"
echo "9. 退出"
echo -n "请选择 [1-9]: "
}
# 备份历史记录
backup_history() {
local backup_name="history_$(date +%Y%m%d_%H%M%S)"
local backup_path="$BACKUP_DIR/$backup_name"
echo "正在备份历史记录..."
# 保存当前历史
history -a # 确保所有命令已保存
# 复制历史文件
cp "$HISTFILE" "$backup_path"
# 添加元数据
echo "# Backup created: $(date)" >> "$backup_path"
echo "# User: $(whoami)" >> "$backup_path"
echo "# Host: $(hostname)" >> "$backup_path"
echo "# Total commands: $(wc -l < "$HISTFILE")" >> "$backup_path"
# 压缩
if [ "$COMPRESS_BACKUPS" = "true" ]; then
gzip "$backup_path"
backup_path="${backup_path}.gz"
fi
echo "备份完成: $(basename "$backup_path")"
echo "文件大小: $(du -h "$backup_path" | cut -f1)"
}
# 恢复历史记录
restore_history() {
echo "可用的备份:"
ls -lh "$BACKUP_DIR" | nl
echo -n "请输入要恢复的备份编号: "
read -r backup_num
local backups=("$BACKUP_DIR"/*)
local selected="${backups[$((backup_num-1))]}"
if [ ! -f "$selected" ]; then
echo "无效的选择"
return 1
fi
echo "即将恢复: $(basename "$selected")"
echo -n "确认恢复?(y/N): "
read -r confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
# 解压如果需要
local source_file="$selected"
if [[ "$selected" == *.gz ]]; then
gunzip -c "$selected" > "/tmp/history_restore"
source_file="/tmp/history_restore"
fi
# 备份当前历史
local current_backup="$BACKUP_DIR/current_before_restore_$(date +%s)"
cp "$HISTFILE" "$current_backup"
# 恢复
cp "$source_file" "$HISTFILE"
history -c
history -r
echo "历史记录已恢复"
echo "原历史已备份到: $(basename "$current_backup")"
# 清理临时文件
[ -f "/tmp/history_restore" ] && rm "/tmp/history_restore"
fi
}
# 列出备份
list_backups() {
echo "=== 备份列表 ==="
echo "总数: $(ls "$BACKUP_DIR" | wc -l)"
echo ""
ls -lh "$BACKUP_DIR" | awk '
NR==1 {print "权限\t大小\t日期\t\t名称"}
NR>1 {print $1 "\t" $5 "\t" $6 " " $7 "\t" $8}
'
}
# 清理旧备份
cleanup_backups() {
echo "当前备份数量: $(ls "$BACKUP_DIR" | wc -l)"
echo "配置的最大备份数: $MAX_BACKUPS"
if [ "$(ls "$BACKUP_DIR" | wc -l)" -le "$MAX_BACKUPS" ]; then
echo "无需清理"
return
fi
echo -n "确认清理旧备份?(y/N): "
read -r confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
# 按时间排序,保留最新的 MAX_BACKUPS 个
ls -t "$BACKUP_DIR" | tail -n +$((MAX_BACKUPS + 1)) | while read -r file; do
echo "删除: $file"
rm "$BACKUP_DIR/$file"
done
echo "清理完成"
fi
}
# 比较备份
compare_backups() {
echo "选择第一个备份:"
ls "$BACKUP_DIR" | nl
echo -n "请输入编号: "
read -r num1
echo "选择第二个备份:"
ls "$BACKUP_DIR" | nl
echo -n "请输入编号: "
read -r num2
local backups=("$BACKUP_DIR"/*)
local backup1="${backups[$((num1-1))]}"
local backup2="${backups[$((num2-1))]}"
# 临时解压
if [[ "$backup1" == *.gz ]]; then
gunzip -c "$backup1" > /tmp/backup1_tmp
backup1="/tmp/backup1_tmp"
fi
if [[ "$backup2" == *.gz ]]; then
gunzip -c "$backup2" > /tmp/backup2_tmp
backup2="/tmp/backup2_tmp"
fi
echo "=== 比较结果 ==="
echo "备份1: $(basename "${backups[$((num1-1))]}")"
echo "备份2: $(basename "${backups[$((num2-1))]}")"
echo ""
echo "1. 行数统计:"
echo " 备份1: $(wc -l < "$backup1") 行"
echo " 备份2: $(wc -l < "$backup2") 行"
echo ""
echo "2. 唯一命令:"
echo " 只在备份1中: $(comm -23 <(sort "$backup1") <(sort "$backup2") | wc -l)"
echo " 只在备份2中: $(comm -13 <(sort "$backup1") <(sort "$backup2") | wc -l)"
echo " 共同命令: $(comm -12 <(sort "$backup1") <(sort "$backup2") | wc -l)"
echo ""
echo "3. 示例差异:"
echo " 只在备份1中的前5条:"
comm -23 <(sort "$backup1") <(sort "$backup2") | head -5 | sed 's/^/ /'
echo ""
echo " 只在备份2中的前5条:"
comm -13 <(sort "$backup1") <(sort "$backup2") | head -5 | sed 's/^/ /'
# 清理临时文件
[ -f "/tmp/backup1_tmp" ] && rm "/tmp/backup1_tmp"
[ -f "/tmp/backup2_tmp" ] && rm "/tmp/backup2_tmp"
}
# 自动备份设置
setup_auto_backup() {
echo "=== 自动备份设置 ==="
echo "当前设置:"
echo " 自动备份: $BACKUP_ENABLED"
echo " 备份间隔: $AUTO_BACKUP_DAYS 天"
echo " 最大备份数: $MAX_BACKUPS"
echo ""
echo "1. 启用/禁用自动备份"
echo "2. 设置备份间隔"
echo "3. 设置最大备份数"
echo "4. 返回"
echo -n "请选择: "
read -r choice
case $choice in
1)
echo -n "启用自动备份?(y/N): "
read -r enable
if [ "$enable" = "y" ]; then
sed -i 's/BACKUP_ENABLED=.*/BACKUP_ENABLED=true/' "$CONFIG_FILE"
echo "已启用自动备份"
else
sed -i 's/BACKUP_ENABLED=.*/BACKUP_ENABLED=false/' "$CONFIG_FILE"
echo "已禁用自动备份"
fi
;;
2)
echo -n "请输入备份间隔天数: "
read -r days
if [[ "$days" =~ ^[0-9]+$ ]]; then
sed -i "s/AUTO_BACKUP_DAYS=.*/AUTO_BACKUP_DAYS=$days/" "$CONFIG_FILE"
echo "备份间隔已设置为 $days 天"
fi
;;
3)
echo -n "请输入最大备份数量: "
read -r max
if [[ "$max" =~ ^[0-9]+$ ]]; then
sed -i "s/MAX_BACKUPS=.*/MAX_BACKUPS=$max/" "$CONFIG_FILE"
echo "最大备份数已设置为 $max"
fi
;;
esac
source "$CONFIG_FILE"
}
# 主函数
main() {
init_tool
while true; do
show_menu
read -r choice
case $choice in
1) backup_history ;;
2) restore_history ;;
3) list_backups ;;
4) cleanup_backups ;;
5) compare_backups ;;
6) analyze_history ;;
7) nano "$CONFIG_FILE" ;;
8) setup_auto_backup ;;
9)
echo "退出"
exit 0
;;
*)
echo "无效选择"
;;
esac
echo ""
read -p "按回车键继续..." -n1
clear
done
}
# 运行主函数
main
#!/bin/bash
# 高效历史命令使用技巧
# 文件名:history_tips.sh
echo "=== Linux history 高效使用技巧 ==="
echo ""
echo "1. 基础快捷键"
echo " Ctrl+P / 上箭头 - 上一个命令"
echo " Ctrl+N / 下箭头 - 下一个命令"
echo " Ctrl+R - 反向搜索历史"
echo " Ctrl+S - 正向搜索历史(需要 stty -ixon)"
echo " Ctrl+G - 退出搜索"
echo ""
echo "2. 历史扩展"
echo " !! - 上一条命令"
echo " !10 - 执行第10条历史命令"
echo " !-2 - 执行倒数第二条命令"
echo " !string - 执行最近以string开头的命令"
echo " !?string - 执行最近包含string的命令"
echo " ^old^new - 替换上一条命令中的字符串"
echo " !$ - 上一条命令的最后一个参数"
echo " !* - 上一条命令的所有参数"
echo ""
echo "3. 搜索技巧"
cat << 'EOF'
# 使用grep搜索
history | grep ssh
history | grep -i "error"
history | grep -E "git (push|pull)"
# 使用fc命令
fc -l # 列出历史
fc -l 100 150 # 列出100-150条
fc -e vim # 用vim编辑上一条命令
# 实时搜索(添加到~/.bashrc)
bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'
EOF
echo ""
echo "4. 配置优化"
cat << 'EOF'
# ~/.bashrc 中添加
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTTIMEFORMAT="%F %T "
export HISTCONTROL=ignoreboth:erasedups
export HISTIGNORE="ls:ll:cd:pwd:clear"
# 实时同步历史(多终端共享)
shopt -s histappend
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# 忽略敏感命令
export HISTIGNORE="*mysql*:*password*:*secret*"
EOF
echo ""
echo "5. 实用函数(添加到~/.bashrc)"
cat << 'EOF'
# 快速执行上一条命令的最后一个参数
alias r='fc -s'
# 搜索历史并执行
hs() {
local cmd
cmd=$(history | fzf | sed 's/^[ ]*[0-9]*[ ]*//')
[ -n "$cmd" ] && eval "$cmd"
}
# 统计命令使用频率
histstat() {
history | awk '{CMD[$2]++;count++;}END{for(a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | \
grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -20
}
# 查找重复命令
histdup() {
history | awk 'BEGIN {FS="[ \t]+|\\|"} {print $3}' | sort | uniq -c | sort -rn | head -20
}
# 按日期查看历史
histdate() {
grep "^#[0-9]*" ~/.bash_history | awk '{print strftime("%Y-%m-%d %H:%M:%S", substr($1,2))}' | \
sort | uniq -c | head -20
}
EOF
echo ""
echo "6. 安全相关"
echo " 禁用历史记录: unset HISTFILE"
echo " 不记录当前会话: set +o history"
echo " 删除包含敏感信息的命令:"
echo " history -d 编号"
echo " 或编辑 ~/.bash_history"
echo " 忽略以空格开头的命令(不记录):"
echo " export HISTCONTROL=ignorespace"
echo " 然后输入命令前加空格"
echo ""
echo "7. 高级技巧"
cat << 'EOF'
# 使用外部工具增强
# fzf: 模糊搜索
# hstr: 历史搜索工具
# mcfly: Rust编写的历史搜索
# 安装fzf示例
# git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
# ~/.fzf/install
# 然后可以绑定到Ctrl+R
# bind -x '"\C-r": __fzf_history__'
# 历史记录分析
# 最常用命令: history | awk '{print $2}' | sort | uniq -c | sort -rn | head
# 最长命令: history | awk '{print length($0), $0}' | sort -rn | head
# 今日命令: history | grep "$(date +%Y-%m-%d)"
# 跨终端同步
# 在~/.bashrc中添加:
# export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# 备份历史
# cp ~/.bash_history ~/bash_history_backup_$(date +%Y%m%d)
# 恢复历史
# cp ~/bash_history_backup ~/.bash_history
# history -c; history -r
EOF
echo ""
echo "8. 演示示例"
echo " $ # 假设历史中有以下命令"
echo " $ # 100: ls -la"
echo " $ # 101: cd /etc"
echo " $ # 102: cat nginx.conf"
echo " "
echo " $ !100 # 执行 ls -la"
echo " $ !ca # 执行 cat nginx.conf"
echo " $ !cd:p # 显示但不执行 cd /etc"
echo " $ ^la^lh # 将上条 ls -la 改为 ls -lh 并执行"
echo " $ !! | grep conf # 对上条命令输出进行grep"
echo ""
echo "总结:熟练使用history可以极大提高命令行工作效率!"
# 问题:history命令不记录或重启后历史记录丢失
# 原因:配置问题或权限问题
# 解决方案:
# 1. 检查HISTFILE变量
echo $HISTFILE
# 应该显示:/home/username/.bash_history
# 2. 检查历史文件权限
ls -la ~/.bash_history
# 权限应为:-rw------- 1 username username
# 如果权限不对:chmod 600 ~/.bash_history
# 3. 检查磁盘空间
df -h ~
# 清理磁盘空间:sudo apt-get clean 或删除大文件
# 4. 检查bash配置
# 确保~/.bashrc中有以下配置:
# export HISTSIZE=1000
# export HISTFILESIZE=2000
# shopt -s histappend
# 5. 检查是否设置了HISTCONTROL
echo $HISTCONTROL
# 如果包含ignorespace,以空格开头的命令不会被记录
# 6. 检查是否在脚本中运行
# 非交互式shell默认不记录历史
# 7. 检查HISTIGNORE设置
echo $HISTIGNORE
# 被忽略的命令不会被记录
# 8. 手动保存历史
history -a # 追加到文件
history -w # 覆盖写入文件
# 9. 检查多个终端会话
# 如果同时打开多个终端,最后一个退出的会覆盖历史
# 解决方法:实时同步历史
# 在~/.bashrc中添加:
# shopt -s histappend
# export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# 10. 检查文件系统类型
# 某些文件系统(如NTFS)可能不支持某些特性
# 问题:!命令扩展(如!!、!string)不工作
# 原因:shell设置问题或语法错误
# 解决方案:
# 1. 检查是否启用了历史扩展
set -o | grep history
# 应该显示:history on
# 2. 启用历史扩展
set -o history
# 3. 检查是否在脚本中
# !扩展在脚本中默认禁用
# 启用脚本中的历史扩展:set -o history
# 4. 检查bash版本
bash --version
# 旧版本可能有问题,更新bash
# 5. 使用完整语法
# 某些情况下需要转义!
\!ls # 转义!
'!ls' # 单引号
"!ls" # 双引号
# 6. 检查HISTCMD变量
echo $HISTCMD
# 如果为空,可能有问题
# 7. 重新加载bash配置
exec bash
# 或
source ~/.bashrc
# 8. 使用fc命令替代
fc -e :-1 # 等同于!!
fc -s ls # 等同于!ls
# 9. 检查是否设置了某些shell选项
# 某些选项可能影响历史扩展
shopt -p | grep hist
# 确保histappend开启
# 10. 使用替代方法
# 如果!ls不工作,可以:
history | grep ls | tail -1 | cut -c 8-
# 或使用Ctrl+R搜索
# 问题:历史记录中包含密码、密钥等敏感信息
# 解决方案:清理和防护
# 1. 立即删除最后一条包含敏感信息的命令
# 假设刚刚输入了带密码的命令
history -d $(history 1 | awk '{print $1}')
# 2. 删除指定编号的命令
history | grep -i password
# 查看包含password的命令编号
history -d 编号
# 3. 批量删除包含敏感信息的命令
for i in $(history | grep -i "password\|secret\|key" | awk '{print $1}' | sort -rn); do
history -d $i
done
# 4. 清理历史文件
sed -i '/password/d' ~/.bash_history
sed -i '/secret/d' ~/.bash_history
sed -i '/KEY/d' ~/.bash_history
# 5. 配置HISTIGNORE忽略敏感命令
export HISTIGNORE="*password*:*secret*:*KEY*"
# 添加到~/.bashrc永久生效
# 6. 使用空格开头不记录
# 在命令前加空格(需要HISTCONTROL=ignorespace)
export HISTCONTROL=ignorespace
# 然后: mysql -u root -p密码 # 注意命令前的空格
# 7. 完全禁用当前会话的历史记录
unset HISTFILE
# 或
set +o history
# 8. 使用其他工具处理敏感信息
# 使用ssh-agent管理ssh密钥
# 使用环境变量存储敏感信息
export MYSQL_PASSWORD="秘密"
mysql -u root -p$MYSQL_PASSWORD
# 9. 加密历史文件
# 使用gpg加密历史文件
gpg -c ~/.bash_history
mv ~/.bash_history.gpg ~/.bash_history_encrypted
# 使用时解密
# 10. 定期清理历史
# 创建清理脚本
cat > ~/clean_history.sh << 'EOF'
#!/bin/bash
# 清理包含敏感信息的命令
sed -i '/password/d' ~/.bash_history
sed -i '/secret/d' ~/.bash_history
sed -i '/-p /d' ~/.bash_history
history -c
history -r
EOF
chmod +x ~/clean_history.sh
# 问题:历史记录文件过大导致性能下降
# 原因:历史记录过多或命令过长
# 解决方案:
# 1. 限制历史记录大小
export HISTSIZE=1000 # 内存中保存1000条
export HISTFILESIZE=2000 # 文件中保存2000条
# 2. 清理过大的历史文件
truncate -s 1M ~/.bash_history # 限制为1MB
# 或保留最后N行
tail -1000 ~/.bash_history > ~/.bash_history.tmp
mv ~/.bash_history.tmp ~/.bash_history
# 3. 忽略不必要的命令
export HISTIGNORE="ls:cd:pwd:clear:history:* --help"
# 4. 删除超长命令
# 查找并删除超过200字符的命令
awk 'length($0) < 200' ~/.bash_history > ~/.bash_history.tmp
mv ~/.bash_history.tmp ~/.bash_history
# 5. 压缩历史文件
gzip ~/.bash_history
# 使用时:zcat ~/.bash_history.gz | grep keyword
# 6. 分割历史文件
# 按月分割
cp ~/.bash_history ~/.bash_history.$(date +%Y%m)
> ~/.bash_history
# 7. 使用数据库存储历史(高级)
# 使用SQLite存储历史记录
# 需要自定义脚本
# 8. 优化HISTTIMEFORMAT
# 简单的时间格式减少文件大小
export HISTTIMEFORMAT="%Y%m%d "
# 9. 定期维护脚本
cat > /usr/local/bin/optimize_history << 'EOF'
#!/bin/bash
# 优化历史文件
MAX_SIZE=1048576 # 1MB
HIST_FILE="$HOME/.bash_history"
if [ -f "$HIST_FILE" ]; then
SIZE=$(stat -c%s "$HIST_FILE")
if [ "$SIZE" -gt "$MAX_SIZE" ]; then
echo "历史文件过大 ($SIZE 字节),正在优化..."
# 保留最后5000行
tail -5000 "$HIST_FILE" > "${HIST_FILE}.tmp"
mv "${HIST_FILE}.tmp" "$HIST_FILE"
echo "优化完成,当前大小: $(stat -c%s "$HIST_FILE") 字节"
fi
fi
EOF
chmod +x /usr/local/bin/optimize_history
# 10. 禁用历史记录(极端情况)
# 如果确实不需要历史记录
unset HISTFILE
# 或
export HISTSIZE=0
export HISTFILESIZE=0
history - 查看所有历史history 10 - 查看最近10条history | grep str - 搜索历史history -c - 清除历史!! - 上一条命令!100 - 第100条命令!str - 以str开头的命令!$ - 上条命令的最后一个参数Ctrl+R # 反向搜索历史
Ctrl+P # 上一条命令(同↑)
Ctrl+N # 下一条命令(同↓)
Ctrl+G # 退出搜索
!! # 执行上一条命令
!10 # 执行第10条命令
^old^new # 替换上条命令中的字符串
HISTTIMEFORMAT以便查看命令执行时间HISTCONTROL=ignoreboth忽略重复命令和空格开头的命令Ctrl+R搜索历史,而不是手动翻找!!前确认上一条命令是否安全mysql -p)可能将密码记录在历史中