at 工作似乎正在使用 /bin/sh 运行,尽管我有 #!/bin/bash

at 工作似乎正在使用 /bin/sh 运行,尽管我有 #!/bin/bash

我正在尝试使用 运行作业at,并且我有一个bash脚本(我确实有第一行),但是由于使用和在脚本中#!/bin/bash作业失败,我在它生成的 中看到以下内容:[[]]mail

=sh: 58: [[: not found
=sh: 58: [[: not found
=sh: 58: [[: not found
=sh: 58: [[: not found
=sh: 58: [[: not found

/bin/sh是一个链接dash,但如果我的脚本中有 she-bang 行#!/bin/bash- 不应该使用它吗bash

PS 如果我只是在提示符下运行脚本bash- 它可以正常工作,没有错误(并且具有可执行权限)。

- 编辑 -

我这样添加工作:

$ at 1:30 am today -f /path/to/my/script.sh



$ which bash 
/bin/bash

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash

$ uname -a
Linux server1 3.5.0-46-generic #70~precise1-Ubuntu SMP Thu Jan 9 23:55:12 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

答案1

POSIX 定义了可以使用环境变量作为 的替代/bin/sh,但没有限制它:

确定用于调用 at-job 的命令解释器的名称。如果变量未设置或为空,则应使用 sh。如果它设置为 sh 名称以外的值,则实现应执行以下操作之一:使用该 shell;使用 sh;使用用户数据库中的登录 shell;或任何前述伴随着所选择的警告诊断。

at 的某些实现可以让您选择要运行的 shell,例如-kKorn shell、-cC-shell。并且并不是所有的实现都at允许SHELL替代sh。所以 POSIX 也保证使用另一个 shell 的可靠方法是显式调用它:

某些实现不允许使用 SHELL 替换不同的 shell。例如,System V 系统已在 /etc/passwd 中使用用户的登录 shell 值。要可靠地选择另一个命令解释器,用户必须将其作为脚本的一部分包含在内,例如:

1800 美元

myshell myscript

环氧乙烷

工作...在...$

一种简单的方法是,使用bash运行脚本bash script作为 stdin 传递到at

echo "bash /path/to/yourscript" | at <time>

例子:

echo "bash /path/to/yourscript" | at 16:30

bash /path/to/yourscript将于今天 16:30运行。

答案2

atbatch:

使用 /bin/sh 从标准输入或指定文件读取稍后要执行的命令。

POSIX 定义at的输入作为:

一个文本文件,由 中描述的 shell 命令语言可接受的命令组成外壳命令语言

也就是说,它是必需的成为 POSIXsh脚本。 Bash 允许 Bashisms 通过,即使它作为 运行sh,但dash很严格。该脚本不是作为可执行文件运行,而是直接使用 运行sh,因此任意二进制文件或 Python 脚本也无法运行。


不过,你可能能做的就是强迫自己bash无论如何。就像是:

[ "$BASH_VERSION" ] || exec bash "/path/to/script"

在文件顶部,bash当脚本尚未以这种方式解释时,应该让脚本重新执行自身。 shell 不会为执行未到达的代码生成语法错误,因此以后的使用[[并不重要。您也许可以使用$0而不是路径,但它似乎在at实现之间不一致,并且没有任何规范暗示它应该工作,因此路径会更可靠。

答案3

我的答案与 Gnouc 的类似,但我相信我对“为什么?”有更好的解释。当你说的时候at … -f /path/to/my/script.sh,你是在告诉你at要读书/path/to/my/script.sh。它将您的脚本复制到某处(可能位于 下的某处/var/spool/cron),以便atd作业at守护程序 可以将脚本的内容传递给/bin/sh。此时,#!/bin/bashshe-bang 行只是一个注释,您的[[…]]用法是错误的。

你想做的不是at内容你的脚本,但给它姓名, 经过

$ echo /path/to/my/script.sh | at 1:30 am today

或者

今天凌晨 1:30 $
/path/to/my/script.sh
Ctrl+D

这样,/bin/sh将看到/path/to/my/script.sh 并将其作为命令执行。和然后she-bang 行将完成其工作,导致bash被调用。

PS 我的答案(就像 Gnouc 的)有一个“功能”,如果您在现在到今天凌晨 1:30 之间更改脚本, atd将运行修改后的版本。 (这与您的方法相反,使用-f, whereat会在运行时复制脚本的副本at。)特别是,如果删除或重命名脚本,则不会运行任何内容。

相关内容