2

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

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

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

4

5 回答 5

5

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

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

n以秒为单位的整数值在哪里。

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

于 2012-06-09T00:43:57.690 回答
2

您可以通过执行以下操作使用 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');
?>
于 2012-06-13T21:12:11.333 回答
0

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

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

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

于 2012-06-09T00:42:58.120 回答
0

您可以使用带超时的 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]);
于 2012-06-09T00:47:27.137 回答
0

或者您可以使用 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";
}

?>
于 2012-06-09T01:58:04.587 回答