我对下面的脚本有一个非常奇怪的行为。它执行正常,但之后我在提示符下键入的任何内容都会被识别,但不会显示。因此,我可以输入另一个命令或使用箭头按钮从历史记录中选择一个命令,但提示仍然为空。如果我执行新的不可见命令,命令输出将正确显示,但问题仍然存在。只有使用新的终端实例,问题才消失。
#!/bin/bash
getAspect () {
aspectR=$(
mplayer -vo null -nosound "$1" 2>&1 |
while read line; do # wait until mplayer prints aspect infos or starts to play
[[ $line =~ Aspe[ck]t.is.*1\.33:1 ]] && echo 1 && break
[[ $line =~ Aspe[ck]t.is.*0\.56:1 ]] || [[ $line =~ Aspe[ck]t.is.*1\.78:1 ]] && echo 2 && break
[[ $line == "VO: [null]"* ]] && echo 0 && break
done
pkill -n mplayer
)
return $aspectR # returns 1 (4:3), 2 (16:9) or 0 (no aspect ratio)
}
getAspect "./NameOfAMovieFile"
我可以将问题缩小到以下范围:
使用 mplayer 输出(见下文),我[[ $line =~ such ]] && echo 9 && break
在循环中插入了另一个测试,以顺序检查问题从哪一行开始。
结果:4 号线 (LIRC)。如果测试与之前的任何行匹配,则问题不会发生,否则就会发生。
将 mplayer 输出保存到文件并cat "saved_output"
在函数中替换 mplayer 不会引发问题。
那么错误到底出在哪里呢?
mplayer 产生一些奇怪的输出、bash 或我的终端程序(使用 Konsole 和 Yakuake 测试)是否是函数中的错误?
我怎样才能解决这个问题?
# mplayer -vo null -nosound "./NameOfAMovieFile" 2>&1
MPlayer 1.2.r38008-Packman-8 (C) 2000-2017 MPlayer Team
do_connect: could not connect to socket
connect: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.
Playing ./NameOfAMovieFile.
libavformat version 58.12.100 (external)
libavformat file format detected.
[lavf] stream 0: video (h264), -vid 0
[lavf] stream 1: audio (vorbis), -aid 0, -alang eng
VIDEO: [H264] 1280x720 0bpp 29.970 fps 0.0 kbps ( 0.0 kbyte/s)
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
libavcodec version 58.18.100 (external)
Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264)
==========================================================================
Clip info:
COMPATIBLE_BRANDS: iso6avc1mp41
MAJOR_BRAND: dash
MINOR_VERSION: 0
ENCODER: Lavf57.71.100
Load subtitles in ./
Audio: no sound
Starting playback...
Movie-Aspect is 1.78:1 - prescaling to correct movie aspect.
VO: [null] 1280x720 => 1280x720 Planar YV12 [zoom]
V: 0.0 0/ 0 ??% ??% ??,?% 0 0 [J
V: 0.0 0/ 0 ??% ??% ??,?% 0 0 [J
MPlayer interrupted by signal 2 in module: sleep_timer
V: 3.1 0/ 0 19% 0% 0.0% 0 0 [J
Exiting... (Quit)
我的系统:OpenSuse TumbleWeed、KDE
答案1
这是因为当您通过 杀死脚本时Ctrl+C,终端将 SIGINT 发送到前台进程组领导者(在您的情况下,bash 进程是领导者),但默认情况下它不会传递到子 shell 进程。
您可以放在trap "kill 0" SIGINT;
脚本之上,例如:
#!/bin/bash
trap "kill 0" SIGINT;
mplayer -vo null foo.mkv 2>&1 | while read line; do echo "$line"; done
或者用一行命令执行此操作:
bash -c 'trap "kill 0" SIGINT; mplayer -vo null foo.mkv 2>&1 | while read line; do echo "$line"; done'
Killing 0 向当前进程组中的所有进程发送信号。信用。
当 mplayer 子 shell 在没有 SIGINT 的情况下终止时,其 shell 将不会重置 stty 回显。您可以键入stty echo
(在您的情况下不可见)并按Enter以手动启用回显可见性。