在Linux中,前台任务调度与Windows的任务计划程序类似。

我在Windows上有一个批处理应用程序,每天午夜运行一次。最近,我将其转换为Linux机器上的Linux shell脚本,并希望以类似的方式每天午夜运行它。我的要求如下:
- Shell脚本在前台运行,这样我可以看到运行过程的输出并在失败时进行修正/修复。 - 类似于Windows任务计划程序的工作方式,我希望有一个可以运行的脚本列表,并且这些列表可以启用/禁用。 - (可选)理想情况下,任务计划程序的等效部分可以通过编程进行修改。这将允许我根据已运行任务的结果禁用/启用任务。
这可行吗?我看到下面的链接,但它们不包含我在我的用例中所需的所有条件。如果下面的链接之一是正确的方法,那么一个示例会非常有帮助。

请问您能解释一下为什么他们不符合您的标准吗?请具体说明。否则,我们只能猜测您已经考虑过的事情,可能会浪费我们的时间。谢谢。 - mchid
顺便说一句,要在午夜运行一个cron作业,你需要在命令或脚本路径前加上0 0 * * *。例如,要运行/home/youssif/myscript,你需要在crontab文件中使用0 0 * * /home/youssif/myscript。要编辑你的crontab文件,请使用crontab -e以当前用户身份运行该命令。或者,如果你绝对需要以root身份运行该命令,可以运行sudo crontab -e来编辑你的crontab文件。 - mchid
分钟为0。小时为0。每个月的每一天 = * 每个月 = * 每周的每一天 = * - mchid
1这对我们的网站来说是相当广泛的。如果你能解释一下你的脚本是做什么的,或者在问题中分享一下它,可能会有所帮助。理想情况下,我建议你试着去做,并找出你遇到的问题,这样你就可以提出更具体的问题了。 - Zanna
3个回答

在午夜运行定时任务,您需要在命令或脚本路径前加上:

0 0 * * *

例如,要运行/home/youssif/myscript,您可以使用:

0 0 * * /home/youssif/myscript

在你的crontab文件中。
要编辑您的crontab文件,请使用“crontab -e”命令以当前用户身份运行。或者,如果您绝对需要以root身份运行该命令,则可以运行“sudo crontab -e”来编辑您的crontab文件。

在终端中运行命令(如果以root身份运行命令,这不是一个好主意),您需要在命令或脚本中指定要使用的显示器。为此,假设您的$DISPLAY:0(默认值),您可以在命令前加上以下变量:

DISPLAY=:0

此外,通常情况下,在命令执行后终端会自动关闭,但你可以使用xterm的保持选项来保持终端开启因此,要在午夜时分在终端中运行echo "hello world"命令,你的命令应该是这样的:
0 0 * * DISPLAY=:0 xterm -hold -e 'echo "hello world"'

或者运行你的脚本:
0 0 * * DISPLAY=:0 xterm -hold -e '/home/youssif/myscript'

然而,检查cron作业的标准方法是将终端输出重定向到一个文件中,以便稍后查看。
例如,要将终端输出重定向到文件/home/youssif/helloworld.log,您可以在crontab文件中使用以下行:
0 0 * * echo "hello world" > /home/youssif/helloworld.log

或者,您还可以使用tee命令来重定向输出,就像这样:
0 0 * * echo "hello world" | tee /home/youssif/helloworld.log

最后,您可以使用cat命令查看文件的内容:
cat /home/youssif/helloworld.log

这样,命令可以在后台运行,但您仍然可以检查输出。
为了根据已运行任务的结果禁用/启用任务,我认为这更适合提出一个单独的问题。我相信你的答案会涉及在Bash脚本中使用“if then else”语句。
编辑:
正如 @Tcooper 指出的那样,我们必须添加 2>&1 来重定向所有输出,包括错误消息,所以你可能想使用类似这样的代码。
0 0 * * echo "hello world" 2>&1 > /home/youssif/helloworld.log

或者

0 0 * * echo "hello world" 2>&1 | tee /home/youssif/helloworld.log

1然而,我认为在终端中以root身份运行crontab可能不是一个好主意。这可能导致您的Xauthority文件失去正确的权限。这在Wayland上可能不是一个问题,但我不确定。这是让输出重定向到文件的最佳方式之一,也是其中众多原因之一。 - mchid
非常感谢您详细的回复。我已经测试过了,对我来说是有效的。这正是我开始所需要的。 - Youssif Saeed
2如果你想将所有的输出都发送到日志文件而不是其他地方,值得一提的是,添加"2>&1",其中2表示标准错误输出,1表示标准输出。这样可以将错误发送到标准输出,并将所有内容输出到日志文件中。或者,你也可以选择将其分别输出到两个不同的日志文件:"2>err_log.txt 1>cron_log.txt" - 如果不声明,默认情况下会将系统邮件用于cron错误,但是我发现这种方式有些烦人,至少相比使用日志文件来说。 - TCooper
3每天0 0 * * echo "hello world" > /home/youssif/helloworld.log这个命令会清空日志文件。如果使用>>,则会将内容添加到文件末尾,每天都会执行。 - A.L
2@A.L 是的,我决定选择这个方案,因为它更像是打开终端并提供单个会话的输出。我认为最好在日志前缀中添加日期,但这似乎会使本来就复杂的答案更加复杂。 - mchid

所有这些要求都可以轻松满足。在Linux中安排作业的传统方式是crontab。在Linux中安排作业的“现代”方式是systemdcrontab在Ubuntu上仍然得到支持。
您的需求1:非常不寻常:任务开始时,您是否会在午夜时分坐在电脑旁等待?否则,这就是为什么在Linux中使用日志文件的原因。系统管理员可以在白天检查日志以查看事物的进展。
如果需要,作业可以在图形终端仿真器中启动。但是,这要求您随时登录,从安全角度来看可能不太理想。 crontab和/或systemd满足需求2。您可以在systemd list-units的输出或crontab文件中看到作业列表。您可以通过systemd命令启用/禁用/删除,或者通过在任务前面添加/删除注释#符号或删除整行来进行操作。

需求3可以很容易地编写脚本。后续的任务可以读取前一个任务所做的工作,并相应地采取行动。


我必须强调,你所询问的一些内容相当不寻常,而且有充分的理由。例如,在前台运行定时任务意味着一旦输出超过终端的回滚缓冲区(即存储“输出历史记录”的容量),输出将会丢失。这就是为什么更常规的做法是将输出发送到日志文件,而不是直接在终端中显示,我强烈建议你遵循这个惯例。
话虽如此... supercronic 是一个任务调度器,你可以以普通用户(非root用户)的身份在前台运行它,并且能够直接将输出记录到终端。它读取类似于crontab的文件,你可以在其中指定要运行的脚本列表以及运行它们的时间,并且你可以安排某个自动化进程编辑该文件并向supercronic进程发出信号,以便它获取到变更。因此,它似乎符合你的所有要求。

  • 相关问题