在 Ubuntu 16.04 xenial 和 Bash 4.3.48 中LEMP,我创建了一个舒适度函数创建一个PHP信息文件(为了更好地了解我的php环境),然后在2小时后删除它。但我从终端调用该函数时遇到问题。
重现我的问题的步骤
1)创建一个带有函数的文件:
#!/bin/bash
drt="/var/www/html"
pif() {
cat > "$drt"/info.php <<< "<?php phpinfo();"
rm "$drt"/info.php | at now + 2 hours
}
2)获取该文件的来源。
3)在终端中调用该函数:
pif
info.php
遗憾的是,没有为我创建同名的文件/var/www/html
。我仔细检查了这一点。
以下是以这种方式执行该函数的完整跟踪 ( pif
):
+ pif
+ cat
+ at now + 2 hours
+ rm /var/www/html/info.php
warning: commands will be executed using /bin/sh
job 17 at Fri Apr 6 05:43:00 2018
另一方面,当我尝试不从函数创建文件时,只需执行:
cat > "$drt"/info.php <<< "<?php phpinfo();"
该文件创建良好。
我的问题
为什么从终端直接执行可以工作,但包含代码的函数执行失败?
更新
1)我确实有写入权限/var/www/html
。
2)我通过以下方式获取该文件:
source myFunctions.sh
3)的输出type -a pif
是:
pif is a function
pif ()
{
cat > "$drt"/info.php <<< "<?php phpinfo();";
rm "$drt"/info.php | at now + 2 hours
}
答案1
您的函数创建info.php
但立即删除它。
创建文件后info.php
,您似乎打算使用下一个命令日程其删除:
rm "$drt"/info.php | at now + 2 hours
但事实并非如此。那运行rm
现在的命令,然后管道它是标准输出(通常不会写入任何内容,rm
默认情况下会静默成功)到at
命令的标准输入。
如果您确实需要让该 shell 函数安排文件的删除,那么您应该在at
的标准输入上以文本形式提供该命令,或者安排一个运行删除文件的单独脚本的命令。看在(1)有关如何安排命令运行的详细信息at
。
请注意,您实际上可以从跟踪中看到正在发生的事情:
+ at now + 2 hours
+ rm /var/www/html/info.php
管道中的命令异步运行。该跟踪表明,当您向 shell 发出两个由 . 分隔的命令时,它会按照应有的方式运行|
。它运行at
出现在管道右侧的命令,以便它可以接收从该rm
命令通过管道传输的数据。然后它立即运行rm
命令。当它这样做时,该rm
命令删除了该文件。为了防止这种情况,您必须告诉at
稍后运行该命令,不是立即在管道中运行它。
drt
如果您想使用类似于您所拥有的内容,并且前提是(在您的示例中)的值/var/www/html
不包含任何空格或其他将被/bin/sh
(at
用于运行命令)特殊处理的字符,那么您可以使用:
at now + 2 hours <<<"rm -- $drt/info.php"
如果已知 的值drt
不是以 a 开头-
,则--
可以安全地省略该参数。在您的情况下,您似乎可以控制$drt
,这似乎是一个非常安全的选择。
您可能会发现通过安排命令在较早的时间运行来测试at
命令很方便,例如立即 ( at now
) 或一分钟后 ( at now + 1 minute
)。
答案2
我已经接受了 Eliah 的回答,我认为应该点赞,但这是我为自己创建的解释,涉及我特别使用的一些不同的代码。
为什么上面的代码是错误的:
看来我的命令由于缺少echo
.
考虑我原来的命令:
rm "$drt"/info.php | at now + 2 hours
发生的事情是rm
创建文件后直接运行,直到那时,一个空跑at
。
在一个更简单的图中:
1)使用此处字符串创建 phpinfo。
2)删除 phpinfo
rm
(任何地方都不再通过管道传输任何内容)。3)等待 2 小时(在本例中没有任何结果)。
正确的代码
我应该做的(而且效果很好,我已经仔细检查过)是这样的:
echo "rm $drt/info.php" | at now + 2 hours
该命令的示意图如下:
1)使用此处字符串创建 phpinfo。
2)回显
rm
命令,但将输出通过管道传输echo
到以下 (at
) 命令中。3)
rm
现在+2小时。
结论
当使用与我类似的代码时,如果您按照上面的代码示例在 范式中工作,请确保将您想要调度的命令用 包装起来at
。echo ""
do X at now + y time (from now)