设置命令执行的超时并将结果输出到文件

时间:2017-02-25 02:25:24

标签: bash

我有一个基本的script.sh,它在里面运行一些命令。该脚本如下:

(script.sh)

......
`gcc -o program program.c` 
 if [ $? -eq 0 ]; then
    echo "Compiled successfully....\n" >> out.txt

 #set a timeout for ./program execution and append results to file
 (gtimeout 10s ./program) 2> out.txt  # <-- NOT WORKING

......

我通过终端运行此脚本,如:

#Go to this directory,pass all folders to compile&execute the program.c file 
czar@MBP~$  for D in /Users/czar/Desktop/1/*; do sh script.sh $D; done

编辑:我在终端输入的输出,虽然不是那么重要:

# program.c from 1st folder inside the above path
Cycle l=1: 46 46
Cycle l=1: 48 48
Cycle l=2: 250 274 250
Cycle l=1: 896 896
.........
# program.c from 2nd folder inside the above path
Cycle l=1: 46 46
Cycle l=1: 48 48
Cycle l=2: 250 274 250
Cycle l=1: 896 896
.........

目标是让那些进入out.txt

我得到的输出是 几乎 我想要的:它在那10秒内执行任何可能的但不会将结果重定向到out.txt,它只是打印到终端。 我已尝试过提出的所有建议here,但没有运气。

赞赏任何其他想法。

编辑2:评论中给出的解决方案。

1 个答案:

答案 0 :(得分:1)

基本方法比从答案中复制到完全不同的问题的命令简单得多。您需要做的只是将标准输出重定向到您的文件:

# Use gtimeout on systems which rename standard Gnu utilities
timeout 10s ./program >> out.txt

但是,如果程序被gtimeout杀死,那么可能不会产生程序生成的所有输出,因为输出仍然位于标准库内的缓冲区中。 (这个缓冲区没什么特别之处;它只是第一次将数据写入流时库函数malloc'd的内存块。)当程序终止时,它的内存返回给操作系统;什么都不会尝试确保将标准库缓冲区刷新到各自的流中。

有三种缓冲模式:

  • Block buffered:在流的缓冲区已满之前不会产生任何输出。 (通常,流的缓冲区大约为8kb,但因系统而异。)

  • 行缓冲:在向流发送换行符时生成输出。如果缓冲区填满,它也会产生,但是很少一条线足够长以填充缓冲区。

  • 无缓冲:根本不执行缓冲。每个字符都会立即发送到输出。

通常,标准输出是块缓冲的,除非它被定向到终端,在这种情况下它将被线路缓冲。 (这不保证;各种标准允许相当大的自由度。)线缓冲可能是你想要的,除非你养成编写写部分线的程序的习惯。 (在每个输出行的开头而不是在结尾处放置换行的奇怪常用的习惯是一个非常糟糕的主意,正是因为它击败了行缓冲。)无缓冲输出是另一种可能性,但如果程序真的很慢产生大量的产出。

您可以在通过调用setvbuf将任何数据写入流之前更改缓冲模式:

/* Line buffer stdout */    
setvbuf(stdout, NULL, _IOLBF, 0);

(有关更多选项,请参阅man setvbuf。)

您还可以通过调用fflush来告诉库立即发送任何缓冲的数据:

fflush(stdout);

如果您不想要线路缓冲的(轻微)开销,这是一种有效的技术,但是您知道何时发送数据很重要(通常,因为程序即将进行一些非常长的计算,或者等待一些外部事件)。

如果无法修改源代码,可以在启动程序之前使用Gnu实用程序stdbuf更改缓冲模式。 stdbuf不适用于所有程序 - 例如,如果程序调用{​​{1}}它将不起作用 - 但它通常是有效的。例如,对于行缓冲区标准输出,您可以这样做:

setvbuf

有关详细信息,请参阅man stdbuf