쉘 스크립트 - 출력을 파일로 리디렉션하고 처음 실행할 때 결과가 예상과 다릅니다.

쉘 스크립트 - 출력을 파일로 리디렉션하고 처음 실행할 때 결과가 예상과 다릅니다.

나는 때때로 파일에서 2줄, 5줄.. 100줄 등을 반환하는 명령의 출력을 리디렉션했습니다. 나중에 다른 조건을 확인하기 위해 if 조건에서 이 파일을 사용할 것입니다.

이상한 점은 예상한 대로 데이터를 얻으려면 스크립트를 여러 번 실행해야 한다는 것입니다. 스크립트를 처음 실행하면 아무 것도 반환되지 않습니다. 이것이 첫 번째 실행에서 예상된 결과를 제공하지 않는 이유를 설명해 주시겠습니까?

코드는 AIX용이며 다음과 같습니다.

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
        chmod 777 /tmp/DISKREQ.TMP
        cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ.TMP
        cat /tmp/DISKREQ.TMP | while read line
        do
                        FSIZE_DISKREQ=`df -g | awk '$7 == "'$line'" {print $3;}'`
                        if [[ $FSIZE_DISKREQ -lt 2 ]]; then
                        echo
                         echo " Instance Home Directory $line = $FSIZE_DISKREQ "
                        else
                        echo
                                echo " Instance Home Directory $line "
                        fi
        done
else
echo
        echo "No Instance Home directory Mounted"
fi

답변1

cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ.TMP

파이프라인의 구성 요소는 병렬로 실행됩니다. 따라서 이 줄은 세 가지 명령을 병렬로 실행합니다.

  • cat /tmp/DISKREQ.TMP
  • awk '{print$6}'
  • awk 'length($0) == 22' > /tmp/DISKREQ.TMP

첫 번째 명령은 /tmp/DISKREQ.TMP읽기용으로 열려 있습니다. 세 번째 명령은 /tmp/DISKREQ.TMP다른 작업을 수행하기 전에 잘립니다. 시간에 따라 cat적어도 파일의 시작 부분을 읽을 시간이 있을 수도 있고 없을 수도 있습니다.

해결책: 입력과 동일한 파일에 쓰지 마십시오. (이름을 재사용할 수 있는 더 복잡하고 깨지기 쉬운 솔루션이 있습니다. 여기서는 복잡한 작업을 수행할 필요가 없기 때문에 솔루션을 제공하지 않겠습니다.)

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
    cat /tmp/DISKREQ.TMP | awk '{print$6}' | awk 'length($0) == 22' > /tmp/DISKREQ2.TMP
    cat /tmp/DISKREQ2.TMP | while read line

(사용하지 마세요 chmod 777. 이렇게 해도 문제가 해결되지 않으며 실제로 문제가 발생할 수 있습니다.)

하지만 이러한 임시 파일이 모두 필요한 것은 아니므로 해당 파일을 삭제하면 문제를 완전히 피할 수 있습니다. 두 번째 임시 파일을 삭제하려면 awk 체인을 while 루프에 직접 파이프하면 됩니다. 또한 쓸모없는 용도를 제거 cat하고 두 awk스크립트를 하나로 병합했습니다.

df -gt | grep /home/prods/db2/ > /tmp/DISKREQ.TMP
if [[ $? -eq 0 ]]; then
    </tmp/DISKREQ.TMP awk 'length($6) == 22 {print $6}' | while read line
    do

완전히 제거 awk하고 루프에서 필터링을 수행할 수도 있습니다 while read. 이에 대해서는 독자에게 연습으로 남겨두겠습니다.

첫 번째 임시 파일을 삭제하려면 로직을 약간 변경해야 합니다. 아무 것도 발견되지 않으면 처리할 행이 없기 때문에 while 루프 본문은 실행되지 않습니다. 그러나 이 경우 메시지를 표시하려면 몇 가지 논리가 필요합니다. awk에서 grep지시어를 사용할 수 있습니다.END

df -gt | grep /home/prods/db2/ |
awk 'length($6) == 22 {print $6}
     END {if (NR==0) print "No Instance Home directory Mounted"}' |
while read line; do …

grep통화를 와 결합 할 수 있습니다 awk. (독자를 위한 연습용입니다.) 또는 전체 필터링을 셸에서 수행할 수도 있습니다. 나는 이것이 /home/prods/db2/항상 6열의 시작이라고 생각한다.

found=0
df -gt |
while read device total used available percent mountpoint; do
    [[ $mountpoint == /home/prods/db2/* ]] || continue
    ((++found))
    [[ ${#mountpoint} -eq 22 ]] || continue
done
if ((found == 0)); then echo "No Instance Home directory Mounted"; fi

관련 정보