cd /var/log
grep "UFW BLOCK" syslog | cut -d ' ' -f 13 | sort -u > pippo.txt
k=0
i=1
ip=""
cat pippo.txt | while read line
do
(( k += i ))
ip=${line:4}
echo "IP " $ip" added to list."
echo -n "K="
echo $k
ufw deny from $ip > /dev/null
done
echo -n "Processed and added "
echo "$k"
echo " IP via UFW to the firewall."
为什么k变量将保留在>> cicle然后它松散了? 在 while - done 期间,cicle echo打印出正确的k值,但在cicle之外,在完成行之后,k始终打印为零。
答案 0 :(得分:1)
这是因为管道|
创建了一个子shell。
子shell复制当前环境并在其中运行新代码。
cd /var/log
grep "UFW BLOCK" syslog | cut -d ' ' -f 13 | sort -u > pippo.txt
k=0
i=1
ip=""
# Pipe creates an environment of its own with k=0, i=1 and ip=""
cat pippo.txt | while read line
do
# The subshell increments its own version of k
(( k += i ))
ip=${line:4}
echo "IP " $ip" added to list."
echo -n "K="
echo $k
ufw deny from $ip > /dev/null
done
# Subhell no longer exists
echo -n "Processed and added "
# The prior environment prints its version of k which is 0
echo "$k"
echo " IP via UFW to the firewall."
您可以通过删除管道并执行此操作来轻松解决此问题。
while read line
do
(( k += i ))
ip=${line:4}
echo "IP " $ip" added to list."
echo -n "K="
echo $k
ufw deny from $ip > /dev/null
done < pippo.txt
这应该会给你相同的效果,但是把它留在同一个shell中
迷你示例
您可以通过运行以下 one liner
来查看此子shell行为的效果k=0; echo $( (( k++ )); echo $k ); echo $k
打印出1
0
,有些人可能希望打印1
1
。这与子shell的原理相同,其中$( )
是具有继承环境的子shell。
答案 1 :(得分:0)
这是由管道造成的,请考虑这个最小的例子,其中k
变量保持不变:
k=0
echo "nothing" | k=5
echo $k
这将打印0
。所以,如果你想让这个例子工作,最简单的方法就是将临时结果存储到一个文件中(在循环中),然后在循环外读取它。