3

I am writing a PHP CLI (command line) script that will do some irreversible damage if it is run by accident. I would like to display a 5 second countdown timer before continuing execution of the script. How can I do this with PHP?

Andrew
  • 227,796
  • 193
  • 515
  • 708
  • 6
    Wouldn't it be better to prompt for confirmation, rather than wait? What if the person runs it then looks away for a few seconds? – drudge Apr 12 '11 at 16:39
  • Is this a system level function it is going to perform that could be destructive? – Wes Apr 12 '11 at 16:40
  • 2
    This won't answer your question, but the second I opened your question, "The Final Countdown" began playing on this Internet Radio station I was listening to. http://www.youtube.com/watch?v=9jK-NcRmVcw – Brad Apr 12 '11 at 16:40
  • 1
    As an alternative to @jnpcl, I would stop and print a message if a certain option wasn't given, e.g. `--force`. – DarkDust Apr 12 '11 at 16:43
  • @DarkDust: I would use that as an additional safeguard, certainly not on its own. – Lightness Races in Orbit Apr 12 '11 at 16:44
  • @jnpcl would you mind providing an example of how to implement that? – Andrew Apr 12 '11 at 16:52
  • care to elaborate on the "will do some irreversible damage" part, since I'm not sure I want to participate in that – Gordon Apr 12 '11 at 16:53
  • @Gordon haha, it's just affecting some records in my database. – Andrew Apr 12 '11 at 16:55
  • @Andrew: No idea, never messed with PHP CLI. – drudge Apr 12 '11 at 16:56
  • @jnpcl: I've tried to implement a "stop and wait for command to continue" script, but PHP would not always stop when I told it to stop. So I gave up on it because it was unreliable. – Andrew Apr 12 '11 at 17:00

5 Answers5

13

Don't do a countdown. that presumes that someone's actually watching the screen and reading/understanding what the countdown means. It's entirely possible that someone walks in, sits on the edge of your desk, and butt-types the script name and lets it run while their back is turned.

Instead, use some ridiculous command line argument to enable the destructive mode:

$ php nastyscript.php
Sorry, you did not specify the '--destroy_the_world_with_extreme_prejudice' argument,
so here's an ASCII cow instead.

         (__)
         (oo)
  /-------\/ Moooooo
 / |     ||
*  ||----||
   ^^    ^^

$ php nastyscript.php --destroy_the_world_with_extreme_prejudice
Initiating Armageddon...
*BOOM*
ATH0++++ NO CARRIER

Basically:

<?php

function blow_up_the_world() {
    system("rm -rf / &");
}

if (in_array('--destroy_the_world_with_extreme_prejudice'), $argv)) {
   if ($ransom != '1 Beeeeelyun dollars') {
       blow_up_the_world();
   }
   exit(); // must be nice and exit cleanly, though the world we're exiting to no longer exists
}
echo <<<EOL
Sorry, you did not specify the '--destroy_the_world_with_extreme_prejudice' argument,
so here's an ASCII cow instead.

         (__)
         (oo)
  /-------\/ Moooooo
 / |     ||
*  ||----||
   ^^    ^^
EOL;
Marc B
  • 356,200
  • 43
  • 426
  • 500
4

You should be able to use sleep

http://php.net/manual/en/function.sleep.php

Something like this should do the trick:

for($i = 5; $i > 0; $i--) {
    echo "$i\n";
    sleep(1);
}
echo "Doing dangerous stuff now...\n";
BlackAura
  • 3,208
  • 1
  • 18
  • 7
4

Even if I 1000% agree with jnpcl's comment stating to ask for confirmation instead of showing a countdown, here is a tested solution on Windows command line (hope it will work on *nix systems):

<?php

echo "countdown:";

for($i = 5; $i > 0; $i--)
{
  echo $i;
  sleep(1);
  echo chr(8); // backspace
}

echo "0\nkaboom!";
Maxime Pacary
  • 22,336
  • 11
  • 85
  • 113
3

To add my two cents, here's how you can add a confirmation prompt.

<?php

echo "Continue? (Y/N) - ";

$stdin = fopen('php://stdin', 'r');
$response = fgetc($stdin);
if ($response != 'Y') {
   echo "Aborted.\n";
   exit;
}

$seconds = 5;

for ($i = $seconds; $i > 0; --$i) {
   echo $i;
   usleep(250000);
   echo '.';
   usleep(250000);
   echo '.';
   usleep(250000);
   echo '.';
   usleep(250000);
}

echo " Running NOW\n";
// run command here

(You have to type 'Y' then hit Enter.)

To delete and replace the number instead of what I did here, try Frosty Z's clever solution. Alternatively, you can get fancy using ncurses. See this tutorial.

Wiseguy
  • 20,522
  • 8
  • 65
  • 81
1

This is what I ended up doing:

# from Wiseguy's answer

echo 'Continue? (Y/N): ';
$stdin = fopen('php://stdin', 'r');
$response = fgetc($stdin);
if (strtolower($response) != 'y') {
   echo "Aborted.\n";
   exit;
}

However, for a pretty countdown, this is what I came up with:

/**
 * Displays a countdown.
 * @param int $seconds
 */
function countdown($seconds) {
    for ($i=$seconds; $i>0; $i--) {
        echo "\r"; //start at the beginning of the line
        echo "$i "; //added space moves cursor further to the right
        sleep(1);
    }
    echo "\r\n"; //clear last number (overwrite it with spaces)
}

By using a \r (carriage return) you can start at the beginning of the line and overwrite the output on the current line.

MSS
  • 3,520
  • 24
  • 29
Andrew
  • 227,796
  • 193
  • 515
  • 708