Bash 停止录制而不停止脚本的其余部分
我正在玩使用谷歌语音到文本api的脚本。api需要flac编码的文件,因此脚本的录制部分如下所示:Bash 停止录制而不停止脚本的其余部分,bash,Bash,我正在玩使用谷歌语音到文本api的脚本。api需要flac编码的文件,因此脚本的录制部分如下所示: arecord -q -t wav -d 0 -f S16_LE -r 16000 | flac - -f --best --sample-rate 16000 -s -o "$TEMP_FILE" 此命令将记录,直到用户使用ctrl-c退出,wav记录的格式应通过管道传输到flac程序,以flac格式输出,然后脚本应继续 我遇到的问题是,按ctrl-c键会完全结束脚本,并切断部分音频(flac
arecord -q -t wav -d 0 -f S16_LE -r 16000 | flac - -f --best --sample-rate 16000 -s -o "$TEMP_FILE"
此命令将记录,直到用户使用ctrl-c退出,wav记录的格式应通过管道传输到flac程序,以flac格式输出,然后脚本应继续
我遇到的问题是,按ctrl-c键会完全结束脚本,并切断部分音频(flac文件仍在输出)。如果在不使用管道的情况下运行脚本:
arecord -q -t wav -d 0 -f S16_LE -r 16000 some.wav
然后按ctrl-c键只会结束录制并继续使用脚本
如何修复此问题,使ctrl-c只停止arecord命令,并允许脚本的其余部分(包括管道flac编码)完成?我认为您试图做的事情无法完成 免责声明:以下内容基于我自己在Ubuntu 12.04上的实验,只是一点研究。如果我错了,一定要告诉我 关键是:
- 在管道运行时按Ctrl-C将向管道中的所有进程发送信号
SIGINT
- 进程接收信号的顺序无法保证
- 除非管道中的所有进程都捕获信号,否则脚本将作为一个整体中止(尽管脚本本身可以使用
命令捕获信号-但这样的shell陷阱在管道进程接收到信号并通常被其终止后才会执行)trap
arecord
设计用于捕获SIGINT
并以有序的方式退出。相比之下,
flac
似乎没有-它被强制终止。但是,即使
flac
也确实捕获了SIGINT
以干净地关闭,由于相关进程接收信号的顺序不确定,您无法安全地使用带有Ctrl-C的管道,同时期望整个处理以有序的方式完成。
(顺便提一下:arecord
在使用Ctrl-C终止时报告退出代码1
,这让我想知道如何将其与真正的故障区分开来,例如磁盘空间不足。)
因此:
- 将
作为单独的命令调用并将输出捕获到(临时)文件中arecord
- 然后,将(临时)文件传递到
(完成后删除临时文件)flac
- 我将尝试以下方法:
# 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
#创建fifo
先进先出=/tmp/my_先进先出
mkfifo$FIFO
#在后台启动一条记录,并将其输出重定向到fifo
A记录…>$先进先出&
#获取arecord PID
PID=$!
#捕获SIGINT以将SIGINT发送到arecord
陷阱“kill-INT$PID”INT
#启动flac并用fifo重定向其输入。
flac-…<$先进先出
#应该在此处阻止脚本,并运行CTRL+C
#kill-INT仅用于arecord进程。
#但我不知道flac在。。。
#如果flac正确退出,只需恢复SIGINT
陷阱整数
问题在于Ctrl-C
会杀死flac
,因为flac
的设计不是以这种方式完全关闭的(不像arecord
)。现在需要的是一种在Ctrl-C
到达flac
之前拦截Ctrl-C的方法,这是您的解决方案无法做到的(陷阱在flac
已经被杀死之后启动)-我不知道如何在bash中做到这一点。此外,我想知道OP追求的是单一管道的优雅。如果不能做到这一点,那么只需记录到一个临时的。文件,然后对临时文件进行转码。文件要简单得多。