Shell脚本:将程序的输出重定向到更改文件。

时间:2021-09-21 00:02:37

My goal:

我的目标:

I would like to redirect the stdout output of my program foo to a changing output file depending on the running time of the program.

我想根据程序的运行时间将程序foo的stdout输出重定向到更改的输出文件。

The program foo itself is listening on a bsd socket for arriving packets and displays information contained in them.
So essentially, after running the program foo for 10 minutes, I would like to have the stdout output of

程序foo本身正在监听bsd套接字,以便到达包并显示包中包含的信息。本质上,在运行程序foo 10分钟后,我想要stdout输出

  • the first minute inside the file bar_0.dat
  • 文件bar_0.dat中的第一分钟
  • the second minute inside the file bar_1.dat
  • 文件bar_1.dat中的第二分钟
  • the 10th minute inside the file bar_9.dat
  • 文件里面的第10分钟是bar_9.dat

Is it possible to achieve this in a shell script and if yes, how could I accomplish this?

是否有可能在shell脚本中实现这个目标,如果是,我将如何实现它?

What I have managed so far:

到目前为止,我所管理的:

I only managed this solution, where the program is restarted after each minute with the redirection to a new output file:

我只管理了这个解决方案,在这个解决方案中,程序在每分钟后重新启动,并重定向到一个新的输出文件:

#!/bin/bash
for i in {0..9}
do
  timeout 60s foo > "bar_${i}.dat"
done

However, I want the program foo to be running continuously and not having to restart it, because in the way I have realized it I am loosing some arriving packets (there is a 20-30ms gap between the running instances).

但是,我希望程序foo是连续运行的,而不需要重新启动它,因为我意识到它正在丢失一些到达的包(运行的实例之间有20-30ms的间隔)。

3 个解决方案

#1


1  

If foo is producing text output, you might get away with something like:

如果foo正在生成文本输出,您可能会得到如下内容:

#!/bin/bash

stamp=0
i=0
redirect() {
        if test "$(date +%s)" -gt "$((stamp + 60))"; then
                stamp=$(date +%s)
                exec > "bar_$((i++)).dat"
        fi
}
redirect
./foo | while read line; do
        echo "$line"
        redirect
done

If foo is not producing text output, you'll probably want to write foo so that it accepts an external input (eg, a signal) and redirects output on its own. Or, you might just want to use logrotate.

如果foo不产生文本输出,那么您可能想要编写foo,以便它接受外部输入(例如,一个信号)并自行重定向输出。或者,您可能只想使用logrotate。

#2


2  

Let the program write to a named pipe (fifo) and then take the output from that pipe and put it in files. In the example here, I start the loop in the background and then immediately start writing to the named pipe:

让程序写入一个命名管道(fifo),然后从该管道获取输出并将其放入文件中。在这里的示例中,我在后台启动循环,然后立即开始编写命名管道:

mkfifo thepipe

for (( i = 0; i < 10; ++i )); do
    timeout 60 cat thepipe >"bar_$i.dat"
done &

foo >thepipe
rm -f thepipe

Alternatively, using a process substitution:

或者,使用过程替换:

foo > >( 
    for (( i = 0; i < 10; ++i )); do
        timeout 60 cat >"bar_$i.dat"
    done
)

#3


0  

You could use an infinite loop and date/time stamp for the file name:

您可以对文件名使用无限循环和日期/时间戳:

while true
do
    #This date/time stamp is month_day_hour_minute all numbers
    filename="bar_$(date "+%m_%d_%H_%M").dat"
    foo > $filename 2>> error_log
    sleep 60
done

Also added an error log for any error messages. Not sure how your program is handling stderr.

还为任何错误消息添加了错误日志。不确定你的程序是如何处理stderr的。

#1


1  

If foo is producing text output, you might get away with something like:

如果foo正在生成文本输出,您可能会得到如下内容:

#!/bin/bash

stamp=0
i=0
redirect() {
        if test "$(date +%s)" -gt "$((stamp + 60))"; then
                stamp=$(date +%s)
                exec > "bar_$((i++)).dat"
        fi
}
redirect
./foo | while read line; do
        echo "$line"
        redirect
done

If foo is not producing text output, you'll probably want to write foo so that it accepts an external input (eg, a signal) and redirects output on its own. Or, you might just want to use logrotate.

如果foo不产生文本输出,那么您可能想要编写foo,以便它接受外部输入(例如,一个信号)并自行重定向输出。或者,您可能只想使用logrotate。

#2


2  

Let the program write to a named pipe (fifo) and then take the output from that pipe and put it in files. In the example here, I start the loop in the background and then immediately start writing to the named pipe:

让程序写入一个命名管道(fifo),然后从该管道获取输出并将其放入文件中。在这里的示例中,我在后台启动循环,然后立即开始编写命名管道:

mkfifo thepipe

for (( i = 0; i < 10; ++i )); do
    timeout 60 cat thepipe >"bar_$i.dat"
done &

foo >thepipe
rm -f thepipe

Alternatively, using a process substitution:

或者,使用过程替换:

foo > >( 
    for (( i = 0; i < 10; ++i )); do
        timeout 60 cat >"bar_$i.dat"
    done
)

#3


0  

You could use an infinite loop and date/time stamp for the file name:

您可以对文件名使用无限循环和日期/时间戳:

while true
do
    #This date/time stamp is month_day_hour_minute all numbers
    filename="bar_$(date "+%m_%d_%H_%M").dat"
    foo > $filename 2>> error_log
    sleep 60
done

Also added an error log for any error messages. Not sure how your program is handling stderr.

还为任何错误消息添加了错误日志。不确定你的程序是如何处理stderr的。