【问题标题】:How to set timeout for a ssh command executed with php?如何为使用 php 执行的 ssh 命令设置超时?
【发布时间】:2012-06-13 00:30:28
【问题描述】:

我使用 php 通过包装函数通过 ssh 执行 scp 命令。移动是在本地和远程服务器之间进行的。

我大致知道脚本应该执行多长时间,如果 scp 进程花费的时间太长(由于目标服务器陷入困境或其他网络问题),我想终止它。当前发生这种情况时,scp 进程将完全锁定,直到重新启动目标服务器或从命令行手动终止 scp 进程。

我可以将某种超时传递给 shell_exec() 以退出其正在执行的工作并继续执行脚本吗?

【问题讨论】:

  • PHP 脚本是否作为 HTTP 请求的一部分运行?

标签: php timeout


【解决方案1】:

您可以编写一个使用 shell_exec 调用的 shell 脚本,该脚本会在一段时间后自动终止,然后您可以直接调用该脚本而不是 scp,这样的脚本将接受参数或硬编码。这是一个脚本示例,它采用 2 个参数,2 秒是它在终止进程之前等待的秒数。 (sleep 也接受分钟、我们的或天,只需附加 m、h 或 d)

 #!/bin/sh
 scp $1 &
 pid=$!
 sleep $2
 kill $pid

edit:或者使用nickb的解决方案,那就更好了。 :)

【讨论】:

    【解决方案2】:

    使用 UNIX timeout 实用程序包装您的命令。

    system('timeout n ../my/aa');
                    ^
    

    n 是以秒为单位的整数值。

    如果命令超时,则以状态 124 退出。否则,退出 状态为 COMMAND。如果未指定信号,则发送 TERM 超时时发出信号。 TERM 信号杀死任何不执行 阻止或捕获该信号。对于其他过程,可能需要 使用 KILL (9) 信号,因为无法捕获此信号。

    【讨论】:

    • 我发现这对 php 非常有用,您可以输出命令。如果它在 x 秒后超时,则返回值为 null。然后您可以使用 php strlen 检查预期的输出字符串长度。如果长度为 0,则命令在完成之前退出。 IE:超时。
    【解决方案3】:

    您可以使用带超时的 PHP 套接字:

    $process = proc_open($command,$descriptorspec,$pipes);
    stream_set_timeout($pipes[1], 30);
    $line=stream_get_contents($pipes[1]);    // read data
    while($line)stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    

    【讨论】:

      【解决方案4】:

      或者您可以使用 select 等待命令返回。 这是从php手册复制的代码示例 可以参考proc_open()和stream_select()

      <?php
      $descriptorspec = array(
         0 => array("pipe", "r"),  
         1 => array("pipe", "w"),
         2 => array("file", "/tmp/error-output.txt", "a")
      );
      
      $pipes = array();
      $process = proc_open('sleep 5 && echo hello', $descriptorspec, $pipes);
      $timer = 0;
      if (is_resource($process)) {
          while(true) {
              $write = null;
              $except = null;
              $read = array($pipes[1]);
              $ret = stream_select($read, $write, $except, 1);
              if ($ret === false) {
                  echo "error";
                  break;
              } else if ($ret == 0) {
                  echo "waiting for " . ++$timer . "sec" . PHP_EOL;       
              } else {
                  echo stream_get_contents($pipes[1]);
                  break;
              }
          }
          fclose($pipes[1]);
          $return_value = proc_close($process);
          echo "command returned $return_value\n";
      }
      
      ?>
      

      【讨论】:

        【解决方案5】:

        您可以使用 phpseclib 执行以下操作:

        <?php
        include('Net/SSH2.php');
        
        $ssh = new Net_SSH2('www.domain.tld');
        if (!$ssh->login('username', 'password')) {
            exit('Login Failed');
        }
        
        $ssh->setTimeout(5);
        echo $ssh->read();
        //$ssh->write('whatever');
        ?>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-22
          • 1970-01-01
          • 2011-09-10
          • 1970-01-01
          • 1970-01-01
          • 2013-08-24
          • 2010-12-03
          • 2012-05-17
          相关资源
          最近更新 更多