我使用 php 通过包装函数通过 ssh 执行 scp 命令。移动是在本地和远程服务器之间进行的。
我大致知道脚本应该执行多长时间,如果 scp 进程花费的时间太长(由于目标服务器陷入困境或其他网络问题),我想终止它。当前发生这种情况时,scp 进程将完全锁定,直到重新启动目标服务器或从命令行手动终止 scp 进程。
我可以将某种超时传递给 shell_exec() 以退出其正在执行的工作并继续执行脚本吗?
使用 UNIXtimeout
实用程序包装您的命令。
system('timeout n ../my/aa');
^
n
以秒为单位的整数值在哪里。
如果命令超时,则以状态 124 退出。否则,以 COMMAND 状态退出。如果未指定信号,则在超时时发送 TERM 信号。TERM 信号会杀死任何不阻塞或捕获该信号的进程。对于其他进程,可能需要使用 KILL (9) 信号,因为无法捕获此信号。
您可以通过执行以下操作使用 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');
?>
您可以编写一个使用 shell_exec 调用的 shell 脚本,该脚本在一定时间后自动终止,然后您调用它而不是 scp 直接调用,这样的脚本将接受参数或将它们硬编码。这是一个脚本示例,它采用 2 个参数,2 秒是它在终止进程之前等待的秒数。(睡眠也接受分钟、我们的或天,只需附加 m、h 或 d)
#!/bin/sh
scp $1 &
pid=$!
sleep $2
kill $pid
编辑:或使用nickb的解决方案,那就更好了。:)
您可以使用带超时的 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]);
或者您可以使用 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";
}
?>