Linux 中多终端同步 history 记录
很多文章都是第一时间在语雀进行了更新和发布,公众号的文章只是在语雀平台的基础上进行同步的,而且更新频率也会比语雀要慢。最近弃坑简书,入驻语雀,欢迎阅读原文来语雀一起交流学习。
基本认识
Linux 默认配置是当打开一个 shell 终端后,执行的所有命令均不会写入到~/.bash_history
文件中,只有当前用户退出后才会写入,这期间发生的所有命令其它终端是感知不到的。
问题场景
在网络上看到 2 个问题,有点意思:
假若之前history
命令记录为 c0,用户先打开了 shell 终端 a,执行了一部分命令 c1,又打开了一个 shell 终端 b,又执行了一部分命令 c2。
问题1:终端 a 执行的这部分命令终端 b 上看不到。
问题2:终端 a 正常退出,相关命令会写入到
~/.bash_history
文件中(c1 命令也会写入,即 c0+c1),等到终端 b 正常退出后,相关命令也会写入到~/.bash_history
文件中,注意这个时候终端 b 写入的内容为 c0+c2,也即 c1 记录会丢失!!!
问题 1 的确会出现!
但是问题 2 貌似不会出现,个人在 CentOS 7 中测试了一下,发现终端 a 正常退出,相关命令的确会写入到~/.bash_history
文件中,即 c0+c1;但终端 b 也正常退出后,终端 b 的相关命令是会自动追加到~/.bash_history
文件,这时候~/.bash_history
的文件内容 = c0 + c1 + c2!造成这样的原因,刚开始以为是受/etc/bashrc
的这一段配置的影响,后来把这两句注释,重新测试发现问题 2 貌似也不会出现。
# Turn on parallel history
shopt -s histappend
history -a
如果在多个打开的终端中实时同步 history(例如,如果我 ls 在一个终端中,切换到另一个已经运行的终端,然后按向上,ls
出现)的确也是有一定的使用需求,但真正的需求个人觉得更应该是这样的:
我可以看到多终端实时同步 history 的优点,但是就我个人而言,我会讨厌它。我通常在终端中打开 3 或 4 个选项卡以用于非常特定的用途:一个用于运行 “make”,一个用于 vi,一个用于运行东西,等等。因此,当我编译时,我转到选项卡 1,单击并显示 “make”。依此类推。这对我非常有帮助。因此,如果突然我进入我的 “make” 选项卡并点击弹出,并且出现一些随机的 grep 命令,我会很生气!
所以,我们增加一个问题 3:当打开一个 shell 终端后,不管是正常退出还是非正常退出,执行的所有命令均实时追加到~/.bash_history
文件中,但当前终端不会实时同步其他终端的 history,除非我重新开启了一个新终端。
解决方案
问题一:实时同步多个终端的 history 记录。
# Avoid duplicates
export HISTCONTROL=ignoredups:erasedups
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend
# After each command, append to the history file and reread it
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
问题二:多个终端执行的所有命令均实时追加到~/.bash_history
文件中。
shopt -s histappend
PROMPT_COMMAND="history -a"
参数解析
贴上一些 history 的参数解析。

history [n]
history -c
history -d offset
history -anrw [filename]
history -p arg [arg ...]
history -s arg [arg ...]
With no options, display the command history list with line numbers. Lines listed with a *
have been modified. An argument of n lists only the last n lines. If the shell variable
HISTTIMEFORMAT is set and not null, it is used as a format string for strftime(3) to display
the time stamp associated with each displayed history entry. No intervening blank is printed
between the formatted time stamp and the history line. If filename is supplied, it is used
as the name of the history file; if not, the value of HISTFILE is used. Options, if sup‐
plied, have the following meanings:
-c Clear the history list by deleting all the entries.
-d offset
Delete the history entry at position offset.
-a Append the ``new'' history lines (history lines entered since the beginning of the
current bash session) to the history file.
-n Read the history lines not already read from the history file into the current history
list. These are lines appended to the history file since the beginning of the current
bash session.
-r Read the contents of the history file and use them as the current history.
-w Write the current history to the history file, overwriting the history file's con‐
tents.
-p Perform history substitution on the following args and display the result on the stan‐
dard output. Does not store the results in the history list. Each arg must be quoted
to disable normal history expansion.
-s Store the args in the history list as a single entry. The last command in the history
list is removed before the args are added.
If the HISTTIMEFORMAT variable is set, the time stamp information associated with each his‐
tory entry is written to the history file, marked with the history comment character. When
the history file is read, lines beginning with the history comment character followed immedi‐
ately by a digit are interpreted as timestamps for the previous history line. The return
value is 0 unless an invalid option is encountered, an error occurs while reading or writing
the history file, an invalid offset is supplied as an argument to -d, or the history expan‐
sion supplied as an argument to -p fails.
常用配置
1. 设置历史记录的时间
HISTTIMEFORMAT
主要用户 history 的格式定义。
export HISTTIMEFORMAT='%F %T ' # 注意有个空格, 这样在显示时日期与命令之间会有空格分隔
HISTTIMEFORMAT %F %T 代表意义:
%F – expands to full date same, as %Y-%m-%d (year-month-date).
%T – expands to time; same as %H:%M:%S (hour:minute:seconds).
2. 控制历史命令记录的总个数
关于HISTFILESIZE
和HISTSIZE
,简单说明一下。
export HISTSIZE=1000 # 设置内存中的 history 命令的个数
export HISTFILESIZE=1000 # 设置文件中的 history 命令的个数
HISTFILESIZE:定义了在
.bash_history
中保存命令的记录总数,可以理解为.bash_history
文件中最多只有 HISTFILESIZE 行。默认值是 500。HISTSIZE:定义了
history
命令输出的记录数,即输出.bash_history
文件中的最后 HISTSIZE 行。默认值是 500。
3. 更换历史命令的存储位置
一般情况下,历史命令会被存储在~/.bash_history
文件中。如果不想存储在这个文件中,而想存储在其他文件中,那么可以通过下面的方式来更改:
export HISTFILE=~/history.log
4. 其他个性化的配置
附上一些HISTCONTROL
的常用设置。
export HISTCONTROL=erasedups # 清除整个命令历史中的重复条目
export HISTCONTROL=ignoredups # 忽略记录命令历史中连续重复的命令
export HISTCONTROL=ignorespace # 忽略记录空格开始的命令
export HISTCONTROL=ignoreboth # 等价于ignoredups和ignorespace
尊重重要命令的隐私
以下内容节选自:编程帮《history 命令 Linux history 命令:查看和执行历史命令》。
试想一下,我们操作 Linux 系统,如果把所有的命令都记录到 .bash_history 中,会不会有风险呢?
当然有风险啦,如果哪一天我们不幸中招,黑客攻入了我们的系统,他只要查看一下 history 就能知道我们的很多秘密,比如一些登录密码。为了避免该类事情的发生,我们希望 history 不要显示含有隐私信息的历史命令,只显示不含有隐私信息的命令。这个需求太个性化,但 history 仍然能够实现,下面我们就为大家介绍两种行之有效的解决方案。
第一种靠谱的解决方案:
第1步:设置 HISTCONTROL 环境变量:export HISTCONTROL=ignorespace。
第2步:输入重要命令时,记得在输入命令前加上空格。
第3步:执行 history,可以看到刚输入的重要命令没有出现在 history 中。
通过设置 HISTCONTROL=ignorespace,可以让 history 不记录你的特殊输入(命令前加空格),这样可以在一定程度上有效地保护我们的系统。
第二种靠谱的解决方案:
第1步:设置 HISTIGNORE 环境变量 export HISTIGNORE=*。
第2步:输入重要命令,比如 mysql-uroot-p123。
第3步:查看你的 history,可以看到刚输入的 mysql 命令没有记录在 history 中。
第4步:恢复命令的记录 export HISTIGNORE=。
第4步后,系统又恢复正常,输入的命令又能被正常记录了。
这个方法虽然略显烦琐,需要你每次在输入重要命令时都要先设置 HISTIGNORE=*,执行完命令后再设置 HISTIGNORE=,但是,这种方法能规避由于你的粗心大意(忘记命令前加空格)带来的巨大安全隐患,确保机密信息不会被泄露出去。
END
猜您喜欢
往期精选▼
本文分享自微信公众号 - 生信科技爱好者(bioitee)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
Linux 中多终端同步 history 记录的更多相关文章
- Linux中的终端、控制台、tty、pty等概念
参考:http://news.newhua.com/news1/program_language/2010/623/10623141048745773199BCF0CFH6AKB9930IGCFKHB ...
- (笔记)Linux中的终端、控制台、tty、pty
1>tty(终端设备的统称): tty一词源于teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘阅读和发送信息的东西,后来这东西被键盘与显示器 ...
- Linux中让终端输入变为非阻塞的三种方法
介绍 在linux下每打开一个终端,系统自动的就打开了三个文件,它们的文件描述符分别为0,1,2,功能分别是"标准输入"."标准输出"和"标准错误输出 ...
- linux中的磁盘的MBR记录详解
在硬盘中,硬盘的0柱面0磁头第一个1扇区称为主引导扇区,也叫主引导记录-MBR(main boot record),其中MBR是以下三个部分组成 1.Bootloader,主引导程序---446个字节 ...
- linux中VI编辑器使用个人记录
VI编辑器有三种编辑模式:命令模式.最后行模式.文本编辑模式 启动VI后进入的第一种模式是”命令模式“.从命令模式可进入最后行模式和编辑模式.而后两种模式之间不能直接切换.必须按ESC键退回到命令模式 ...
- linux中ftp的安装过程记录[运维篇]
安装FTP的全过程记录,对于相同情况希望有所帮助.[centOS] 1.查询本机是否安装vsftpd: rpm -qa |grep vsftpd : 2.安装ftp服务 yum install vsf ...
- 在linux中使用终端浏览器w3m
w3m是一个基于文本的网页浏览器,支持多种操作系统,在命令行终端可以很好的支持中文.即使在没有鼠标支持的情况下也可以检查网页的输出. 1. 安装w3m $ sudo apt install w3m 2 ...
- linux中的线程同步:生产者、消费者问题
#include <stdio.h> #include <semaphore.h> #include <unistd.h> #include <stdlib. ...
- linux日志服务器审计客户端history记录
https://blog.csdn.net/yanggd1987/article/details/70255179
- Linux 的伪终端的基本原理 及其在远程登录(SSH,telnet等)中的应用
本文介绍了linux中伪终端的创建,介绍了终端的回显.行缓存.控制字符等特性,并在此基础上解释和模拟了telnet.SSH开启远程会话的过程. 一.轻量级远程登录 之前制作的一块嵌入式板子,安装了嵌入 ...
随机推荐
- 【转载】vue3 中如何像 vue2 的 extend 一样挂载未挂载的组件,拿到标签本身($el)
原文地址:https://blog.csdn.net/qq_39953537/article/details/110437554 vue3 中如何像 vue2 的 extend 一样挂载未挂载的组件, ...
- java创建线程的方式有几种?
java中创建线程的方式有多少种,这个问题也是众多纷纭,这个时候更应该参考官方文档(https://docs.oracle.com/javase/8/docs/api/java/lang/Thread ...
- 浅谈$\mathcal{LCT}$初步使用及具体操作
\(0x01\) 闲话 · \(LCT\)的用途以及具体思路 \(LCT\)是啥?百度一下的话--貌似是一种检查妇科病的东西?Oier的口味可是真不一般啊 咳,其实在我最近只是浅浅地学了一部分的基础上 ...
- sqlite4操作
目录 SQLite数据库(一):基本操作... 1 目录... 1 一.SQLite介绍... 2 1. 什么是SQLite. 2 2. 什么是数据库... 2 3. 数据库是如何存 ...
- 多态、抽象、Object类
1.方法重写要求:方法名相同.参数类型相同.返回值相同或其子类返回值相同,子类修饰符要不小于父类 2.方法重载要求:方法名相同.参数类型不同.返回值没有改变.修饰符无关 3.多态的前提是继承.多态是定 ...
- 安全测试前置实践1-白盒&黑盒扫描
作者:京东物流 陈维 一.引言 G.J.Myers在<软件测试的艺术>中提出:从心理学角度来说,测试是一个为了寻找错误而运行程序的过程. 那么安全测试则是一个寻找系统潜在安全问题的过程,通 ...
- 从桌面和应用内 Activity的启动流程
1.APP还没有被打开过从桌面启动 <1>首先桌面进程会像AMS服务发送startActivity的请求,AMS从system_service中去拿----一次IPC通信 <2> ...
- OpenCv人脸检测技术-(实现抖音特效-给人脸戴上墨镜)
OpenCv人脸检测技术-(实现抖音特效-给人脸戴上墨镜) 本文章用的是Python库里的OpenCv. OpenCv相关函数说明 import cv2 # 导入OpenCv库 cv2.imread( ...
- Object o = new Object();
对象的创建过程: 1,申请内存,并初始化: 2,构造器初始化: 3,o指向对象. 对象在内存中的存储布局: 使用jol工具打印java对象在内存的存储布局: 其中,对象头的组成: 对象头包括Mark ...
- 【干货】Vue2.x 组件通信方式详解,这篇讲全了
前言 vue是数据驱动视图更新的框架, 我们平时开发,都会把页面不同模块拆分成一个一个vue组件, 所以对于vue来说组件间的数据通信非常重要,那么组件之间如何进行数据通信的呢? 首先我们需要知道在v ...