假设我有一个名为的脚本文件pma.sh
:
#!/bin/bash
apt-get install phpmyadmin -y
function uninstpma {
apt-get purge phpmyadmin -y
}
uninstpma ()
要使用 运行整个脚本,at
我可以这样做./pma.sh | at 'now + 2 minuts'
。但我不希望它用于整个脚本;相反,只用于脚本内的函数。所以:
我怎样才能仅使用该at
实用程序来安排该功能?
答案1
如果可以,请将函数定义移到单独的“库”文件中。
如果可以编辑脚本,那么最好的解决方案可能是将函数定义从脚本移出到单独的文件中。该文件包含函数定义,然后脚本将获取该文件(以及从脚本中删除函数,您必须向脚本添加执行此操作的命令),并且您正在运行的任何其他脚本或命令也将获取该文件at
。
例如,现在你pma.sh
看起来像这样:
!#/bin/bash
apt-get install phpmyadmin -y
function uninstpma {
apt-get purge phpmyadmin -y
}
uninstpma
(您的原始脚本格式不同,并且uninstpma ()
最后一行也是这样。参数列表(无论是空的还是其他)在 Bourne 风格的 shell 中都不括在括号中。而且,至少在我的系统上的 bash 4.3.46 中,这是不是被接受为替代语法。因此,我认为这()
是一个错误并将其删除。)
您可以创建一个名为pma_funcs.sh
(您可以随意命名)的新文件,其中包含:
function uninstpma {
apt-get purge phpmyadmin -y
}
它还可以包含额外的函数定义。
它没有#!/bin/bash
hashbang 行,也不需要标记为可执行,因为它不会作为自包含脚本执行。相反,它实际上将被用作其他脚本的库。
所有调用者将首先获取包含函数定义的文件。
假设你将其放入pma.sh
一个/opt/pma-helpers
目录中。(我不是说你应该把它放在那里——它很可能不是最好的地方——我只是必须选一个地方。)然后你可以修改pma.sh
:
!#/bin/bash
. /opt/pma-helpers/pma_funcs.sh
apt-get install phpmyadmin -y
uninstpma
.
你的脚本的内置来源也就是说它使 shell 执行作为其参数传递的文件中的所有命令( /opt/pma-helpers/pma_funcs.sh
)。由于没有创建子 shell 来运行它们(请参阅这个问题和那个),定义新变量和函数的命令对调用者生效。(调用者是运行的脚本.
,而不是运行的任何脚本)它,如果有的话,除非其他脚本.
也使用。)
然后,当您需要修改函数时,您只有一个副本可以编辑 - 中的副本。新版本将在已更新的pma_funcs.sh
shell 实例中定义。. /opt/pma-helpers/pma_funcs.sh
pma_funcs.sh
在使用函数之前,您必须获取包含函数定义的文件,但不必在脚本的最顶部这样做(除非下一行使用其中一个)。
要在运行时调用这些函数之一at
,您需要在运行的代码中获取脚本at
。
您的示例代码需要bash
,但at
使用 运行命令sh
。
然而,在这个特殊情况下,还有一个额外的复杂因素at
运行脚本/bin/sh
, 哪个在 Ubuntu 中由 提供dash
,而不是bash
但是您的脚本使用了 Bash 特定的功能,而 Dash 等更基本的 POSIX shell 并不支持该功能。
(该功能是语法function name compound-command
用于定义函数。与所有符合 POSIX 的 shell 一样,Dash 也支持函数,但只支持标准语法。Bash 也支持该语法,因此name () compound-command
如果这是你正在使用的唯一 Bash 特定功能,那么你可以切换到标准语法。不过,我猜这不是你计划使用的唯一功能,因为 Bash 提供了许多其他方便的扩展,而且替换起来并不那么简单。)
因此,您应认真考虑编写一个 Bash 脚本并使用 调度该脚本at
。假设您编写了这个 at-job 脚本/opt/pma-helpers/pma_job
。(再次说明,我没有理由认为这是将其放在系统上的合理位置。您应该将其放在对您正在做的事情有意义的地方。)此文件可能包含:
#!/bin/bash
# any commands here must not use the functions; they're not sourced yet
. /opt/pma-helpers/pma_funcs.sh
# you can put commands here if you want
uninstpma
# you can put commands here, too, if you want
将脚本标记为可执行(chmod u+x /opt/pma-helpers/pma_job
,假设 at 作业将作为脚本的所有者运行)。然后,当您想要安排它时,您将创建一个由运行该脚本的单个命令组成的 at 作业:
at 'now + 2 minutes' <<<'/home/ek/source/pma_job'
(我用过这里是字符串在调用的命令中at
)
如果您确实不想这样做,则不必将这项工作放入专用的脚本文件中。
您的 Bash 脚本将能够获取并运行用 Bash 编写的所有 shell 函数。但是,如果出于某种原因您确实不想运行单独的脚本,那么您还有其他选择。只要确保您的依赖于 bash 的 shell 函数在 bash shell 中定义和使用就足够了。
例如,您可以在此处使用嵌套的文档:
at now <<'EOF'
bash - <<'EOF_BASH'
# any commands here must not use the functions; they're not sourced yet
. /opt/pma-helpers/pma_funcs.sh
# you can put commands here if you want
uninstpma
# you can put commands here, too, if you want
EOF_BASH
EOF
这有点复杂。你可能更适合有额外的pma_job
脚本。