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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:46:29  来源:igfitidea点击:

stopping arecord recording without stopping rest of script

bash

提问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 SIGINTto 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 trapcommand - 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, arecordis designedto trapSIGINTand exit in an orderly fashion in response.
By contrast, flacappears not to - it is terminated forcefully.
However, even if flacalso didtrap SIGINTto 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: arecordreports exit code 1when 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 arecordas 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