是否有工具可根据要求将输出动态重定向到新文件


8

我目前正在将监视工具的输出重定向到文件,但是,我想做的是根据我的请求(使用键绑定)将该输出重定向到新文件,而无需停止所说的工具。

就像是

monitor_program | handle_stdout

在哪里handle_stdout,我可以定义一个新文件,将日志放在特定位置。

我知道我可以轻松编写它,但是我想知道是否已经有工具允许这样做。


您可能可以logrotate手动运行带有自定义配置文件的文件,具体取决于monitor_program的行为,但这有点黑。
乌尔里希·施瓦茨

看来您的编辑实际上是对问题的解答。在这种情况下,请将其发布为答案(鼓励自助答案!),然后从问题中删除答案。

Answers:


9

我建议一个命名管道。

  1. 创建管道mkfifo p(任意调用,如果不是“ p”,则调用它)

  2. 创建一个“读取器”脚本,该脚本从管道读取并在您喜欢的任何地方写入

  3. 告诉监视程序将其日志写入命名管道

这是一个示例读取器脚本,该脚本从命名管道“ p”读取并将数据写入索引的“ mylog”文件:

#!/bin/sh

INDEX=0

switchlog() {
  read INDEX < newindex
  echo now writing to "mylog.$INDEX"
}

trap switchlog USR1

while :
do
  cat p >> mylog."$INDEX"
done

2
您还可以在阅读器脚本中捕获一个信号(例如USR1)作为切换日志的信号。
杰夫·谢勒

这开始是我需要的东西。但是阅读器脚本应该能够基于我的kebinding更改输出。并有可能问我要一个新的文件名(尽管这是可选的,甚至有连续的日志名称将被罚款)
特维诺

我编辑了示例脚本,以显示使用kill -USR1进行日志切换的示例。在“ newindex”文件中回显一个新数字,以供提取。
杰夫·谢勒

1
只是另一个想法-如果您为正在运行的“阅读器”脚本打开一个窗口,则可以捕获“ INT”而不是USR1,只需在该窗口中按Control-C即可通知它新的日志文件名。
杰夫·谢勒

1
为什么readprintf而不仅仅是cat <p >> mylog."$INDEX"
通配符

7

建立在您的SIGINT想法的基础上,在这里使用SIGQUIT(Ctrl+\)仍然Ctrl+C可以停止整个事情:

(trap '' QUIT; monitor_command) | (
   trap : QUIT
   ulimit -c 0 # prevent core dump so SIGQUIT behaves like SIGINT
               # for cat
   n=0; while n=$((n+1)); file=output.$n.log; do
     printf 'Outputting to "%s"\n' "$file"
     cat > "$file"
   done)

假定cat外壳中没有内置的东西(因此按确实会打断它Ctrl+\)。

请注意,就像您的方法一样,SIGQUIT有可能在错误的时间(在写入系统调用中)交付,从而导致某些数据丢失。


1

您可能可以less通过键入s要保存到的文件名,然后从那里使用并保存Enter。从我怎样写都行从少到一个文件?


不幸的是,不可能再使用更多的日志文件,一旦您设置了一个日志文件,便无法重新定义一个新的日志文件。同样,一旦完成,您将无法清除日志。所以...很好的起点(谢谢),但还不够。
特维诺

0

如果不了解您的“请求”,就不可能回答。如果基于文件大小或间隔,则可以使用rotatelogs(应该与Apache httpd捆绑在一起)。


抱歉,我没有明确地说,我假设是一个允许更改日志名称的键绑定。
特维诺

0

多亏了Jeff Schaller的回答,我最终得到了这样的东西,基本上可以满足我的需要,我们称之为reader.sh

#!/bin/sh

INDEX=0
LOGNAME="$INDEX.log"

switchlog() {
  local custom_name
  read -p "Add log name: " custom_name
  INDEX=$((INDEX+1))
  LOGNAME="$(printf "%03d" $INDEX).$custom_name.log"
  echo now writing to $LOGNAME
}

trap switchlog INT
switchlog

while :
do
  read foo < p
  printf "%s\n" "$foo" >> "$LOGNAME"
done

然后,仅需使用创建一个命名管道mkfifo p,并在monitor_program > preader.sh运行两个终端上使用它们即可。然后,我可以使用Ctrl+ 停止阅读器设置新日志C,然后输入新名称。Ctrl+ Z,然后照常停止并杀死它。

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.