Bash(或其他shell):用函数/脚本包装所有命令

时间:2013-12-11 16:50:32

标签: linux bash shell zsh fish

编辑:这个问题最初是针对特定的。我仍然宁愿有一个bash解决方案,但如果有一个很好的方法在另一个shell中执行此操作,那么这也是有用的知识!

好的,问题的顶级描述。我希望能够为bash添加一个钩子,以便当用户输入时,例如$cat foo | sort -n | less,这被拦截并转换为wrapper 'cat foo | sort -n | less'。我已经看到了在每个命令之前和之后运行命令的方法(使用DEBUG陷阱或PROMPT_COMMAND或类似命令),但没有关于如何拦截每个命令并允许它由另一个进程处理的方法。有没有办法做到这一点?

为了解释为什么我愿意这样做,以防人们有其他方法来处理它:

script这样的工具可以让您将终端中的所有内容记录到日志中(在某种程度上,可以记录bash历史记录)。然而,他们做得不是很好 - 脚本将输入与输出混合成一个大字符串,并与诸如vi等接管屏幕的应用程序混淆,历史记录只给出输入的原始命令,并且它们都不起作用好吧,如果您同时输入多个终端的命令。我想要做的是捕获更丰富的信息 - 例如,命令,执行的时间,完成的时间,退出状态,stdin和stdout的前几行。我也更喜欢将它发送到一个可以愉快地复用多个终端的监听守护进程。执行此操作的简单方法是将命令传递给另一个程序,该程序可以执行shell以处理作为子进程的命令,同时获取stdin,stdout,退出状态等的句柄。可以写一个shell来执行此操作,但是你' d失去了bash中的大部分功能,这会很烦人。

这样做的动机来自于试图理解事后的程序之类的探索性数据分析。有了这样更丰富的信息,就可以生成关于发生的事情的正确报告,将一个命令的多个调用压缩到一个命令,其中前几个命令给出非零退出,通过搜索触及文件的所有内容询问文件来自何处,等等。

2 个答案:

答案 0 :(得分:2)

运行此bash脚本:

#!/bin/bash
while read -e line
do
    wrapper "$line"
done

最简单的形式是wrapper可以由eval "$LINE"组成。你提到想要有时间,所以也许有time eval "$line"。您想捕获退出状态,因此应该跟在行save=$?之后。而且,你想捕获stdout的前几行,所以有些重定向是有序的。等等。

更多:Jo So建议包含对多行bash命令的处理。在最简单的形式中,如果eval返回“语法错误:意外的文件结束”,那么您需要在继续之前提示输入另一行。更好的是,要检查正确的bash命令,请在执行bash -n <<<"$line"之前运行eval。如果bash -n报告行尾错误,则提示输入更多内容以添加到“$ line”。等等。

答案 1 :(得分:0)

Binfmt_misc浮现在脑海中。 Linux内核能够识别任意可执行文件格式并将其传递给用户应用程序。

您可以使用此功能注册您的包装器,但它不应处理任意可执行文件,而应处理所有可执行文件。