由 Cron 运行的 Bash 脚本中的局部变量

由 Cron 运行的 Bash 脚本中的局部变量

我有一个 bash 脚本,它循环遍历文本文件中的文件名列表,从文件名推断出日期,然后调用库脚本 (./dropbox_uploader.sh delete [filname]) 有条件地删除我的 Dropbox 帐户中的远程文件使用 Dropbox 的 API。条件只是文件是否早于 [n] 天。 n 被传递到脚本中的位置 $2。 $1 是包含条目的文本文件。

2 个局部变量 $go 和 $stay 计算文件是否符合删除条件的实例。在脚本的最后,我使用两个变量的值通过邮件程序发送了一封电子邮件。

我的问题是,如果我从命令行运行它,一切都会正常,并且电子邮件内容如下:

“Dropbox 文件已被清除:删除了 554 个文件,保留了 310 个文件。”

但是,如果脚本使用我的用户的 crontab 通过 Cron 运行,那么局部变量似乎都为零/空,并且电子邮件为:

Dropbox 文件已被清除:删除了 0 个文件,保留了 0 个文件。

我可以在 cron 运行后再次手动运行脚本,并且变量不为零。

我认为我错过了有关 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 循环是在子 shell 中实现的。这是一个头讨论它以及潜在的正确解决方案。

但我对这个问题感到非常沮丧,以至于我试图完全避免它。使用文件来保存变量不会赢得优雅的分数,但它确实有效。这个小脚本说明了这一点。

#!/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。我无法具体说明您的条目有什么问题,但我将分享一些我注意到的关于运行脚本和运行脚本的交互式 shellcron之间差异的想法。cron

首先,cron不读取您的本地环境,PATH我相信默认是/usr/bin:/usr/sbin.可以尝试的一项测试是在脚本开头打印环境变量并以交互方式运行,然后从 cron 运行并查看差异。

#!/bin/bash
env

其次,不要假设您正在从主目录运行。指定所有路径名。即/bin/date, /home/pi/scriptname.sh /home/pi/filename, 等

第三,尝试在脚本中获取本地环境和/或尝试将选项添加-f到您的 shebang

#!/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

相关内容