bash - bash 陷阱后恢复

标签 bash bash-trap

我有一个带有一些文件操作的 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/

相关文章:

linux - 使用 Bash 构建一个简单的计算机到计算机信使

linux - 什么时候处理信号以及为什么某些信息会卡住?

bash - `ERR` 语法错误时不执行trap

bash - 捕获一行代码的错误流,并在保持stdout不变的情况下用trap报告

bash - 通过传递参数来捕获函数?

bash - Trap 命令未检测终端大小调整 (SIGWINCH)

bash - 使用替换和变量重命名文件和目录

linux - TAR命令文件扩展路径扩展

linux - 删除具有相似名称的文件,除了一个?

bash - 按顺序打印正则表达式匹配的每个字符串