我有一个 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