Joh*_*gen 5 bash parent-child sigint child-process
我正在编写一个 bash 脚本,其中编写了一个处理程序来处理用户按下 Control+C(通过使用trap interruptHandler SIGINT)时的情况,但 SIGINT 会发送到 bash 脚本和当前正在运行的子进程,从而关闭子进程过程。我怎样才能防止这种情况发生?
编辑:这是剧本,不要过多批评我的技能..
#!/bin/bash
trap "interruptHandler" SIGINT
inInterrupt=false;
quit=false;
if [ -z ${cachedir+x} ]; then cachedir=~/.cache/zlima12.encoding; fi
cachedir=$(realpath ${cachedir});
if [ ! -e ${cachedir} ]; then mkdir ${cachedir}; fi
if [ ! -e ${cachedir}/out ]; then mkdir ${cachedir}/out; fi
cleanCache ()
{
rm ${cachedir}/*.mkv;
rm ${cachedir}/out/*.mkv;
}
interruptHandler ()
{
if [ ${inInterrupt} != true ]; then
printf "BASHPID: ${BASHPID}";
inInterrupt=true;
ffmpegPID=$(pgrep -P ${BASHPID});
kill -s SIGTSTP ${ffmpegPID};
printf "\nWould you like to quit now(1) or allow the current file to be encoded(2)? ";
read response;
if [ ${response} = "1" ]; then kill ${ffmpegPID}; cleanCache;
elif [ ${response} = "2" ]; then quit=true; kill -s SIGCONT ${ffmpegPID};
else printf "I'm not sure what you said... continuing execution.\n"; kill -s SIGCONT ${ffmpegPID};
fi
inInterrupt=false;
fi
}
for param in "$@"; do
dir=$(realpath ${param});
if [ ! -e ${dir} ]; then
printf "Directory ${dir} doesn't seem to exist... Exiting...\n"
exit 1;
elif [ -e ${dir}/new ]; then
printf "${dir}/new already exists! Proceed? (y/n) ";
read response;
if [ ${response} != y ]; then exit 1; fi
else
mkdir ${dir}/new;
fi
for file in ${dir}/*.mkv; do
filename="$(basename ${file})";
cp $file ${cachedir}/${filename};
ffmpeg -vsync passthrough -i ${cachedir}/${filename} -c:v libx265 -c:a copy -f matroska ${cachedir}/out/${filename};
rm ${cachedir}/${filename};
mv ${cachedir}/out/${filename} ${dir}/new/${filename};
if [ ${quit} = true ]; then exit 0; fi
done
done
Run Code Online (Sandbox Code Playgroud)
(如果您好奇的话,这是一个将 matroska (mkv) 文件编码为 H.265 的脚本)
在这里进行了一个简单的测试,它提供了预期的结果:
int.sh内容:
#!/bin/bash
trap '' SIGINT
tail -f /var/log/syslog >& /dev/null
Run Code Online (Sandbox Code Playgroud)
测试:
$ ./int.sh
^C^C
# ... SIGINT ignored (CTRL+C) ...
# ... Will send SIGTSTP with CTRL+Z ...
^Z
[1]+ Stopped ./int.sh
$ kill %1
$
[1]+ Terminated ./int.sh
$
Run Code Online (Sandbox Code Playgroud)
编辑(回答问题编辑):
您可能希望捕获并忽略SIGINT每个其他命令(例如(trap '' SIGINT && command)在脚本中),这样您就可以防止在调用之前从当前命令捕获信号interruptHandler。
正在发生的事情的一个简单示例:
#!/bin/bash
function intHandler() {
echo "If SIGINT was caught, this will be printed AFTER sleep exits."
}
trap intHandler SIGINT
sleep 5 # Sleep will exit as soon as SIGINT is caught
Run Code Online (Sandbox Code Playgroud)
输出:
$ time ./int.sh
^C
# ... Right here, only 0.6 seconds have elapsed before the below message being printed ...
If SIGINT was caught, this will be printed AFTER sleep exits.
real 0m0.634s
user 0m0.004s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
注意,由于SIGINT被抓住,只持续了0.6秒。
但是当你忽略 SIGINT 时sleep:
function intHandler() {
echo "If SIGINT was caught, this will be printed AFTER sleep exits."
}
trap intHandler SIGINT
(trap '' SIGINT && sleep 5)
Run Code Online (Sandbox Code Playgroud)
输出是:
$ time ./int.sh
^C
# ... Right here, 5 seconds have elapsed without any message ...
If SIGINT was caught, this will be printed AFTER sleep exits.
real 0m5.007s
user 0m0.000s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
请注意,尽管SIGINT已被脚本传递并捕获,但intHandler只有当当前sleep退出时才会返回,还要注意当前sleep并没有SIGINT从父级(它持续了整整 5 秒)作为其运行的子 shell 捕获 。 on (the ( ... )) 被忽略SIGINT。
| 归档时间: |
|
| 查看次数: |
3995 次 |
| 最近记录: |