Cron이 실행하는 Bash 스크립트의 지역 변수

Cron이 실행하는 Bash 스크립트의 지역 변수

텍스트 파일의 파일 이름 목록을 반복하고 파일 이름에서 날짜를 유추한 다음 라이브러리 스크립트(./dropbox_uploader.sh delete [filname])를 호출하여 내 Dropbox 계정에서 원격 항목을 조건부로 삭제하는 bash 스크립트가 있습니다. 파일은 Dropbox의 API를 사용합니다. 조건은 단순히 파일이 [n]일보다 오래된지 여부입니다. n은 스크립트의 $2 위치로 전달됩니다. $1은 항목이 포함된 텍스트 파일입니다.

2개의 지역 변수 $go 및 $stay는 파일이 삭제 조건을 충족하는지 여부를 계산합니다. 스크립트가 끝나면 두 변수의 값을 사용하여 메일러를 통해 이메일을 보냅니다.

내 문제는 명령줄에서 실행하면 모든 것이 잘 작동하고 이메일 내용은 다음과 같다는 것입니다.

"Dropbox 파일이 삭제되었습니다. 554개 파일이 삭제되고 310개 파일이 보관되었습니다."

그러나 내 사용자의 crontab을 사용하여 Cron을 통해 스크립트를 실행하는 경우 로컬 변수는 모두 0/null인 것으로 보이며 이메일은 다음과 같습니다.

Dropbox 파일 삭제됨: 삭제된 파일 0개, 보관된 파일 0개.

cron 후에 스크립트를 수동으로 다시 실행할 수 있으며 변수는 0이 아닙니다.

나는 cron이 사용자를 위해 실행되는 방식에 대해 근본적인 것을 놓치고 있다고 생각하며 조언을 주시면 감사하겠습니다.

내 스크립트:

#!/bin/bash
threshold=$(date -d "$2 days ago" +%s)
go=0
stay=0
rm /home/pi/Dropbox-Uploader/camDeleteLog.txt
echo "deleting older than $2 days ago ..."

while IFS='' read -r line || [[-n "$line" ]]; do
        line=$(echo $line | xargs)      # trim spaces from the filename, just i$
        y=${line:0:4}
        m=${line:5:2}
        d=${line:8:2}
        #echo "Filedate is $y-$m-$d"
        seconds=$(date -d "$y-$m-$d" +%s)

        if ((seconds < threshold))
        then
                echo "Deleting file $go, $line"
                ((go++))
                ###echo "./dropbox_uploader.sh delete \"$line\""
               ./dropbox_uploader.sh delete "$line" >> /home/pi/Dropbox-Upload$

        else
                echo "$line is too new to delete"
                ((stay++))
        fi
done < "$1"
echo "The dropbox files were purged: $go files deleted and $stay were kept." | $

내 사용자 pi의 crontab:

0 */8 * * * /home/pi/Dropbox-Uploader/moveVideostoDropbox.py # JOB_ID_1
0 0,6,12,18 * * * Dropbox-Uploader/processDBFiles.sh # JOB_ID_2
0 1,7,13,19 * * * Dropbox-Uploader/processByDate.sh camfiles.txt 2 # JOB_ID_3

작업 3은 날짜 처리 및 삭제를 담당합니다. 작업 2와 3은 처음에 함께 실행되었지만 이것이 내 문제의 원인이라고 (잘못) 의심했기 때문에 2개의 작업을 분리하고 실험을 위해 한 시간 간격으로 별도로 실행했습니다. 작업 2의 실행 시간은 결코 아니었습니다. 1시간 이상 소요.

답변1

문제는 while 루프가 서브쉘에서 구현된다는 것입니다. 이것은앞으로그것에 대해 토론하고 잠재적인 올바른 해결책을 논의하십시오.

하지만 나는 이 문제로 인해 너무 좌절해서 완전히 피하려고 노력합니다. 파일을 사용하여 변수를 저장한다고 해서 우아함 측면에서 점수를 얻을 수는 없지만 작동합니다. 이 작은 스크립트는 요점을 보여줍니다.

#!/bin/bash
c=0
FILE=/tmp/$(basename $0).$$
while IFS= read -r line; do
    ((c++))
    echo "count=$c" > $FILE
done < somefile
. $FILE
echo "Read $count lines"
rm -f $FILE

답변2

나는 직장에서 비슷한 문제에 직면했습니다 cron. 귀하의 항목에 어떤 문제가 있는지 구체적으로 말할 수는 없지만 cron스크립트 실행과 스크립트를 실행하는 대화형 셸 간의 차이점에 대해 제가 알아낸 몇 가지 생각을 공유하겠습니다.cron

먼저 cron로컬 환경을 읽지 마십시오 . 시도할 수 있는 테스트 중 하나는 스크립트 시작 부분에서 환경 변수를 인쇄하고 대화식으로 실행한 다음 cron에서 실행하여 차이점을 확인하는 것입니다 PATH./usr/bin:/usr/sbin

#!/bin/bash
env

둘째, 홈 디렉터리에서 실행 중이라고 가정하지 마세요. 모든 경로 이름을 지정하십시오. 즉 /bin/date, /home/pi/scriptname.sh /home/pi/filename, 등이다.

셋째, 스크립트에서 로컬 환경을 가져오거나 -fShebang에 옵션을 추가해 보십시오.

#!/bin/bash
. /home/pi/.bashrc  #Not the period space at the beginning of the line

또는

#!/bin/bash -f

넷째, 스크립트의 로그 출력을 확인하여 올바른 파일을 처리하고 실제로 변수를 설정하고 있는지 확인하세요. cron로그를 읽거나(설정한 위치에 관계없이) STDIN 및 STDOUT을 파일로 리디렉션하여 이를 수행 할 수 있습니다 .

0 1,7,13,19 * * * /home/pi/Dropbox-Uploader/processByDate.sh /home/pi/camfiles.txt 2 >/dev/null 2>&1

관련 정보