In this kind of situations pushing (invoking a script when the rendering operation is complete) is preferrable to polling (periodically checking if the rendering operation is complete).
If you cannot push, do it in one language only, don't create a hybrid of bash and PHP. Here is are 2 examples you could try which might suit your situation:
Example if rendering command returns after finishing:
<?php
/** PHP wrapper around rendering command X that mails the output **/
// Don't write attachment code yourself, use a class like PHPMailer: https://github.com/Synchro/PHPMailer
require_once('class.phpmailer.php');
// Ignore user browser close, rendering takes a long time
ignore_user_abort(true);
// On windows you'll also need to set_time_limit to something large. On Unix PHP doesn't count things like database queries and shell commands, on Windows it does
// Execute render command, don't forget to escape if you use user input
// Script will only continue once renderer returns. If renderer return before rendering is finished you cannot use this
$render_output = shell_exec('renderer input.file output.file');
// Could also be done in PHP for finer control and error handling
$imagemagick_output = shell_exec("convert output.file animation.gif");
unlink("output.file");
$mail = new PHPMailer();
$mail->addAttachment('animation.gif');
// etc.
unlink("animation.gif");
?>
Example if rendering command returns before finishing:
<?php
/** PHP wrapper around rendering command X that mails the output **/
// Don't write attachment code yourself, use a class like PHPMailer: https://github.com/Synchro/PHPMailer
require_once('class.phpmailer.php');
// Ignore user browser close
ignore_user_abort(true);
// Execute render command, don't forget to escape if you use user input
// If renderer returns before file is finished use this
$render_output = shell_exec('renderer input.file output.file 2> error.file');
// Wait for rendering to finish
// Implement these function, e.g. file_exists for output.file or error.file
while(!rendering_has_failed() && !rendering_is_finished()) {
sleep(15*60); // Low-resource wait for 15 minutes
}
// Could also be done in PHP for finer control and error handling
$imagemagick_output = shell_exec("convert output.file animation.gif");
unlink("output.file");
$mail = new PHPMailer();
$mail->addAttachment('animation.gif');
// etc.
unlink("animation.gif");
?>