我一直在尝试在脚本中创建一个陷阱,以基本上创建后台运行的脚本的一些日志。
每当我在陷阱中引入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 …; done
是for 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)")