Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于while read line 循环中变量作用域的问题 #93

Open
vieyahn2017 opened this issue Feb 7, 2024 · 3 comments
Open

关于while read line 循环中变量作用域的问题 #93

vieyahn2017 opened this issue Feb 7, 2024 · 3 comments

Comments

@vieyahn2017
Copy link
Owner

https://www.cnblogs.com/Juststudy02/p/9842713.html

@vieyahn2017
Copy link
Owner Author

前一阵用shell写了一个从数据库中抽取数据生成.xml文件的脚本,要求是每个文件中只生成1000条数据。于是用到了while read line 作为循环。

在制作文件计数器的时候发现了一个问题,在执行的过程中文件计数器(FILENUM)总是出现返回初始值的现象,具体简化的脚本如下:

#/bin/bash
FILENUM=1
for i in (多个表)
do
  #sql 语句 > .swap
  COUNTER=0
  cat .swap | while read line
  do
    #变量赋值以及写入文件的内容(不是重点,没细写)
    COUNTER=$[COUNTER+1]
    if [ $COUNTER -eq 1000 ]
    then
      #封包操作,封包的包名中附带了$FILENAME(没细写)
      FILENUM=$[FILENUM+1]
    fi
  done
  #封包操作,封包的包名中附带了$FILENAME,因为不能保证是1000条整数,所以read line跳出后还是需要执行这个操作。
  FILENUM=$[FILENUM+1]
done

基本流程如上:

在执行过程中发现文件计数器FILENUM总是有还原成默认值的情况。

经过调试发现,每一次while read line 循环的文件完成之后都会发生这种现象。

启动sh的时候同时也发现了两个同名的*.sh进程

经过查阅资料,发现在while read line 的用法中常用的有两种。

cat FILE | while read line
do
    `
done
while read line
do

done < FILE

经过分别测试得出以下结论:

使用管道符 | 的方法相当于启动了一个独立的子进程,因此循环中的变量FILENUM是属于自进程中的,与循环外的FILENUM虽然同名,但是值却不同。

使用重定向 < 的方法则不会有这种现象,在脚本启动时并没有子进程出现,因此循环内部变量FILENUM与循环外的FILENUM变量在同一个bash shell中。

@vieyahn2017
Copy link
Owner Author

#!/bin/bash

tmpfile=/root/multipath_tmp
[ -e "$tmpfile" ] && rm -rf $tmpfile

this_inode=$(ifconfig Mgnt-0 | grep "inet " | awk '{print $2}')

function explain_one_foreach () {
    for lun in $(cat "$WWIDS" | grep -v ^# | sed s#/##g);
    do
        result=$(multipath -ll "$lun" 2> /dev/null)
        echo "$result" | grep " sd" | awk -v nlun="$lun" '{print nlun" "$3" "$2" "$5" "$6" "$7}' >> $tmpfile
    done
}

function explain_all () {
    results=$(multipath -ll 2> /dev/null)
    local lun=""
    local count=0
    echo "$results" | while read line;
    do
        if [ "${line:0:2}" == "36" ]; then
            lun=$(echo $line | awk '{print $1}')
            if [ ! -z "$last_lun" ] && [ "$count" -gt 0 ]; then
                echo "$last_lun at $this_inode count is [$count]"
            fi
            last_lun=$lun
            count=0
        fi
        if [ $(echo $line | grep -c " sd") -eq 1 ]; then
            echo "$line" | awk -v nlun="$lun" '{print nlun" "$3" "$2" "$5" "$6" "$7}'
            count=$((count+1))
        fi
    done
    echo "$lun at $this_inode count is [$count]"
}

WWIDS=/etc/multipath/wwids
if [ ! -f /etc/multipath/wwids ]; then
    echo "/etc/multipath/wwids files not existed"
    if [ $(multipath -ll  2>&1 | grep -c "DM multipath kernel driver not loaded") -eq 1 ]; then
        echo "DM multipath kernel driver not loaded"
        exit 1
    fi
fi

explain_all >> $tmpfile
exit 0

最后一行没有值
366c2222222222aa95116c76b00000163 sdc 33:0:0:2 active ready running
366c2222222222aa95116c76b00000163 sdg 34:0:0:2 active ready running
366c2222222222aa95116c76b00000163 sdk 35:0:0:2 active ready running
366c2222222222aa95116c76b00000163 sdo 36:0:0:2 active ready running
366c2222222222aa95116c76b00000163 at 2.2.2.2 count is [4]
366c2222222222aa95116c76b00000162 sdb 33:0:0:1 active ready running
366c2222222222aa95116c76b00000162 sdf 34:0:0:1 active ready running
366c2222222222aa95116c76b00000162 sdj 35:0:0:1 active ready running
366c2222222222aa95116c76b00000162 sdn 36:0:0:1 active ready running
366c2222222222aa95116c76b00000162 at 2.2.2.2 count is [4]
366c2222222222aa95116c76b00000165 sde 33:0:0:4 active ready running
366c2222222222aa95116c76b00000165 sdi 34:0:0:4 active ready running
366c2222222222aa95116c76b00000165 sdm 35:0:0:4 active ready running
366c2222222222aa95116c76b00000165 sdq 36:0:0:4 active ready running
at 2.2.2.2 count is [0]

@vieyahn2017
Copy link
Owner Author

#!/bin/bash

tmpfile=/root/multipath_tmp
rstfile=/root/multipath_rst
[ -e "$tmpfile" ] && rm -rf $tmpfile
[ -e "$rstfile" ] && rm -rf $rstfile

this_inode=$(ifconfig Mgnt-0 | grep "inet " | awk '{print $2}')

function explain_one_foreach () {
    for lun in $(cat "$WWIDS" | grep -v ^# | sed s#/##g);
    do
        result=$(multipath -ll "$lun" 2> /dev/null)
        echo "$result" | grep " sd" | awk -v nlun="$lun" '{print nlun" "$3" "$2" "$5" "$6" "$7}' >> $rstfile
    done
}

function explain_all () {
    multipath -ll > $tmpfile 2> /dev/null
    local lun=""
    local count=0
    while read line;
    do
        if [ "${line:0:2}" == "36" ]; then
            lun=$(echo $line | awk '{print $1}')
            if [ ! -z "$last_lun" ] && [ "$count" -gt 0 ]; then
                echo "$last_lun at $this_inode count is [$count]"
            fi
            last_lun=$lun
            count=0
        fi
        if [ $(echo $line | grep -c " sd") -eq 1 ]; then
            echo "$line" | awk -v nlun="$lun" '{print nlun" "$3" "$2" "$5" "$6" "$7}'
            count=$((count+1))
        fi
    done < $tmpfile
    echo "$lun at $this_inode count is [$count]"
}

WWIDS=/etc/multipath/wwids
if [ ! -f /etc/multipath/wwids ]; then
    echo "/etc/multipath/wwids files not existed"
    if [ $(multipath -ll  2>&1 | grep -c "DM multipath kernel driver not loaded") -eq 1 ]; then
        echo "DM multipath kernel driver not loaded"
        exit 1
    fi
fi

explain_all >> $rstfile
# cat $rstfile
exit 0

对了

366c2222222222aa95116c76b00000163 sdc 33:0:0:2 active ready running
366c2222222222aa95116c76b00000163 sdg 34:0:0:2 active ready running
366c2222222222aa95116c76b00000163 sdk 35:0:0:2 active ready running
366c2222222222aa95116c76b00000163 sdo 36:0:0:2 active ready running
366c2222222222aa95116c76b00000163 at 2.2.2.2 count is [4]
366c2222222222aa95116c76b00000162 sdb 33:0:0:1 active ready running
366c2222222222aa95116c76b00000162 sdf 34:0:0:1 active ready running
366c2222222222aa95116c76b00000162 sdj 35:0:0:1 active ready running
366c2222222222aa95116c76b00000162 sdn 36:0:0:1 active ready running
366c2222222222aa95116c76b00000162 at 2.2.2.2 count is [4]
366c2222222222aa95116c76b00000165 sde 33:0:0:4 active ready running
366c2222222222aa95116c76b00000165 sdi 34:0:0:4 active ready running
366c2222222222aa95116c76b00000165 sdm 35:0:0:4 active ready running
366c2222222222aa95116c76b00000165 sdq 36:0:0:4 active ready running
366c2222222222aa95116c76b00000165 at 2.2.2.2 count is [4]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant