gpt4 book ai didi

linux - 比 MATLAB 的 `system` 命令更安全的替代方法

转载 作者:IT王子 更新时间:2023-10-29 00:31:35 26 4
gpt4 key购买 nike

我一直在使用 MATLAB 的 system 命令来获取一些 linux 命令的结果,如以下简单示例所示:

[junk, result] = system('find ~/ -type f')

这按预期工作,除非用户同时在 MATLAB 的命令窗口中键入。这在较长的 find 命令中并不少见。如果发生这种情况,那么用户的输入似乎会与 find 命令的结果混淆(然后事情就会中断)。

例如,代替:

/path/to/file/one
/path/to/file/two
/path/to/file/three
/path/to/file/four

我可能会:

J/path/to/file/one
u/path/to/file/two
n/path/to/file/three
k/path/to/file/four

为了轻松演示这一点,我们可以运行类似的东西:

[junk, result] = system('cat')

在命令窗口中键入内容,然后按 CTRL+D 关闭流。 result 变量将是您在命令窗口中输入的任何内容。

有没有一种更安全的方法可以让我从 MATLAB 调用系统命令而不会冒损坏输入的风险?

最佳答案

哇。这种行为令人惊讶。听起来值得向 MathWorks 报告错误。我在 OS X 上对其进行了测试,并看到了相同的行为。

作为一种变通方法,您可以通过调用 java.lang.Process 和嵌入在 Matlab 中的 JVM 中的相关对象来重新实现 system()

你需要:

  • 使用轮询来保持 Matlab 自己的输入,尤其是 Ctrl-C,有效
  • 使用 shell 处理而不是将命令直接传递给 ProcessBuilder,以支持 ~ 和其他变量和通配符的扩展,并支持像 Matlab 系统那样在单个字符串中指定命令及其参数。** 或者,如果您想要较低级别的控制并且不想处理 shell 的转义和引用字符串,则可以公开参数数组形式。两者都会有用。
  • 将输出重定向到文件,或在您的轮询代码中定期清空子进程的输出缓冲区。

这是一个例子。

function [status,out,errout] = systemwithjava(cmd)
%SYSTEMCMD Version of system implemented with java.lang features
%
% [status,out,errout] = systemwithcmd(cmd)
%
% Written to work around issue with Matlab UI entry getting mixed up with
% output captured by system().

if isunix
% Use 'sh -s' to enable processing of single line command and expansion of ~
% and other special characters, like the Matlab system() does
pb = java.lang.ProcessBuilder({'bash', '-s'});
% Redirect stdout to avoid filling up buffers
myTempname = tempname;
stdoutFile = [myTempname '.systemwithjava.out'];
stderrFile = [myTempname '.systemwithjava.err'];
pb.redirectOutput(java.io.File(stdoutFile));
pb.redirectError(java.io.File(stderrFile));
p = pb.start();
RAII.cleanUpProcess = onCleanup(@() p.destroy());
RAII.stdoutFile = onCleanup(@() delete(stdoutFile));
RAII.stderrFile = onCleanup(@() delete(stderrFile));
childStdin = java.io.PrintStream(p.getOutputStream());
childStdin.println(cmd);
childStdin.close();
else
% TODO: Fill in Windows implementation here
end

% Poll instead of waitFor() so Ctrl-C stays live
% This try/catch mechanism is lousy, but there is no isFinished() method.
% Could be done more cleanly with a Java worker that did waitFor() on a
% separate thread, and have the GUI event thread interrupt it on Ctrl-C.
status = [];
while true
try
status = p.exitValue();
% If that returned, it means the process is finished
break;
catch err
if isequal(err.identifier, 'MATLAB:Java:GenericException') ...
&& isa(err.ExceptionObject, 'java.lang.IllegalThreadStateException')
% Means child process is still running
% (Seriously, java.lang.Process, no "bool isFinished()"?
% Just continue
else
rethrow(err);
end
end
% Pause to allow UI event processing, including Ctrl-C
pause(.01);
end

% Collect output
out = slurpfile(stdoutFile);
errout = slurpfile(stderrFile);
end

function out = slurpfile(file)
fid = fopen(file, 'r');
RAII.fid = onCleanup(@() fclose(fid));
out = fread(fid, 'char=>char')'; %'
end

我尽我所能地尝试了这一点,看起来它使子进程的输出与 Matlab IDE 的键盘输入分开。 systemwithjava() 返回后,键盘输入被缓冲并作为附加命令执行。 Ctrl-C 保持事件状态并将中断该功能,让子进程被杀死。

关于linux - 比 MATLAB 的 `system` 命令更安全的替代方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23948227/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com