bash脚本中的历史记录命令


20

历史是Shell内置命令,我无法在BASH脚本中使用它。那么,有没有一种方法可以使用BASH脚本来实现?
在这里,我们为您准备了我的脚本:

#!/bin/bash
history |  tail -100 > /tmp/history.log
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com

Answers:


32

Bash默认情况下会禁用非交互式Shell中的历史记录,但是您可以将其打开。

#!/bin/bash
HISTFILE=~/.bash_history
set -o history
history | tail 

但是,如果您要监视该服务器上的活动,则shell历史记录是无用的(运行历史记录中未显示的命令很简单)。请参阅如何在Linux中记录所有进程启动

如果您要调试脚本,则shell历史记录不是获取有用信息的最佳方法。更好的工具是调试跟踪工具:放在set -x脚本顶部附近。跟踪被写入标准错误。


这拒绝在脚本中工作:histtest.sh: 5: set: Illegal option -o history
肯·夏普

4
@KenSharp那是因为您试图在sh脚本中使用它(并且sh错误消息的确切措辞使您破晓不绝)。要访问bash的历史记录,您需要使用bash(以#!/bin/bash或开头的脚本#!/usr/bin/env bash)。
吉尔(Gilles)'所以

1
@KenSharp是的。给定错误消息,您显然在破折号下运行了它。Bash没有错误消息Illegal option(会显示set: history: invalid option name)。
吉尔斯(Gilles)'所以别再邪恶了'

与此问题是,它增加了所有的命令之后set -o history 的历史则其将要与像条目鼻塞if [... vars=$(...
纳特

1
@nath就是这个问题的要求。我指出,这几乎没有意义。监视活动是shell历史无法解决的难题。如果您要调试脚本,那么set -x它会有用得多。
吉尔斯(Gillles)“所以-不再是邪恶的人”

6

我不确定在非交互运行时它是否实际上使用了历史记录功能,否则运行的每个shell脚本都会使命令历史记录混乱。

为什么不直接进入源代码${HOME}/.bash_history,而替换history | tail -100tail -100 ${HOME}/.bash_history。(如果您使用时间戳记,则可能必须按照进行操作grep -v ^# ${HOME}/.bash_history | tail -100)。


确实,有了时间戳记,您实际上应该greq -v '^#[0-9]\+$'(我有时会在外壳中“执行”评论...)
PlasmaBinturong

实际上,就我而言,我需要使用正确的历史记录行号,但是方法history的输出与grep方法的输出之间存在差异……
PlasmaBinturong

好的,解决方法是将历史记录列表与历史记录文件进行同步,如下所示:history -a; history -c; history -r。(添加,清除,阅读)
PlasmaBinturong

2

如果要history在脚本中使用活动外壳程序会话中命令的输出,可以先使用别名来运行命令。然后,以相同的别名,您可以调用脚本的其余部分。通过这样的配置,您可以获得与history在实际脚本中包含命令基本相同的结果。

例如,您可以创建这样的别名,假设脚本的名称为script.sh:

alias hy_tmp='history | tail -100 > /tmp/history.log ; bash /patch/to/script.sh'

并将脚本更改为此:

#!/bin/bash
cd /tmp
uuencode history.log history.txt  | mail -s "History log of server" hello@hel.com

我在编写将~/bash_history两台计算机上的文件进行组合,排序和同步的过程时发现了这个问题,因此可以轻松搜索我过去使用的命令。

更新我的累积历史记录文件而不必登录到新的Shell进行~/bash_history更新就省去了很多麻烦。如其他答案中所述,对于监视服务器,这显然不起作用。

我的用法尤其是:

alias hbye='history | cut -c 8- > /home/chris/.bash_history_c; bash /hby.sh

然后,脚本hby.sh从所有~/.bash_history*文件中提取所有唯一条目。



1

创建一个script.sh如下所示的脚本。它创建一个名为X的脚本,并将Y的历史行数放入其中。

#!/bin/bash
SCRIPT_NAME=$1
NUMBER_OF_LINES_BACK=$2

# Enable History in a non interactive shell
HISTFILE=~/.bash_history
set -o history

# echo shabang line and x number of lines of history to new script
echo \#\!\/bin\/bash > $SCRIPT_NAME.sh; history | tail -n $NUMBER_OF_LINES_BACK >> $SCRIPT_NAME.sh;
chmod u+x $SCRIPT_NAME.sh;

# Open the newly created script with vim
vim $SCRIPT_NAME.sh;
~

然后,如果您想创建一个脚本来完成名为“任务”的任务,而该任务在最近的14行运行中一直在进行

script.sh task 14

然后整理您的历史记录,制作出精美的脚本!


histtest.sh: 5: set: Illegal option -o history
肯·夏普

1

默认情况下,bash脚本上的history命令是禁用的,这就是为什么连history命令都无法在.sh文件中工作的原因。对于其重定向,请在.sh文件中重定向bas​​h_history文件。

也可以通过提及历史记录文件并更改运行时参数来启用历史记录机制,如下所述

#!/bin/bash
HISTFILE=~/.bash_history
set -o history 

注意:上面提到的脚本文件顶部的两行。现在历史记录命令将在历史记录中起作用。


0

每个用户都有自己的历史文件,这是由history命令产生的结果。您可以在用户的​​外壳文件中使用history文件来代替在外壳程序脚本中使用history命令。.bash_history用户的主目录中将有一个文件,该文件将是用户的历史文件。


-1

简短答案

用于history -p显式执行历史记录扩展。

下面是一个示例。

我经常遇到的一种用例是:

  • 上一个命令获取文件名列表,并打印到stdout,
  • 我需要用vim编辑这些文件。

由于我的bash已经 set -o histexpand,通常我所做的就是输入

vim $(!!)

编辑上一个命令列出的文件。

遗憾的是有时会发生错误,因此我启用了验证shopt -s histverify

现在,我可以验证扩展了,但要多花一分钱 Return密钥。

今天,由于我经常使用这些细节,因此我想将这些细节包装到bash函数中,

function vk() {
    set -o history && set -o histexpand;
    vim -i ~/.viminfok $($(history -p !!));
}

在这里,我使用了两个nested command substitution,内部的一个扩展!!为上一个命令,外部的一个执行它并获取输出。

现在,我只需三个键就可以达到相同的效果,其中之一就是Return

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.