在陷阱中创建 for 循环在 Shell 脚本中不起作用



我一直在尝试在脚本中创建一个陷阱,以基本上创建后台运行的脚本的一些日志。

每当我在陷阱中引入for循环时,脚本就会停止执行它应该执行的操作:

trap 'terminate' 10
...
write_log(){
    local target=$1
    local file="/tmp/"$target"_log.txt"
    local lines=$(cat /tmp/"$target"_log.txt | wc -l)
    printf "Log for $targetn" >> "log.txt"   # This line is printed

    for ((i=1;i<=$lines;i++));                # Nothing in this loop happens
    do                         
        local start_date=$(date -d "$(sed -n ""$i"p") $file | cut -f1")
        local end_date=$(date -d "$sed -n ""$i"p") $file | cut -f2")
        printf "Logged in $start_date, logged out $end_date" > "log.txt"
    done
}
terminate(){
    for target
    do
        echo "In the for loop!"
        end_session "$target"
        write_log "$target"
    done
    exit 0
}

当我在后台运行脚本并用杀死它时

kill -10 (process_id)

脚本停止并开始进行清理,直到找到for循环为止。当我删除terminate((中的for循环,转而对end_session((和write_log((进行单独调用时,end_session((运行良好,write_log(运行良好——直到它到达for循环。

我可能错过了一些基本的东西,但我已经看了一段时间了,似乎不知道发生了什么。陷阱中的for循环有任何限制吗?

trap调用terminate时,不会向其传递任何参数,因此其循环执行次数为零(因为for target; do …; donefor target in "$@"; do …; done的缩写,在函数中,"$@"是函数的参数列表,而不是整个shell脚本的参数列表(。

如果您不希望发生这种情况,则必须安排将相关参数传递给trap中的terminate。例如,您可以通过全局数组将所有参数传递给脚本:

args=( "$@" )

和内部terminate:

for target in "${args[@]}"

然而,什么是最好的取决于你想要实现什么。

函数挂起是因为日期命令中的括号弄乱了。试试这个:

local start_date=$(date -d "$(sed -n ${i}p "$file" | cut -f1)")
local end_date=$(date -d "$(sed -n ${i}p "$file" | cut -f2)")

最新更新