从脚本获取最后执行的命令

时间:2014-06-14 20:04:58

标签: bash shell ksh

我试图从脚本的命令行中获取最后一个执行的命令,以备日后参考:

示例:

# echo "Hello World!!!"
> Hello World!!!
# my_script.sh
> echo "Hello World!!!"

并且脚本的内容为:

#!/usr/bin/ksh

fc -nl -1 | sed -n 1p

现在你注意到使用kshfc是一个内置命令,如果正确理解应该由任何POSIX兼容的shell实现。 [我知道这个功能是互动的,再次调用同一个fc会产生不同的结果,但这不是关于讨论的问题]

上述作品到目前为止只有在从my_script.sh调用ksh时调用bash,或者从#!/bin/bash调用并将第1行脚本更改为{{ 1}}然后它也可以工作,如果外壳不同,它也不会。

我想知道是否有任何好方法可以实现上述目标而不受shell调用脚本的限制。我知道fc是一个内置命令,它适用于每个shell,因此我的方法很可能完全不是我希望实现的。有更好的建议吗?

3 个答案:

答案 0 :(得分:4)

我实际上尝试了这一点,但不能在不同的shell之间进行一致。

虽然 fc -l`, 是用于显示$ SHELL历史的POSIX标准命令,实现细节可能不同。

至少 bash ksh93 都将使用

报告最后一个命令
fc -n -l -1 -1

但是,POSIX不保证shell历史记录会被转移到shell的新实例,因为这需要$HISTFILE的存在。如果没有 目前,shell可能默认为$HOME/.sh_history

但是,此历史记录文件或命令历史记录列表在不同的shell之间不可移植。

POSIX Shell的描述 Command History List说:

  

当以交互方式使用sh实用程序时,它应保留一个命令列表   先前从HISTFILE环境命名的文件中的终端输入   变量。 此文件的类型,大小和内部格式未指定

强调我的

这意味着您的脚本需要知道哪个shell写了该历史记录。

我尝试使用$SHELL -c 'fc -nl -1 -1',但是当$ SHELL引用bash时,这似乎不起作用。从bash调用ksh -c ...实际上有效。

我能让这个工作的唯一方法是创建一个函数。

last_command() { (fc -n -l -1 -1); }

在ksh bash中,这将给出预期的结果。可以使用此函数的变体将结果写入其他位置。但是,无论什么时候打电话都会打破 来自与当前不同的过程。

您可以做的最好的事情就是创建这些功能并将它们输入您的 交互式shell。

答案 1 :(得分:0)

fc旨在以交互方式使用。我在cygwin / bash上测试了你的例子,结果不同了。即使在任何地方使用bash,fc命令在我的情况下都不起作用。

我认为fc会显示当前shell的最后一个命令(这里我不是说shell解释器,而是shell作为“处理盒”。所以问题更多的是它为什么适合你。

我认为没有一种干净的方法来实现你想要的东西,因为(也许我想念一些东西)你想要两个不同的过程(bash和你的魔法命令[my_script.sh]),默认情况下OS确保它们之间的隔离

你可以依靠你观察到的东西(不可移植,取决于shell解释器等)。

您不能依赖BASH历史记录,因为它在内存中(文件仅在退出时更新)。

您可以使用别名或功能(编辑:@Charles Duffy是对的)。在这种情况下,您将无法使用来自其他终端的“魔术命令”,但对于交互式使用,它可以完成这项工作。

编辑: 或者您可以提供两个命令:一个用于保存,另一个用于查找。在这种情况下,你管理自己的历史,但你必须明确保存每个令人痛苦的命令......

所以我寻找一个钩子。我找到了另一个帖子:https://superuser.com/questions/175799/does-bash-have-a-hook-that-is-run-before-executing-a-command

# At the beginning of the Shell (.bashrc for example) 
save(){ history 1 >>"$HOME"/myHistory ; }
trap 'save' DEBUG
# An example of use
rm -f "$HOME"/myHistory
echo "1 2  3"
cat "$HOME"/myHistory
    14  echo "1 2  3"
    15  cat "$HOME"/myHistory

但是我发现它减慢了解释者的速度......

答案 2 :(得分:0)

有点费解,但我能够使用此命令在Linux上的zsh,bash,ksh和tcsh中获取最新命令:

history | tail -2 | head -1 | sed -r 's/^[ \t]*[0-9]*[ \t]+([^ \t].*$)/\1/'

警告:这使用GNU sed,因此如果你使用BSD,OS X等,你需要安装它;而且,tcsh将在命令本身之前显示命令的时间。我尝试时,常规csh似乎没有正常运行的history命令。