Nic*_*mas 5 bash environment-variables function at
我想在预定的时间执行 Bash 函数。我认为正确的工具是at
命令。
但是,它似乎不起作用。
function stupid () {
date
}
export -f stupid
cat << EOM | at now + 1 minute
stupid
EOM
Run Code Online (Sandbox Code Playgroud)
等待一分钟后,我检查了我的邮件,这是我看到的错误:
sh: line 41: syntax error near unexpected token `=\(\)\ {\ \ date"
"}'
sh: line 41: `"}; export BASH_FUNC_stupid()'
Run Code Online (Sandbox Code Playgroud)
我不明白这里出了什么问题,尤其是因为我知道该功能有效。
$ stupid
Fri May 29 21:05:38 UTC 2015
Run Code Online (Sandbox Code Playgroud)
查看错误,我认为使用了不正确的 shell 来执行函数(sh
而不是bash
),但是如果我检查$SHELL
它/bin/bash
,我看到它指向,并且手册页at
说:
$ echo $SHELL
/bin/bash
$ man at
...
SHELL The value of the SHELL environment variable at the time
of at invocation will determine which shell is used to
execute the at job commands.
Run Code Online (Sandbox Code Playgroud)
所以 Bash 应该是运行我的函数的 shell。
这是怎么回事?有没有办法让我的 Bash 函数运行at
?
Gil*_*il' 10
Bash 函数通过环境导出。该at
命令通过生成重现环境的 shell 代码使脚本可以使用环境、umask 和调用进程的当前目录。你的 at 作业执行的脚本是这样的:
#!/bin/bash
umask 022
cd /home/nick
PATH=/usr/local/bin:/usr/bin:/bin; export PATH
HOME=/home/nick; export HOME
…
stupid
Run Code Online (Sandbox Code Playgroud)
在较旧版本的 bash 中,函数被导出为一个变量,该变量带有函数名和一个()
以定义函数的代码开头并由其组成的值,例如
stupid="() {
date
}"; export stupid
Run Code Online (Sandbox Code Playgroud)
这使得许多场景容易受到安全漏洞Shellshock 漏洞(由Stéphane Chazelas发现)的攻击,该漏洞允许任何人以任何名称注入环境变量的内容,以在 bash 脚本中执行任意代码。带有 Shellshock 修复的 bash 版本使用不同的方式:它们将函数定义存储在一个变量中,该变量的名称包含在环境变量中找不到的字符,并且 shell 不会解析为赋值。
BASH_FUNC_stupid%%="() {
date
}"; export stupid
Run Code Online (Sandbox Code Playgroud)
由于%
, 这不是有效的 sh 语法,甚至在 bash 中也不是,因此 at 作业失败,无论它是否尝试使用该函数。在许多 Linux 发行版中使用的 at的Debian 版本已更改在 3.16 版为仅导出在 shell 脚本中具有有效名称的变量。因此,较新版本的 at 不会通过后 Shellshock bash 导出的函数,而较旧的版本会出错。
即使使用前 Shellshock 版本的 bash,导出的函数也仅适用于从 at 作业启动的 bash 脚本,而不适用于 at 作业本身。在 at 作业本身中,即使它是由 bash 执行的,stupid
也只是另一个环境变量;bash 仅在启动时导入函数。
要将函数导出到 at 作业,而不管 bash 或 at 版本如何,请将它们放在一个文件中并从您的作业中获取该文件,或者直接将它们包含在您的作业中。要以可回读的格式打印出所有定义的函数,请使用declare -f
.
{ declare -f; cat << EOM; } | at now + 1 minute
stupid
EOM
Run Code Online (Sandbox Code Playgroud)