Shell 脚本:将程序输出重定向到更改文件
Shell script: Redirect output of program to changing files
我的目标:
我想根据程序的 运行 时间将程序 foo
的 stdout
输出重定向到一个不断变化的输出文件。
程序 foo
本身正在监听 bsd 套接字以获取到达的数据包并显示其中包含的信息。
所以基本上,在 运行 程序 foo
10 分钟后,我想要
的 stdout
输出
- 文件中的第一分钟
bar_0.dat
- 文件内第二分钟
bar_1.dat
- …
- 文件第10分钟
bar_9.dat
是否可以在 shell 脚本中实现此目的?如果可以,我该如何实现?
我目前管理的内容:
我只管理了这个解决方案,程序在每分钟后重新启动并重定向到新的输出文件:
#!/bin/bash
for i in {0..9}
do
timeout 60s foo > "bar_${i}.dat"
done
但是,我希望程序 foo
连续 运行 而不必重新启动它,因为按照我所意识到的方式,我丢失了一些到达的数据包(有一个 20 运行 个实例之间的 -30 毫秒间隔)。
如果 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
如果 foo 没有产生文本输出,您可能想要编写 foo 以便它接受外部输入(例如,信号)并自行重定向输出。或者,您可能只想使用 logrotate。
您可以使用无限循环和 date/time 标记文件名:
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
还为任何错误消息添加了错误日志。不确定您的程序如何处理 stderr
.
让程序写入命名管道 (fifo),然后从该管道获取输出并将其放入文件中。在这里的示例中,我在后台启动循环,然后立即开始写入命名管道:
mkfifo thepipe
for (( i = 0; i < 10; ++i )); do
timeout 60 cat thepipe >"bar_$i.dat"
done &
foo >thepipe
rm -f thepipe
或者,使用进程替换:
foo > >(
for (( i = 0; i < 10; ++i )); do
timeout 60 cat >"bar_$i.dat"
done
)
我的目标:
我想根据程序的 运行 时间将程序 foo
的 stdout
输出重定向到一个不断变化的输出文件。
程序 foo
本身正在监听 bsd 套接字以获取到达的数据包并显示其中包含的信息。
所以基本上,在 运行 程序 foo
10 分钟后,我想要
stdout
输出
- 文件中的第一分钟
bar_0.dat
- 文件内第二分钟
bar_1.dat
- …
- 文件第10分钟
bar_9.dat
是否可以在 shell 脚本中实现此目的?如果可以,我该如何实现?
我目前管理的内容:
我只管理了这个解决方案,程序在每分钟后重新启动并重定向到新的输出文件:
#!/bin/bash
for i in {0..9}
do
timeout 60s foo > "bar_${i}.dat"
done
但是,我希望程序 foo
连续 运行 而不必重新启动它,因为按照我所意识到的方式,我丢失了一些到达的数据包(有一个 20 运行 个实例之间的 -30 毫秒间隔)。
如果 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
如果 foo 没有产生文本输出,您可能想要编写 foo 以便它接受外部输入(例如,信号)并自行重定向输出。或者,您可能只想使用 logrotate。
您可以使用无限循环和 date/time 标记文件名:
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
还为任何错误消息添加了错误日志。不确定您的程序如何处理 stderr
.
让程序写入命名管道 (fifo),然后从该管道获取输出并将其放入文件中。在这里的示例中,我在后台启动循环,然后立即开始写入命名管道:
mkfifo thepipe
for (( i = 0; i < 10; ++i )); do
timeout 60 cat thepipe >"bar_$i.dat"
done &
foo >thepipe
rm -f thepipe
或者,使用进程替换:
foo > >(
for (( i = 0; i < 10; ++i )); do
timeout 60 cat >"bar_$i.dat"
done
)