【问题标题】:php script which uses system command and running in background -- will it still run in order?使用系统命令并在后台运行的 php 脚本——它还会按顺序运行吗?
【发布时间】:2015-04-18 18:27:59
【问题描述】:

我有以下脚本update_pos_databases.php(简化版)

<?php
ini_set('display_errors', 1);
set_time_limit(0);
$db_host = 'localhost';
$db_user = 'root';
$db_password = 'PASSWORD';

$databases = array('example');

$db_host = escapeshellarg($db_host);
$db_user = escapeshellarg($db_user);
$db_password = escapeshellarg($db_password);

foreach($databases as $database)
{
    echo "Running queries on $database\n***********************************\n";
    system("mysql --host=$db_host --user=$db_user --password=$db_password -v -v -v $database < ../update.sql"); 
    echo "\n\n";
}
?>

当我调用它时,我会执行以下操作:

nohup php update_pos_databases.php > results.txt 2>&1 </dev/null &

由于我在 php 脚本中使用系统命令,如果系统命令之一由于某种原因失败,使用上述命令是否会导致任何问题?我认为我正在做的很好;但在部署此更改之前,我想知道在使用 nohup 调用的脚本中使用 system() 的任何危险。 (我不希望脚本因为某种随机原因而死掉)。

上面脚本中的单个系统命令也会被阻塞吗?我想确保它们一个接一个地运行,而不是同时运行。

【问题讨论】:

  • 如果mysql命令出错我会错过这个吗?还是所有的mysql都被定向到标准输出?看起来我仍然可以标准输出
  • 啊,对不起,我有点宿醉,你说得对。 :)
  • 如果你想一个一个地运行它们——那么不要试图把它传递给某个地方。运行它而不放置到后台,因此主脚本实际上会等到该过程完成。而且-不-一旦将其置于后台,就不能保证它会“按顺序运行”-只能保证“开始时间”将遵循您的循环逻辑。但是相应的脚本将如何以及何时完成 - 是另一回事
  • nohup 只将php进程置于后台,不影响系统进程的顺序,它们会按照循环确定的顺序执行,等待完成。此外,您不需要 & 将进程置于命令行的后台,nohup 已经做到了。反正我对系统内部的

标签: php


【解决方案1】:

nohup 将 keep the process going 即使在终端断开连接(例如,注销)之后,&amp; 也会将该进程置于后台。是的,每个system 都会在迭代到下一个循环之前运行到完成:php 不知道它正在无中断运行。

以下是显示这些行为的简化示例:

$ cat demo.php
<?php foreach (range(1,10) as $i) system("/bin/date && /bin/sleep $i");

# run it without nohup, then simulate a logout
$ php demo.php > results.txt 2>&1 </dev/null &
$ kill -HUP $!
$ cat results.txt
Tue Sep  8 12:27:20 EDT 2015
Tue Sep  8 12:27:21 EDT 2015
[1]+  Hangup                  php demo.php > results.txt 2>&1 < /dev/null    

$ # do it again, this time with nohup
$ nohup php demo.php > results.txt 2>&1 </dev/null &
$ kill -HUP $!  # no effect
$ cat results.txt
Tue Sep  8 12:08:56 EDT 2015
Tue Sep  8 12:28:28 EDT 2015
Tue Sep  8 12:28:29 EDT 2015
Tue Sep  8 12:28:31 EDT 2015
Tue Sep  8 12:28:34 EDT 2015
Tue Sep  8 12:28:38 EDT 2015

因此,您的脚本似乎是按照您的预期编写的。我建议的唯一修改是将 MySQL 命令行可执行文件的完整路径放在系统语句中。

【讨论】:

    【解决方案2】:

    只是概念验证

    <?php
    
    $commands = array('uptime', 'uptime', 'jhsddf', 'uptime');
    foreach ($commands as $exe) {
      echo "Begin $exe\n";
      system("$exe");
      sleep(rand(1,5));
      echo "End $exe\n";
    }
    
    ?>
    

    正如您将看到的,这段代码会一一执行 uptime 命令,如果出现类似 jhsddf 命令的问题,它将显示错误并继续执行。

    结果:

    Begin uptime
     17:59:43 up 127 days,  7:41,  1 user,  load average: 0.24, 0.20, 0.18
    End uptime
    Begin uptime
     17:59:44 up 127 days,  7:41,  1 user,  load average: 0.24, 0.20, 0.18
    End uptime
    Begin jhsddf
    sh: jhsddf: not found
    End jhsddf
    Begin uptime
     17:59:53 up 127 days,  7:41,  1 user,  load average: 0.20, 0.19, 0.18
    End uptime
    

    拥有不同命令的唯一选择是在每个系统进程中调用 nohup(在你的情况下是 nohup mysql...)。它们将具有脚本定义的开始顺序,但您将无法确保完成顺序,因为它们将同时执行

    【讨论】:

    • 感谢您的回答。我不想要不同的订单;我只是想确保 nohup 在顺序方面不会导致 php 系统命令出现问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 2013-06-12
    • 2011-02-12
    • 1970-01-01
    • 2011-09-15
    • 2023-03-10
    相关资源
    最近更新 更多