Bash 重击陷阱后恢复

Bash 重击陷阱后恢复,bash,bash-trap,Bash,Bash Trap,我有一个带有一些文件操作的bash脚本,我想在按下CTRL+C后处理一个循环,直到块结束。我举了一个例子: #!/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 (

我有一个带有一些文件操作的bash脚本,我想在按下CTRL+C后处理一个循环,直到块结束。我举了一个例子:

#!/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;
如果在basename命令期间发生陷阱,则不设置。这会导致
cp
和以下命令出错

我错过什么了吗?bash如何从陷阱中恢复?有没有其他具有相同效果的解决方案?

而不是

BASE=$(basename $FILE);
换成这个:

BASE=${FILE##*/}
将工作函数放在后台,远离处理SIGINT的接口也是一个好主意。只是避免在它里面要求输入。同时,请始终正确引用变量

#!/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"
#/bin/bash
#寄存器信号处理器
中止=0;
陷阱中止=1 SIGINT;
#创建临时目录
TEMPDIR=$(mktemp-d-t$0);
#辅助函数
函数做其他的事情{
是的;
}
#处理文件
for((计数器=0;计数器<3&&ABORT==0;计数器++);做
(
FILE=/some/directory/$COUNTER.txt
BASE=${FILE##*/}
cp“$FILE”“$TEMPDIR”
>“$FILE”
做其他事情吗
cp“$TEMPDIR/$BASE”“$FILE”
rm“$TEMPDIR/$BASE”
) &
消费物价指数=$!
#处理SIGINT,但在子流程完成其工作之前不要结束循环。
而kill-s0cpid&>/dev/null;do##检查子进程是否仍然存在。
#如果是,请稍候。
等待“$CPID”
完成
完成
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"
#处理文件
for((计数器=0;计数器<3&&ABORT==0;计数器++);做
(
FILE=/some/directory/$COUNTER.txt
BASE=${FILE##*/}
cp“$FILE”“$TEMPDIR”
>“$FILE”
做其他事情吗
cp“$TEMPDIR/$BASE”“$FILE”
rm“$TEMPDIR/$BASE”
) &
消费物价指数=$!
虽然
等待“$CPID”
如果[[中止-等式1]];然后
kill-s ABRT“$CPID”和>/dev/null
打破
fi
kill-s 0“$CPID”和>/dev/null
做
持续
完成
完成
rm-rf“$TEMPDIR”

很有效,谢谢。现在只剩下一个问题,bash在这件事上的意图是什么。@UrsMarti因为我们知道SIGINT可以中断陷阱处理之外的其他操作,所以我们只允许将工作命令放在子shell(
(commands;…)&
)下的后台。因此,通过这样做,SIGINT将不再能够到达它们,并且按照预期,shell将能够轻松地处理它。当处于等待模式(
wait
)并收到信号时,将触发陷阱,将标志设置为变量,然后在等待后的下一个命令上继续操作。这是我们进行循环的时间,以不断检查子shell,直到它完成为止。
# 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"