0

I have an external library with a bunch of executables (DCMTK). Normally, those can be executed on the CLI, with output sometimes showing in the terminal. I want to use some of those in PHP scripts, and I was able to do that with one.

Essentials are:

// path to the executables.

private static $dcmtk_path = '/usr/local/opt/dcmtk/bin/';

//method to execute the dcmtk executable.

public static function dcmtk_command($command) {
    //--logfile dcmlogfile.cfg
    echo exec(self::$dcmtk_path . $command); // $outputarray, 2nd arg ?
    }
}

// working example that converts a text file to a dcm worklist file

file_put_contents (self::$MWL_PATH . "samplephp.txt", $template); // text file for MWL.
echo '[{"status":"Sent to PATH"}]';
self::dcmtk_command('dump2dcm ' . self::$MWL_PATH . "samplephp.txt " . self::$MWL_PATH . "samplephp.wl");

I don't know if this is even possible. But, I am uploading multiple files via a $_POST and get:

 $file_tmp = $files['tmp_name'];

That is saved to a path on the server:

 $success = move_uploaded_file($file_tmp, $upload_path);

and then I want to execute another command:

self::dcmtk_command('dcmdump ' . $upload_path . $file_name );
// dcmdump +P StudyInstanceUID IM-0001-0004.dcm for specific tag

When executed from the CLI that prints out a bunch of text to the terminal (?STDOUT). What I want to do is capture that output in the PHP script so that I can process the output. I have tried a few things, like using an output buffer, the $outputarray from the exec command, etc.

Seems like that should be possible. The files are getting saved on the server in the path that is configured, so they should be at $upload_path . $file_name. And, I do not see any errors in the PHP console / error log. I actually do not have a good way to check if the command was even successful.

SScotti
  • 2,158
  • 4
  • 23
  • 41
  • 1
    Does this answer your Q https://stackoverflow.com/questions/2320608/php-stderr-after-exec – Ron May 06 '20 at 00:25
  • It isn't clear from your question why using the [2nd parameter of `exec()`](https://www.php.net/manual/en/function.exec.php) is not enough. There are also several other relevant built-in options - [`passthru()`](https://www.php.net/manual/en/function.passthru.php) and [`shell_exec()`](https://www.php.net/manual/en/function.shell-exec.php) - have you tried either of those? – Don't Panic May 06 '20 at 01:29
  • 1
    There are many similar questions here, do they help? https://stackoverflow.com/questions/16665041/php-why-isnt-exec-returning-output, https://stackoverflow.com/questions/7093860/php-shell-exec-vs-exec, https://stackoverflow.com/questions/20107147/php-reading-shell-exec-live-output ... – Don't Panic May 06 '20 at 01:32
  • Thanks. This was helpful: https://stackoverflow.com/questions/2320608/php-stderr-after-exec Also, had some issues with the class file, so I just put it all into one script for now to get it working. Maybe make a class again now that it is working. Pretty nice really. – SScotti May 06 '20 at 04:27
  • @Don't Panic Do you have contact info ? – SScotti May 09 '20 at 16:08

2 Answers2

0

Thanks again. That does the trick.

$proc = proc_open($dcmtk_path . 'dcmdump +P StudyInstanceUID ' . $upload_path,[
1 => ['pipe','w'],
2 => ['pipe','w'],
],$pipes);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
proc_close($proc);
DatabaseFactory::logVariable( $stdout);  

Can even just get a single tag if I want. It captures that single line in a variable like:

(0020,000d) UI [1.3.76.2.1.1.4.1.2.5310.511614778]      #  34, 1 StudyInstanceUID

Need some sort of function to extract the thing between the brackets:

This almost works:

$text = '(0020,000d) UI [1.3.76.2.1.1.4.1.2.5310.511614778]      #  34, 1 StudyInstanceUID';
preg_match_all("/\[([^\]]*)\]/", $text, $match);
print_r($match);

Array
(
    [0] => Array
        (
            [0] => [1.3.76.2.1.1.4.1.2.5310.511614778]
        )

    [1] => Array
        (
            [0] => 1.3.76.2.1.1.4.1.2.5310.511614778
        )

)
SScotti
  • 2,158
  • 4
  • 23
  • 41
0

As a follow up, I want a way to catch an error if the process throws an error. I forced one, and it prints this in the output stream (not the error stream):

As a follow up, is it possible catch an error thrown by the command in proc_open. There are cases when that might throw and error:

e.g. I get what look like warning and errors on the CLI (intentionally made it do that). I would like a way to catch those ?

[07-May-2020 12:29:46 America/Cayman]

W: DcmItem: Length of element (5089,474e) is odd
E: DcmElement: Unknown Tag & Data (5089,474e) larger (169478669) than remaining bytes in file
E: dcmdump: I/O suspension or premature end of stream: reading file: /Users/sscotti/Desktop/newtelerad2/dicomtemp/tattoo.dcm

It looks like maybe:

proc_get_status ( resource $process ) : array can give that with the exit code:

{
    "command": ". . . .",
    "pid": 8245,
    "running": false,
    "signaled": false,
    "stopped": false,
    **"exitcode": 1,**
    "termsig": 0,
    "stopsig": 0
}

Thanks.

SScotti
  • 2,158
  • 4
  • 23
  • 41