我正在尝试使用 运行作业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,例如-k
Korn shell、-c
C-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
使用 /bin/sh 从标准输入或指定文件读取稍后要执行的命令。
一个文本文件,由 中描述的 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/bash
she-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
。)特别是,如果删除或重命名脚本,则不会运行任何内容。