我一直在尝试编写一个简单的 bash 脚本,但无法让它工作。
我想要:
- 启动一个程序,从文本文件中为其提供输入 (
./prog < input1.txt
) - 等待一小段时间并杀死它,就好像它被键盘中断服务一样 (
& PID=$!; sleep 1; kill -INT $PID
)来源 - 找出程序输出和文本文件之间的差异 (
| diff -y output1.txt -
)来源
这就是我现在所拥有的,将前面的步骤放在一起:
./program < input1.txt & PID=$!; sleep 1; kill -INT $PID | diff -y output1.txt -
此版本始终报告第一个命令没有输出,因为 PID 行正在隐藏它。如果我在程序名称后添加文件重定向,kill 命令就会停止工作,因为它现在指向重定向。
编辑:我使用的是 Ubuntu 16.04;的输出bash --version
是GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
答案1
事实上,在您的代码中diff
接收的是 的输出kill
而不是program
.您可以通过将子 shell 中管道之前的命令与()
.
您的脚本的另一个潜在问题是,它kill
不是设计用来等待program
;的终止的。相反,它只是向它发送一个信号。因此,您可能会看到竞争条件在diff
没有捕获 的整个输出的情况下起作用program
。我建议以编程方式等待wait
内置 bash 后台进程的终止。
下面是包含上述修复的代码示例:
#!/bin/bash
(
./program <input1.txt &
PID=$!
sleep 1
kill -INT $PID
wait
) | diff -y reference_output.txt -
答案2
您可以使用进程替换[1]:
diff -y output1.txt <(your_program & sleep 1; kill $!)
如果your_program
能够在一秒钟内生成大量数据(就像使用 进行测试时一样yes(1)
),那么diff
处理时会遇到很多麻烦,除非您有一些仔细的限制,否则它可能会耗尽您的内存并挂起您的机器(在最好的情况下,它会产生命令“挂起”一段时间的错觉)。相反yes
,请尝试使用slowyes
类似 的脚本while echo y; do sleep .01; done
。
请注意,<(...)
进程替换正在运行在平行下,因此diff
不会等待它完成后再开始处理其数据。
your_program
我想在生成多行之后停止而不是在一段时间之后停止会更好:
diff -y output1.txt <(your_program | head -n 1000)
在这种情况下,your_program
应该被 杀死SIGPIPE
,就像通常使用管道左侧一样。如果您的程序忽略了SIGPIPE
和write(2)
错误,那么请就此提出另一个问题,或者如何修复它或如何解决它。
[1] 如果您的 shell 不支持进程替换(如/bin/sh
debian 上的那样,则不支持bash
),您还可以使用管道,如其他答案中所示
{ your_program & sleep 1; kill $!; } | diff -y output1.txt -
同样的注意事项也适用于本案。