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

时间:2022-11-15 21:44:21

Edit: This question was originally bash specific. I'd still rather have a bash solution, but if there's a good way to do this in another shell then that would be useful to know as well!

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

Okay, top level description of the problem. I would like to be able to add a hook to bash such that, when a user enters, for example $cat foo | sort -n | less, this is intercepted and translated into wrapper 'cat foo | sort -n | less'. I've seen ways to run commands before and after each command (using DEBUG traps or PROMPT_COMMAND or similar), but nothing about how to intercept each command and allow it to be handled by another process. Is there a way to do this?

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

For an explanation of why I'd like to do this, in case people have other suggestions of ways to approach it:

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

Tools like script let you log everything you do in a terminal to a log (as, to an extent, does bash history). However, they don't do it very well - script mixes input with output into one big string and gets confused with applications such as vi which take over the screen, history only gives you the raw commands being typed in, and neither of them work well if you have commands being entered into multiple terminals at the same time. What I would like to do is capture much richer information - as an example, the command, the time it executed, the time it completed, the exit status, the first few lines of stdin and stdout. I'd also prefer to send this to a listening daemon somewhere which could happily multiplex multiple terminals. The easy way to do this is to pass the command to another program which can exec a shell to handle the command as a subprocess whilst getting handles to stdin, stdout, exit status etc. One could write a shell to do this, but you'd lose much of the functionality already in bash, which would be annoying.

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

The motivation for this comes from trying to make sense of exploratory data analysis like procedures after the fact. With richer information like this, it would be possible to generate decent reporting on what happened, squashing multiple invocations of one command into one where the first few gave non-zero exits, asking where files came from by searching for everything that touched the file, etc etc.

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

2 个解决方案

#1


1  

Run this bash script:

运行此bash脚本:

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

In its simplest form, wrapper could consist of eval "$LINE". You mentioned wanting to have timings, so maybe instead have time eval "$line". You wanted to capture exit status, so this should be followed by the line save=$?. And, you wanted to capture the first few lines of stdout, so some redirecting is in order. And so on.

在最简单的形式中,包装器可以包含eval“$ LINE”。你提到想要有时间,所以也许有时间评估“$ line”。你想捕获退出状态,所以这应该是行save = $?。而且,你想捕获stdout的前几行,所以一些重定向是有序的。等等。

MORE: Jo So suggests that handling for multiple-line bash commands be included. In its simplest form, if eval returns with "syntax error: unexpected end of file", then you want to prompt for another line of input before proceeding. Better yet, to check for proper bash commands, run bash -n <<<"$line" before you do the eval. If bash -n reports the end-of-line error, then prompt for more input to add to `$line'. And so on.

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

#2


0  

Binfmt_misc comes to mind. The Linux kernel has a capability to allow arbitrary executable file formats to be recognized and passed to user application.

想到Binfmt_misc。 Linux内核能够识别任意可执行文件格式并将其传递给用户应用程序。

You could use this capability to register your wrapper but instead of handling arbitrary executable, it should handle all executable.

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

#1


1  

Run this bash script:

运行此bash脚本:

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

In its simplest form, wrapper could consist of eval "$LINE". You mentioned wanting to have timings, so maybe instead have time eval "$line". You wanted to capture exit status, so this should be followed by the line save=$?. And, you wanted to capture the first few lines of stdout, so some redirecting is in order. And so on.

在最简单的形式中,包装器可以包含eval“$ LINE”。你提到想要有时间,所以也许有时间评估“$ line”。你想捕获退出状态,所以这应该是行save = $?。而且,你想捕获stdout的前几行,所以一些重定向是有序的。等等。

MORE: Jo So suggests that handling for multiple-line bash commands be included. In its simplest form, if eval returns with "syntax error: unexpected end of file", then you want to prompt for another line of input before proceeding. Better yet, to check for proper bash commands, run bash -n <<<"$line" before you do the eval. If bash -n reports the end-of-line error, then prompt for more input to add to `$line'. And so on.

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

#2


0  

Binfmt_misc comes to mind. The Linux kernel has a capability to allow arbitrary executable file formats to be recognized and passed to user application.

想到Binfmt_misc。 Linux内核能够识别任意可执行文件格式并将其传递给用户应用程序。

You could use this capability to register your wrapper but instead of handling arbitrary executable, it should handle all executable.

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