bash 停止 arecord 记录而不停止脚本的其余部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24535707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
stopping arecord recording without stopping rest of script
提问by RBI
I am playing with scripts that use the google speech-to-text api. The api requires flac encoded files so the recording part of the script looks like this:
我正在使用使用 google 语音到文本 api 的脚本。api 需要 flac 编码的文件,因此脚本的录制部分如下所示:
arecord -q -t wav -d 0 -f S16_LE -r 16000 | flac - -f --best --sample-rate 16000 -s -o "$TEMP_FILE"
This command will record until the user exits with ctrl-c and the wav recorded format should be piped to the flac program for outut in flac format, then the script should continue.
这个命令会一直录制,直到用户用 ctrl-c 退出,wav 录制的格式应该通过管道传输到 flac 程序以 flac 格式输出,然后脚本应该继续。
The problem I am having is that pressing ctrl-c ends the script entirely and is cutting off some of the audio (the flac file is still outputted). If I run the script without the pipe:
我遇到的问题是按 ctrl-c 会完全结束脚本并切断一些音频(仍输出 flac 文件)。如果我在没有管道的情况下运行脚本:
arecord -q -t wav -d 0 -f S16_LE -r 16000 some.wav
Then pressing ctrl-c will only end the recording and continues on with the script as it should.
然后按 ctrl-c 只会结束录制并继续执行脚本。
How do I fix this so that ctrl-c only stops the arecord command and allows the rest of the script (including the piped flac encoding) to finish?
如何解决此问题,以便 ctrl-c 仅停止 arecord 命令并允许脚本的其余部分(包括管道 flac 编码)完成?
采纳答案by mklement0
Methinks what you're trying to do cannot be done.
我觉得你想做的事是做不到的。
Disclaimer: The following is based on my own experiments on Ubuntu 12.04, with just a smattering of research. Do let me know if I'm wrong.
免责声明:以下内容基于我自己在 Ubuntu 12.04 上的实验,仅进行了少量研究。如果我错了,请告诉我。
The crux:
关键:
- Pressing Ctrl-Cwhile a pipeline is running sends signal
SIGINT
to ALL processes in the pipeline. - The orderin which the processes receive the signal is not guaranteed.
- Unless ALL processes in the pipeline trapthe signal, the script will abort as a whole (though the script itself can trap the signal with a
trap
command - but such a shell trap won't execute until afterthe pipeline processes have received the signal and have typically been terminated by it).
- Ctrl-C在管道运行时按下会向管道中的
SIGINT
所有进程发送信号。 - 不能保证进程接收信号的顺序。
- 除非所有的管道处理陷阱的信号,该脚本将中止作为一个整体(虽然脚本本身可以捕获一个信号
trap
命令-但这样的罩子套住不会执行,直到后处理已接收到的信号的管道,并有通常被它终止)。
In your specific case, arecord
is designedto trapSIGINT
and exit in an orderly fashion in response.
By contrast, flac
appears not to - it is terminated forcefully.
However, even if flac
also didtrap SIGINT
to shut down cleanly, given the nondeterministic order in which the signal is received by the processes involved, you cannot safely use a pipeline with Ctrl-Cwhile expecting overallprocessing to finish in an orderly fashion.
在特定情况下,arecord
被设计来捕获SIGINT
和退出有序地响应。
相比之下,flac
似乎没有 - 它被强行终止。
但是,即使flac
也确实使用了陷阱SIGINT
来干净地关闭,鉴于所涉及的进程接收信号的顺序不确定,您也不能安全地使用管道,Ctrl-C同时期望整体处理以有序的方式完成。
(As an aside: arecord
reports exit code 1
when terminated with Ctrl-C, which makes me wonder how you can distinguish that from true failure, such as running out of disk space.)
(顺便arecord
说一句:以1
终止时报告退出代码Ctrl-C,这让我想知道如何将其与真正的失败区分开来,例如磁盘空间不足。)
Thus:
因此:
- Invoke
arecord
as a separate commandand capture the output in a (temporary) file. - Afterward, pass the (temporary) file to
flac
(and delete the temporary file when done).
arecord
作为单独的命令调用并在(临时)文件中捕获输出。- 然后,将(临时)文件传递给
flac
(完成后删除临时文件)。
回答by jmlemetayer
I will try this way:
我会尝试这种方式:
# Create a fifo
FIFO=/tmp/my_fifo
mkfifo $FIFO
# Start arecord in background and redirect its output into the fifo
arecord ... > $FIFO &
# Get the arecord PID
PID=$!
# Trap the SIGINT to send SIGINT to arecord
trap "kill -INT $PID" INT
# Start flac and redirect its input with the fifo.
flac - ... < $FIFO
# The script should be blocked here, and a CTRL+C will run
# the kill -INT to the arecord process only.
# But I don't know how flac will react after ...
# If flac exit correctly, just restore the SIGINT
trap - INT