Wait for user input a period of time and continue with script execution if none is supplied

When doing devops work one of the many responsibilities you might have is creation of various installation or deployment scripts. They can be created in any scripting language, starting from the standard bash script to various server side languages (Perl, Python, PHP, etc…). For this example we are going to tackle a specific problem when you create such a script in PHP and we will work with some of the less known features which are embedded in the language.

Lets say we need a script which would give the end-user a chance to either press ‘R’ to completely reinstall some module, in which case the module directory would be deleted and git clone would be executed, or maybe press any other key to halt the script execution, or wait for 5 seconds in which the script execution would continue in which case git pull will be performed.
Having this story narrowed down, these are the steps we need to accomplish:

  • Ask the end-user for a standard input (stdin) entry and perfrom action accordingly
  • If there is no user action supplied in a certain amount of time then continue with the script execution

For the means of practicality this script will deal only with the bare essentials to accomplish this task, and you can expand it further to meet your needs.

function userConfirmation($message) {
 
    $timeToWait = 5; //seconds to wait for user input
    echo $message . PHP_EOL;
    echo "Press 'R' to reinstall, any other key to quit or wait 10 seconds to perform an update: " . PHP_EOL;
    $stdin = fopen ("php://stdin","r");

    $read = array($stdin);
    $write = $except = array(); //we don't need these for this particular task

    if(stream_select($read, $write, $except, $timeToWait)) {
        if (strtoupper(trim(fgets($stdin))) == 'R') {
            $action = true;
        } else {
            fclose($stdin);
            echo "ABORTING!" . PHP_EOL;
            exit;
        }
    } else {
        echo "No user action detected, continuing with update..." . PHP_EOL;
        $action = false;
    }

    fclose($stdin);
    return $action;
}

exec ('mkdir test-module'); //create a test directory 
$msg = "Completly reinstall test-module? This will delete the directory and install it from scratch.";

if(userConfirmation($msg)) {

    if(file_exists('test-module')) {
        echo "Directory exists, performing 'rm test-module -rf'" . PHP_EOL;
        exec('rmdir test-module');
    }

    if(!file_exists('test-module')) {
        echo "Perform 'git clone'..." . PHP_EOL;
    } else {
        echo "Perform 'git pull'..." . PHP_EOL; 
    }
}

As you can see besides the basic conditional blocks all the hard work is performed in two lines of code:

  • fopen ("php://stdin","r"); – which opens the standard input (stdin) to receive input from the user; and
  • the stream_select() function — a less known PHP feature which accepts arrays of streams and waits for them a specific timeout to change status.

More about PHP streams: http://php.net/manual/en/intro.stream.php
More about stream_select()http://php.net/manual/en/function.stream-select.php

Without the usage of this function the task of creating script in PHP which would wait for the user input for a predefined amount of time would be a messy one.

Do you have a question or maybe a better alternative to this approach? Please do write a comment.

Leave a Reply