我有一个带有一些文件操作的 bash 脚本,我想在按 CTRL+C 后处理一个循环直到 block 结束。我举了个例子:
#!/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
BASE=$(basename $FILE);
未设置,如果陷阱恰好发生在 basename 命令期间。这会导致 cp
和以下命令出错。
我错过了什么吗? bash 的意图是如何从陷阱中恢复的?是否有其他解决方案具有相同的效果?
最佳答案
代替
BASE=$(basename $FILE);
改用这个:
BASE=${FILE##*/}
将您的工作函数放在后台远离处理 SIGINT 的接口(interface)也是一个好主意。只是避免在其中询问输入。还要始终正确引用您的变量。
#!/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 - bash 陷阱后恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18683066/