如果我在 cron 中为 SHELL 分配两个 shell 可以吗?

如果我在 cron 中为 SHELL 分配两个 shell 可以吗?

最近我开始逐渐将 shell 切换到 正因为如此,我考虑将其路径分配给 cron 中的 SHELL。

阅读了手册的大部分内容后man 5 crontab,我查看了 PATH 并复制了在:尝试将两个 shell 分配给 SHELL 的值之间使用 in 的约定:

SHELL=/bin/bash:/home/jerzy/.cargo/bin/nu

它不起作用,我的 crontab 中的脚本没有完成它们的工作。而 和 都SHELL=/bin/bash工作 SHELL=/home/jerzy/.cargo/bin/nu得很好。

我可以给SHELL分配两个shell吗?这样做有意义吗?

答案1

不,您不能将两个 shell 分配给SHELLcron需要知道要启动哪个 shell,只能有一个。SHELL中的变量未crontab指定可能的shell,它指定外壳来使用。cron读取 中的值SHELL(如果有),并将其用作运行命令;它不解释:或任何其他符号。

后备也不起作用:如果某件事因 失败nucron则无法知道它是因为nu还是其他原因而失败。大多数脚本都是为给定的解释器(在其 shebang 中指定)编写的,您不能尝试使用一个解释器运行它们,然后再使用另一个解释器运行它们。同样,crontab条目的编写是SHELL考虑到指定的(如果不是默认的/bin/sh)。

答案2

不,有多个 shellSHELL是没有意义的,原因如下@Stephen 在他们的回答中描述了。但是,该SHELL变量仅控制 shellcron用于运行该crontab行中的立即命令部分;至少在 Linux 系统上经常使用的 Vixie cron 中,SHELL可以在crontab.这Debian 手册页crontab(5)

crontab 文件是从上到下解析的,因此任何环境设置都只会影响文件中位于其下方的 cron 命令。

这句话看起来可能是 Debian 添加的,但在我尝试过的 CentOS 系统上似乎效果相同。但正如 Toby Speight 的评论中所指出的,环境变量赋值crontab根本不是 POSIX 功能,所以 YMMV。


因此,无论 cron 如何,您都应该能够执行以下操作:

* * * * * /path/to/somescript.py maybe 
* * * * * /path/to/otherscript.pl some
* * * * * /path/to/thirdscript.sh args

其中脚本有正确的 hashbang 行,例如#!/usr/bin/python3#!/usr/bin/perl#!/bin/bash其他。SHELL只需要设置为可以将/path/to/somescript.py maybe等作为命令并使用参数运行该脚本的东西。大多数 shell 都相同地支持琐碎的内容,因此,如果您将复杂的内容放在单独的脚本中并保持行crontab简单,则可以在脚本本身中使用任何 shell 或脚本语言。


而且,如果您需要在直接 crontab 命令中使用不同的 shell,您可以这样做,至少在 Vixie cron 中:

SHELL=/bin/bash
* * 8-14 * * if test "$(date +\%w)" = 0; then echo $BASH_VERSION > /tmp/bashtest; fi
SHELL=/usr/bin/fish
* * 8-14 * * if test (date +\%w) = 0; echo $FISH_VERSION > /tmp/fishtest; end

两者都检查当天是否是星期日,如果是,则打印 shell 版本,一种使用 Bash,一种使用 Fish。 (当然,这只是一个示例,但由于 cron 时间设置的工作方式,在一个月的第一个/第二个/最后一个特定工作日运行是您可能希望在 crontab 上使用 shell 代码的常见情况之一命令。)

另外,顺便说一句,您在评论中提到 Nu 不支持带有 的多行命令\,并且希望您可以在那里使用 Bash。请注意,crontab 行中不能有多行命令:命令本身必须位于文件中的一行上,并且当cron采用%符号作为换行符时,第一行后面的行将发送到命令。 (这就是为什么我们需要转义上面%格式字符串中使用的内容date。)

相关内容