如何通过Cron运行Bash脚本

21

我看到其他类似的问题,但找不到如何通过Crontab正确运行Bash脚本的实际信息。.sh文件位于用户目录中(在我的情况下是serverpilot)。

该脚本试图复制apps文件夹的内容并发送到我的S3存储桶。当在终端中使用sh backupS3.sh运行该脚本时,它可以完美地工作,但是在Cron中却没有反应。我看到人们参考了PATH变量等,但不知道从哪里开始!

/backupS3.sh

#!/bin/sh
echo 'Started backing to S3'
date +'%a %b %e %H:%M:%S %Z %Y'
aws s3 sync /apps s3://bucketname
date +'%a %b %e %H:%M:%S %Z %Y'
echo 'Finished backing to S3'

定时任务(crontab)

*/10 * * * * /backupS3.sh >> backupS3.log  

有人能指出我做错了什么吗?谢谢!

编辑:我在cron命令的末尾添加了2>&1,现在日志文件里有一些内容:

/bin/sh: 1: /backupS3.sh: not found


抱歉 @JordonPhillips,我认为脚本没有运行,因为同步从未发生,回显语句也没有打印到日志中。 - André Goldstein
我应该指出它确实创建了日志文件,但是日志文件仍然为空。 - André Goldstein
1
你的脚本是一个 sh 脚本,但用 bash 运行它是无害的。反之则通常不成立。无论哪种情况,都应该在它跳起来咬你之前了解它们之间的区别。例如,请参阅 https://dev59.com/g2025IYBdhLWcg3w6aUX - tripleee
1
此外,这并不是一个编程问题;在将来,serverfault会是更好的选择。 - Mark Reed
明白了@MarkReed,如果能移动的话那就太好了,如果不行的话,下次我会去找一下那边的东西。谢谢。 - André Goldstein
显示剩余3条评论
3个回答

17
在路径名中,前导的 / 并不意味着「主目录」;它总是指文件系统的根目录,无论你以谁的身份登录。你需要使用实际的完整绝对路径来调用脚本(例如 /home/serverpilot/backupS3.sh)。如果 crontab 属于与脚本所在目录相同的用户,则可以使用 "$HOME"/backupS3.sh,系统会自动填充他们的主目录路径。或者更简单地,只需使用 ./backupS3.sh,因为 cron 作业启动时,工作目录等于其所有者的主目录。

如果这样仍然不起作用,那么要么你所说的「用户目录」与 POSIX 的「主目录」概念不同,要么脚本不可执行(你可以运行命令 chmod +x backupS3.sh 来修复)。

如果你不确定完整路径是什么,只需在保存脚本的相同目录中运行 pwd 命令,然后将输出和一个斜线放在脚本名称前面即可。


1
谢谢,我应该在哪里运行chmod命令?只需要在终端中运行一次吗? - André Goldstein
1
是的,它只需要运行一次。 - Mark Reed
非常感谢@MarkReed,现在我的日志中收到以下内容/srv/users/serverpilot/backupS3.sh: 4: /srv/users/serverpilot/backupS3.sh: aws: not found。不确定这是否仍然表示找不到脚本或者是使用AWS CLI的问题? - André Goldstein
aws 命令不在 cron 作业的 $PATH 中。您需要指定它的完整路径(可以使用 which aws 获取)。 - Mark Reed
这个答案非常有帮助,已经帮我成功运行了脚本。现在我遇到了一个 AWS 凭证错误,但我认为这是由于最初将 AWS 配置为根用户所致。 - André Goldstein
显示剩余7条评论

11

我曾经遇到过相同的问题,即日志文件为空,唯一的方法是在cron job的结尾添加2>&1来查看正在发生什么。

*/10 * * * * /home/users/me/backupS3.sh >> /home/users/me/backupS3.log 2>&1

如果有人想知道这里的2>&1实际上是什么意思,这里是一个简短的解释:

2 - 是用于识别stderr的文件描述符

1 - 是用于识别stdout的文件描述符

因此,2>&1基本上可以理解为:将stderr重定向到stdout


你可以通过使用&>> /home/users/me/backupS3.log来跳过2>&1部分,其中&>>会将所有的输出文件描述符重定向到日志文件,而不仅仅是1/stdout - jlucktay

8

首先,将#!/bin/sh更改为#!/bin/bash,接下来使用脚本的完整路径(文件名中也不需要.sh)

*/10 * * * * /home/users/me/backupS3.sh >> /home/users/me/backupS3.log  

1
bash提示是一个转移注意力的手段;你的脚本目前并不包含任何Bash特有的语法。 - tripleee
感谢 @triplee 提供的信息。 - André Goldstein
@tripleee 红鲱鱼?这是额外的和有建设性的,因为用户将其发布为“bash问题”。不需要进行负投票,因为路径是问题所在。 - SaintHax
更改Shebang的建议是不正确的,它并不能帮助解决问题。 - tripleee
1
事实上,我已经阅读了整个答案,如果您删除不正确的部分,那就没问题了。有很多情况下这些建议确实会有帮助,但这并不是其中之一。无论如何推荐它看起来像是货柜崇拜编程,我认为这是基于错误原则的(顺便说一下,“principals”不是正确的拼写)。 - tripleee
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接