bash的陷阱后恢复 [英] Recover after bash trap
问题描述
我和一些文件操作一个bash脚本,我想处理一个循环,直到pressing控制-C后,块的结尾。我做了一个例子:
I've a bash script with some file manipulations and I would like to process a loop until the end of the block after pressing Control-C. I've made an example:
#!/bin/bash
# Register signal handler
ABORT=0;
trap ABORT=1 SIGINT;
# Create temp dir
TEMPDIR=$(mktemp -d -t $0);
# Helper functions
function do_other_stuff {
true;
}
# Process files
for ((COUNTER = 0; COUNTER < 3 && ABORT == 0; COUNTER++)); do
FILE=/some/directory/$COUNTER.txt;
BASE=$(basename $FILE);
cp $FILE $TEMPDIR;
> $FILE;
do_other_stuff;
cp $TEMPDIR/$BASE $FILE;
rm $TEMPDIR/$BASE;
done;
rm -rf $TEMPDIR;
这似乎运作得很好,但我注意到,有时BASE在声明
This seems to work quite well, but I noticed, that sometimes BASE in the statement
BASE=$(basename $FILE);
没有设置,如果陷阱发生的基本部分命令期间发生。这导致在CP错误和下面的命令
is not set, if the trap happens to occur during the basename command. This leads to errors in the cp and following commands.
我是否错过了什么呢?如何猛砸从陷阱中恢复的用意何在?是否存在具有相同效果的另一种解决方案?
Do I miss something there? How is the intention of bash to recover from traps? Is there another solution with the same effect?
推荐答案
而不是
BASE=$(basename $FILE);
有这一个,而不是:
Have this one instead:
BASE=${FILE##*/}
这也是放置在后台的工作职能远离处理SIGINT接口是一个好主意。只要避免要求在它的输入。还引用您的变量总是正确的。
It's also a good idea to place your work functions on the background away from the interface that handles SIGINT. Just avoid asking for input within it. Also quote your variables properly always.
#!/bin/bash
# Register signal handler
ABORT=0;
trap ABORT=1 SIGINT;
# Create temp dir
TEMPDIR=$(mktemp -d -t $0);
# Helper functions
function do_other_stuff {
true;
}
# Process files
for ((COUNTER = 0; COUNTER < 3 && ABORT == 0; COUNTER++)); do
(
FILE=/some/directory/$COUNTER.txt
BASE=${FILE##*/}
cp "$FILE" "$TEMPDIR"
> "$FILE"
do_other_stuff
cp "$TEMPDIR/$BASE" "$FILE"
rm "$TEMPDIR/$BASE"
) &
CPID=$!
# Handle SIGINT but don't end the loop until subprocess finishes its work.
while kill -s 0 CPID &>/dev/null; do ## Checks if subprocess is still there.
# Wait if yes.
wait "$CPID"
done
done
rm -rf "$TEMPDIR"
这人会很快中止操作:
# Process files
for ((COUNTER = 0; COUNTER < 3 && ABORT == 0; COUNTER++)); do
(
FILE=/some/directory/$COUNTER.txt
BASE=${FILE##*/}
cp "$FILE" "$TEMPDIR"
> "$FILE"
do_other_stuff
cp "$TEMPDIR/$BASE" "$FILE"
rm "$TEMPDIR/$BASE"
) &
CPID=$!
while
wait "$CPID"
if [[ ABORT -eq 1 ]]; then
kill -s ABRT "$CPID" &>/dev/null
break
fi
kill -s 0 "$CPID" &>/dev/null
do
continue
done
done
rm -rf "$TEMPDIR"
这篇关于bash的陷阱后恢复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!