[英]How to break a MATLAB system call after a specified number of seconds
我正在使用 Windows MATLAB 來運行 SSH 命令,但每隔一段時間 SSH 命令就會無限期掛起,然后我的 MATLAB 腳本也會掛起(有時會在一夜之間運行)。 在一定的等待時間后如何讓命令超時? 例如,假設我不想在 SSH 命令完成執行之前等待超過 3 秒,然后再中斷它並繼續:
% placeholder for a command that sometimes hangs
[status,result] = system('ssh some-user@0.1.2.3 sleep 10')
% placeholder for something I still want to run if the above command hangs
[status,result] = system('ssh some-user@0.1.2.3 ls')
我想制作一個 function sys_with_timeout
可以像這樣使用:
timeoutDuration = 3;
[status,result] = sys_with_timeout('ssh some-user@0.1.2.3 sleep 10', timeoutDuration)
[status,result] = sys_with_timeout('ssh some-user@0.1.2.3 ls', timeoutDuration)
我已經嘗試過FEX 的超時 function,但它似乎不適用於系統/SSH 命令。
我認為system
命令不是很靈活,而且我看不出有什么方法可以用它來做你想做的事。 但是我們可以為此使用 Java 內置的功能 MATLAB,根據André Caron 的回答。
這是您等待進程超時完成的方式:
runtime = java.lang.Runtime.getRuntime();
process = runtime.exec('sleep 20');
process.waitFor(10, java.util.concurrent.TimeUnit.SECONDS);
if process.isAlive()
disp("Done waiting for this...")
process.destroyForcibly();
end
process.exitValue()
在示例中,我們運行sleep 20
shell 命令,然后waitFor()
等待程序完成,但最多等待 10 秒。 我們輪詢以查看該進程是否仍在運行,如果是,則將其殺死。 如果需要, exitValue()
會返回狀態。
運行sleep 5
我看到:
ans =
0
運行sleep 20
我看到:
Done waiting for this...
ans =
137
基於@Cris Luengo 的回答,這里是sys_with_timeout()
function。我沒有使用process.waitFor()
function,因為我寧願在 while 循環中等待並在它進入時顯示 output。while 循環中斷一次命令完成或超時,以先到者為准。
function [status,cmdout] = sys_with_timeout(command,timeoutSeconds,streamOutput,errorOnTimeout)
arguments
command char
timeoutSeconds {mustBeNonnegative} = Inf
streamOutput logical = true % display output as it comes in
errorOnTimeout logical = false % if false, display warning only
end
% launch command as java process (does not wait for output)
process = java.lang.Runtime.getRuntime().exec(command);
% start the timeout timer!
timeoutTimer = tic();
% Output reader (from https://www.mathworks.com/matlabcentral/answers/257278)
outputReader = java.io.BufferedReader(java.io.InputStreamReader(process.getInputStream()));
errorReader = java.io.BufferedReader(java.io.InputStreamReader(process.getErrorStream()));
% initialize output char array
cmdout = '';
while true
% If any lines are ready to read, append them to output
% and display them if streamOutput is true
if outputReader.ready() || errorReader.ready()
if outputReader.ready()
nextLine = char(outputReader.readLine());
elseif errorReader.ready()
nextLine = char(errorReader.readLine());
end
cmdout = [cmdout,nextLine,newline()];
if streamOutput == true
disp(nextLine);
end
continue
else
% if there are no lines ready in the reader, and the
% process is no longer running, then we are done
if ~process.isAlive()
break
end
% Check for timeout. If timeout is reached, destroy
% the process and break
if toc(timeoutTimer) > timeoutSeconds
timeoutMessage = ['sys_with_timeout(''',command, ''',', num2str(timeoutSeconds), ')',...
' failed after timeout of ',num2str(toc(timeoutTimer)),' seconds'];
if errorOnTimeout == true
error(timeoutMessage)
else
warning(timeoutMessage)
end
process.destroyForcibly();
break
end
end
end
if ~isempty(cmdout)
cmdout(end) = []; % remove trailing newline of command output
end
status = process.exitValue(); % return
end
為簡單起見,將ssh some-user@0.1.2.3
替換為wsl
(當然需要WSL ),這是一個 function 超時的示例:
>> [status,cmdout] = sys_with_timeout('wsl echo start! && sleep 2 && echo finished!',1)
start!
Warning: sys_with_timeout('wsl echo start! && sleep 2 && echo finished!',1) failed after timeout of 1.0002 seconds
> In sys_with_timeout (line 41)
status =
1
cmdout =
'start!'
這是一個 function 沒有超時的例子:
>> [status,cmdout] = sys_with_timeout('wsl echo start! && sleep 2 && echo finished!',3)
start!
finished!
status =
0
cmdout =
'start!
finished!'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.