文件创建不会在源文件的函数内进行

文件创建不会在源文件的函数内进行

在 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/shat用于运行命令)特殊处理的字符,那么您可以使用:

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小时。

结论

当使用与我类似的代码时,如果您按照上面的代码示例在 范式中工作,请确保将您想要调度的命令用 包装起来atecho ""do X at now + y time (from now)

相关内容