Maintenance scripts exit with 0 when they fail due to an exception, as I just discovered on the snapshot hosts (Wikidata dumps failed there, but exited with 0).
Can be easily reproduced: Take any maintenance script and put throw new \Exception(); at the top of its execute function (I tested it with maintenance/refreshLinks.php but any script should work). It will exit with 0 (success).
This happens as MW sets its own exception handler (set_exception_handler):
$ cat test.php <?php throw new Exception(); echo 1; $ php test.php PHP Fatal error: Uncaught Exception in /home/hoch_m/tmp/test.php:5 Stack trace: #0 {main} thrown in /home/hoch_m/tmp/test.php on line 5 $ echo $? 255
but once we add an exception handler:
$ cat test.php <?php set_exception_handler(function($e) {echo "ACK\n";}); throw new Exception(); echo 1; $ php test.php ACK $ echo $? 0