|
1 |
| -function [status, msg] = subprocess_run(cmd_array, opt) |
2 |
| - |
| 1 | +function [status, stdout, stderr] = subprocess_run(cmd, opt) |
| 2 | +% SUBPROCESS_RUN run a program with arguments and options |
| 3 | +% uses Matlab Java ProcessBuilder interface to run subprocess and use stdin/stdout pipes |
3 | 4 | arguments
|
4 |
| - cmd_array (1,:) string |
| 5 | + cmd (1,:) string |
5 | 6 | opt.env struct {mustBeScalarOrEmpty} = struct.empty
|
6 | 7 | opt.cwd string {mustBeScalarOrEmpty} = string.empty
|
| 8 | + opt.stdin string {mustBeScalarOrEmpty} = string.empty |
7 | 9 | end
|
8 | 10 |
|
9 |
| -exe = space_quote(cmd_array(1)); |
| 11 | +%% process instantiation |
| 12 | +proc = java.lang.ProcessBuilder(""); |
10 | 13 |
|
11 |
| -if length(cmd_array) > 1 |
12 |
| - cmd = append(exe, " ", join(cmd_array(2:end), " ")); |
13 |
| -else |
14 |
| - cmd = exe; |
| 14 | +if ~isempty(opt.env) |
| 15 | + % requires Parallel Computing Toolbox |
| 16 | + env = proc.environment(); |
| 17 | + fields = fieldnames(opt.env); |
| 18 | + for i = 1:length(fields) |
| 19 | + env.put(fields{i}, opt.env.(fields{i})); |
| 20 | + end |
15 | 21 | end
|
16 | 22 |
|
17 | 23 | if ~isempty(opt.cwd)
|
18 | 24 | mustBeFolder(opt.cwd)
|
19 |
| - cwd = stdlib.fileio.absolute_path(opt.cwd); |
20 |
| - oldcwd = pwd; |
21 |
| - cd(cwd) |
| 25 | + proc.directory(java.io.File(opt.cwd)); |
22 | 26 | end
|
23 | 27 |
|
24 |
| -old = isMATLABReleaseOlderThan('R2022b'); |
25 |
| -if old && ~isempty(opt.env) |
26 |
| - warning("Matlab >= R2022b required for 'env' option of subprocess_run()") |
| 28 | +proc.command(cmd); |
| 29 | +%% start process |
| 30 | +h = proc.start(); |
| 31 | + |
| 32 | +%% stdin pipe |
| 33 | +if ~isempty(opt.stdin) |
| 34 | + writer = java.io.BufferedWriter(java.io.OutputStreamWriter(h.getOutputStream())); |
| 35 | + writer.write(opt.stdin); |
| 36 | + writer.flush() |
| 37 | + writer.close() |
27 | 38 | end
|
28 | 39 |
|
29 |
| -if isempty(opt.env) || old |
30 |
| - [status, msg] = system(cmd); |
31 |
| -else |
32 |
| - envCell = namedargs2cell(opt.env); |
33 |
| - % https://www.mathworks.com/help/matlab/ref/system.html |
34 |
| - [status, msg] = system(cmd, envCell{:}); |
| 40 | +%% wait for process to complete |
| 41 | +% https://docs.oracle.com/javase/9/docs/api/java/lang/Process.html#waitFor-- |
| 42 | +status = h.waitFor(); |
| 43 | + |
| 44 | +%% read stdout, stderr pipes |
| 45 | +stdout = read_stream(h.getInputStream()); |
| 46 | +stderr = read_stream(h.getErrorStream()); |
| 47 | + |
| 48 | +%% close process |
| 49 | +h.destroy() |
| 50 | + |
| 51 | +if nargout < 2 && strlength(stdout) > 0 |
| 52 | + disp(stdout) |
35 | 53 | end
|
36 |
| -if ~isempty(opt.cwd) |
37 |
| - cd(oldcwd) |
| 54 | +if nargout < 3 && strlength(stderr) > 0 |
| 55 | + warning(stderr) |
38 | 56 | end
|
39 | 57 |
|
40 |
| -end |
| 58 | +end % function subprocess_run |
41 | 59 |
|
42 | 60 |
|
43 |
| -function q = space_quote(p) |
44 |
| -arguments |
45 |
| - p (1,1) string |
46 |
| -end |
| 61 | +function msg = read_stream(stream) |
47 | 62 |
|
48 |
| -if ~contains(p, " ") |
49 |
| - q = p; |
50 |
| - return |
| 63 | +reader = java.io.BufferedReader(java.io.InputStreamReader(stream)); |
| 64 | +line = reader.readLine(); |
| 65 | +msg = ""; |
| 66 | +while ~isempty(line) |
| 67 | + msg = append(msg, string(line), newline); |
| 68 | + line = reader.readLine(); |
51 | 69 | end
|
52 |
| - |
53 |
| -q = append('"', p, '"'); |
| 70 | +msg = strip(msg); |
| 71 | +reader.close() |
54 | 72 |
|
55 | 73 | end
|
0 commit comments