Last active
September 7, 2022 13:46
-
-
Save BenMorel/eca011a88cb889d8865aa446ed001be0 to your computer and use it in GitHub Desktop.
Stream a file that is being written to by another process
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This script streams a file that is being written to by another process. | |
* It will continue fread()ing past EOF until explicitly stopped with CTRL+C. | |
* | |
* The script will exit with a status code of 0 if and only if the stream is stopped *after* EOF has been reached, | |
* i.e. if actual EOF *MAY* have been reached. | |
* | |
* The output of the streamed file is sent to STDOUT, and the output of the script is sent to STDERR, | |
* so the output can be piped to another program while watching progress in the terminal. | |
*/ | |
declare(strict_types=1); | |
declare(ticks=1); | |
if (!extension_loaded('pcntl')) { | |
fwrite(STDERR, 'The pcntl extension is required.'); | |
exit(1); | |
} | |
$interrupted = false; | |
pcntl_signal(SIGINT, function () use (&$interrupted): void { | |
$interrupted = true; | |
}); | |
if ($argc !== 2) { | |
fwrite(STDERR, sprintf("Usage: %s <file>\n", $argv[0])); | |
exit(1); | |
} | |
$filename = $argv[1]; | |
$fp = @fopen($filename, 'rb'); | |
if ($fp === false) { | |
fwrite(STDERR, sprintf("Could not open file '%s' for reading\n", $filename)); | |
exit(1); | |
} | |
$totalBytes = 0; | |
$totalBytesSinceEof = 0; | |
$lastRead = null; | |
$eof = false; | |
while (true) { | |
$eof = $eof || feof($fp); | |
$data = @fread($fp, 1024 * 1024); | |
if ($data === false) { | |
fwrite(STDERR, sprintf("Could not read from file '%s'\n", $filename)); | |
exit(1); | |
} | |
$bytes = strlen($data); | |
$totalBytes += $bytes; | |
if ($eof) { | |
$totalBytesSinceEof += $bytes; | |
} | |
if ($bytes !== 0) { | |
$lastRead = time(); | |
} | |
fwrite(STDOUT, $data); | |
fwrite(STDERR, "\r\033[K"); // clear line | |
fwrite(STDERR, sprintf('%s bytes read', number_format((float) $totalBytes))); | |
if ($eof) { | |
fwrite(STDERR, sprintf(', %s bytes since EOF', number_format((float) $totalBytesSinceEof))); | |
if ($lastRead !== null) { | |
fwrite(STDERR, sprintf(', last read %s seconds ago', time() - $lastRead)); | |
} | |
} | |
if ($interrupted) { | |
break; | |
} | |
if ($bytes === 0) { | |
usleep(100000); | |
} | |
} | |
exit($eof ? 0 : 1); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment