A Basic Example using PHP in AWS (Amazon Web Services)

By: Clay Loveless, Chief Architect, Mashery Emailed: 1588 times Printed: 2040 times    

Latest comments
By: rohit kumar - how this program is work
By: Kirti - Hi..thx for the hadoop in
By: Spijker - I have altered the code a
By: ali mohammed - why we use the java in ne
By: ali mohammed - why we use the java in ne
By: mizhelle - when I exported the data
By: raul - no output as well, i'm ge
By: Rajesh - thanx very much...
By: Suindu De - Suppose we are executing

To illustrate the use of AWS services, we'll build a simple video database with the following characteristics:

  • Hosted on EC2
  • Uses Amazon S3 as the primary data store.
  • Uses SQS and a separate EC2 server to manage batch encoding of video for Flash display.
  • Uses SimpleDB to store metadata about the videos.

While there are a number of ways to get all these services running, including very convenient management interfaces in Firefox (such as Elasticfox), plus web-based management tools from RightScale and Scalr, we'll do it all with PHP and the API, since that's what this article is about.

To keep the examples as focused as possible, from here on they will make use of an inclusion calledexample_setup.php, which includes and parses your aws.conf file, configures PHP 5's autoload functionality, and a few other things to keep example code concise and accurate. The example_setup.php file looks like this:

File: example_setup.php

<?php
// keep ourselves honest
error_reporting(E_ALL);
ini_set('display_errors', 'on');
ini_set('log_errors', 'on');
ini_set('error_log', '/tmp/php.log');

// use the config that we set up previously
$creds = parse_ini_file('/etc/aws.conf');
if (! isset($creds['tutorial_file_path'])) {
    $creds['tutorial_file_path'] = sys_get_temp_dir();
}

// set include_path for article's bundled AWS libraries
ini_set('include_path', dirname(__FILE__) 
        . DIRECTORY_SEPARATOR
        . 'AWSforPHP'
        . PATH_SEPARATOR
        . ini_get('include_path'));

// make loading simple
function __autoload($class_name) 
{
    if (class_exists($class_name, false) || 
        interface_exists($class_name, false)) {
        return;
    }
    // AWS and Killersoft classes follow PEAR
    // file naming conventions
    $file = str_replace('_', 
                DIRECTORY_SEPARATOR,
                $class_name
            ) . '.php';
    @include_once $file;
}

Finally, we'll be generating an SSH keypair specific to this tutorial, so please add a path to your config file that specifies where those files should be stored once generated. Like so:

; Path to writable directory where we can save files
tutorial_file_path = "/tmp"

Start Your Server

We need a place to host the scripts associated with this video library, so let's start by getting a server running with the latest Amazon-provided Fedora Core Linux image. At the time of this writing, that's Fedora Core 8 and has an AMI ID of ami-2b5fba42.

Before launching an instance, let's briefly explore how to set up EC2 Security Groups and generate EC2 KeyPairs. In a nutshell, EC2 Security Groups are firewall rules that control what ports and serivces may be accessed on any server running under the specified group. The full details are outside the scope of this article, but there is an excellent exploration of difference Security Group scenarios and use cases in the EC2 Developer Guide.

We'll also set up an EC2 KeyPair, which is simply an SSH keypair that you'll need in order to access the EC2 server once the instance is launched. The public key will be stored on the instance when you launch it, and you will then be able to login via SSH using the private key.

The following block of code will:

  1. Make sure that the 'awstutorial' KeyPair exists, and will create it if it does not exist. The private key will be stored as 'id_rsa-awstutorial' in the 'tutorial_file_path' directory you specified in your aws.conf file above.
  2. Make sure that the 'awstutorial' Security Group exists, and will create it if it does not exist.
  3. Make sure that ports 80 and 22 are open in the 'awstutorial' Security Group.

Note: Careful tuning of EC2 Security Group settings is beyond the scope of this article. Please readthe documentation on that subject carefully.

File: ec2-prelaunch.php

<?php
/**
 * Script to check port 80 on the 'awstutorial' security group,
 * and open it if it is not open. This will use the 'awstutorial' 
 * keypair as well, creating it if it does not exist.
 */
require_once 'example_setup.php';

// load the service
$ec2 = new Amazon_EC2_Client(
    $creds['access_key'], 
    $creds['secret_key']
);

/**
 * 
 * Use 'awstutorial' keypair
 * 
 */
$req = new Amazon_EC2_Model_DescribeKeyPairsRequest();
$kpmatch = false;

// run the request
$resp = $ec2->describeKeyPairs($req);

$pairs = $resp->getDescribeKeyPairsResult()->getKeyPair();
foreach ($pairs as $pair) {
    if ($pair->getKeyName() == 'awstutorial') {
        echo "KeyPair awstutorial exists!\n";
        $kpmatch = true;
        break;
    }
}

// create the keypair if we need to
$keypath = $creds['tutorial_file_path']
         . DIRECTORY_SEPARATOR
         . 'id_rsa-awstutorial';

if (! $kpmatch) {
    echo "Creating awstutorial keypair...\n";
    $req = new Amazon_EC2_Model_CreateKeyPairRequest();
    $req->withKeyName('awstutorial');
    
    $resp = $ec2->createKeyPair($req);
    
    if ($resp->isSetCreateKeyPairResult()) {
        $res = $resp->getCreateKeyPairResult();
        $kp = $res->getKeyPair();
        
        echo "generated fingerprint\n";
        echo $kp->getKeyFingerprint() . "\n";
        
        echo "generated material\n";
        echo $kp->getKeyMaterial() . "\n";
                
        // save private key for future use      
        @file_put_contents(
            $keypath,
            $kp->getKeyMaterial()
        );
        
        // set permissions appropriately for key
        chmod($keypath, 0600);
    }
} else {
    // emit a notice if key file isn't where we expect it
    if (! is_readable($keypath)) {
        echo "!! Couldn't read id_rsa-awstutorial file "
           . "at $keypath\n";
    }
}

/**
 * 
 * Use 'awstutorial' Security Group. Create it if
 * necessary.
 * 
 */
$req = new Amazon_EC2_Model_DescribeSecurityGroupsRequest();
$req->withGroupName('awstutorial');

// run the request
try {
    $resp = $ec2->describeSecurityGroups($req);
    echo "Security Group awstutorial exists!\n";
} catch (Amazon_EC2_Exception $e) {
    // doesn't exist, create it
    echo "Creating awstutorial security group ...";
    $new = new Amazon_EC2_Model_CreateSecurityGroupRequest();
    $new->withGroupName('awstutorial')
        ->withGroupDescription(
            'AWS for PHP Developers Tutorial Group'
        );
    $ec2->createSecurityGroup($new);
    echo "done.\n";
    
    // now fe-fetch response
    $resp = $ec2->describeSecurityGroups($req);
}

/**
 * 
 * Make sure 'awstutorial' group has ports 80 and 22 open.
 * 
 */
if ($resp->isSetDescribeSecurityGroupsResult()) {
    $list = $resp->getDescribeSecurityGroupsResult()
                 ->getSecurityGroup();

    // look for wide-open port 80
    $port80open = false;
    $port22open = false;
    foreach ($list as $securityGroup) {
        
        if (! $securityGroup->isSetIpPermission()) {
            continue;
        }
        
        $perms = $securityGroup->getIpPermission();
        foreach ($perms as $perm) {
            if ($perm->isSetIpProtocol() 
                && $perm->getIpProtocol() == 'tcp'
                && $perm->isSetFromPort()
                && $perm->getFromPort() == '80'
                && $perm->isSetToPort()
                && $perm->getToPort() == '80'
            ) {
                $port80open = true;
                continue;
            }
            if ($perm->isSetIpProtocol() 
                && $perm->getIpProtocol() == 'tcp'
                && $perm->isSetFromPort()
                && $perm->getFromPort() == '22'
                && $perm->isSetToPort()
                && $perm->getToPort() == '22'
            ) {
                $port22open = true;
                continue;
            }
        }
    }
}

if ($port80open) {
    echo "Security Group awstutorial port 80 is open!\n";
} else {
    // open port 80
    echo "Opening awstutorial port 80 ...";
    $req = new Amazon_EC2_Model_AuthorizeSecurityGroupIngressRequest();
    $req->withGroupName('awstutorial')
        ->withIpProtocol('tcp')
        ->withFromPort(80)
        ->withToPort(80)
        ->withCidrIp('0.0.0.0/0');
    $ec2->authorizeSecurityGroupIngress($req);
    echo "done.\n";
}

if ($port22open) {
     echo "Security Group awstutorial port 22 is open!\n";
} else {
    // open port 22
    echo "Opening awstutorial port 22 ...";
    $req = new Amazon_EC2_Model_AuthorizeSecurityGroupIngressRequest();
    $req->withGroupName('awstutorial')
        ->withIpProtocol('tcp')
        ->withFromPort(22)
        ->withToPort(22)
        ->withCidrIp('0.0.0.0/0');
    $ec2->authorizeSecurityGroupIngress($req);
    echo "done.\n";
}

From your workstation:

PROMPT> cd ~/awsfiles
php ec2-prelaunch.php

Now that credentials are created and a known firewall setting is in place, it's time to launch the server. In the next block of code, we set up the Amazon_EC2_Client object provided by the Amazon EC2 PHP library, launch a small Fedora Core instance, and wait for it to complete the initial boot process so that we can retrieve its public hostname.

File: ec2-launch.php

<?php
/**
 * Script to launch a small EC2 instance with Amazon's
 * Fedora Core 8 AMI.
 * 
 * The script will loop during the launch, waiting 
 * for the instance to obtain a public DNS name.
 */
require_once 'example_setup.php';

// load the service
$ec2 = new Amazon_EC2_Client(
    $creds['access_key'], 
    $creds['secret_key']
);

// set up the request with nice fluent interface
$req = new Amazon_EC2_Model_RunInstancesRequest();

// ami-2b5fba42 is Amazon's Fedora Core 8 image
$req->setImageId('ami-2b5fba42')
    ->withMinCount(1)
    ->withMaxCount(1)
    ->withKeyName('awstutorial')
    ->withSecurityGroup('awstutorial');

// run the request
echo "Launching awstutorial instance.\n";
$response = $ec2->runInstances($req);

// this can take a few minutes
$start = microtime(true);
set_time_limit(0);

// get the pending instance id
$reservation = $response->getRunInstancesResult()
                        ->getReservation();
$instances = $reservation->getRunningInstance();
$runningInstance = $instances[0];

// output instance id and state
$id = $runningInstance->getInstanceId();
echo $id
    . ' is ' 
    . $runningInstance->getInstanceState()
                        ->getName()."\n";
// save example instance id
@file_put_contents(
    $creds['tutorial_file_path']
    . DIRECTORY_SEPARATOR
    . 'awstutorial-instance.txt',
    $id
);

// set up DescribeInstances request to fetch status on new
// instance in a loop.
$desc = new Amazon_EC2_Model_DescribeInstancesRequest();
$desc->setInstanceId($id);

echo 'Waiting for public hostname';
while (1) {
    // output progress
    echo '.';
    
    $response = $ec2->describeInstances($desc);
    $res = $response->getDescribeInstancesResult()
                    ->getReservation();
                   
    $ri = $res[0]->getRunningInstance();
    $runningInstance = $ri[0];
    
    if ($runningInstance->isSetPublicDnsName()) {
        $end = microtime(true);
        break;
    }
    
    sleep(2);
}
echo "\n";

// now we're ready to set up our server
echo $id
    . ' is ' 
    . $runningInstance->getInstanceState()->getName()
    . ' at '
    . $runningInstance->getPublicDnsName()
    . "\n";
    
// save hostname for later
@file_put_contents(
    $creds['tutorial_file_path']
    . DIRECTORY_SEPARATOR
    . 'awstutorial-hostname.txt',
    $runningInstance->getPublicDnsName()
);

$span = $end - $start;
echo "Instance booted in {$span} seconds.\n";
exit;

From your workstation:

PROMPT> cd ~/awsfiles
php ec2-launch.php

Note: Establishing a public DNS name does not necessarily mean that the server is ready to accept SSH logins. It may take a minute or two after running the launch example before you can log in to your instance. Do not panic, this is normal.

As you can see from these examples, the Amazon_EC2_Model class and its descendants fully encapsulate all the details of making the requests and parsing the responses from the API.

This concludes the majority of this article's use of the EC2 API. The Amazon-provided EC2 library is robust and well-documented. Be sure to check out its reference documentation.

Setting Up the Server

Now that we have an EC2 instance available, it's time to set up PHP and Apache so we can serve the video library interface.

Start by logging in to the instance, using SSH key, instance id and hostname that we acquired in the previous section of the tutorial. If you need introductory assistance on how to log in to an instance using SSH, please refer to the EC2 Getting Started Guide.

If you want to use the data we saved in the previous section to login, set these shell variables (using the appropriate path, of course).

From your workstation:

# assumes current working directory - change path as needed
PROMPT> export AWSTUTORIAL_HOST=`cat \`pwd\`/awstutorial-hostname.txt`
PROMPT> export AWSTUTORIAL_KEY=`pwd`/id_rsa-awstutorial

Now, make sure you'll be able to run tutorial examples from the server by copying the aws.conf file we've been working with to the new instance.

From your workstation:

PROMPT> scp -i $AWSTUTORIAL_KEY /etc/aws.conf root@$AWSTUTORIAL_HOST:/etc/aws.conf
PROMPT> ssh -i $AWSTUTORIAL_KEY root@$AWSTUTORIAL_HOST \
    'curl -O http://s3.killersoft.com/AWSforPHP/awsfiles.zip; \
    unzip awsfiles.zip -d /var/www/'
PROMPT> scp -i $AWSTUTORIAL_KEY awstutorial-*.txt root@$AWSTUTORIAL_HOST:/tmp/

With that, you're ready to login:

From your workstation:

PROMPT> ssh -2 -i $AWSTUTORIAL_KEY root@$AWSTUTORIAL_HOST

Once you're in, we need to set up PHP and Apache. In case you're inclined to try out the SOAP examples mentioned above, we'll install the packages necessary for those as well as the basic PHP 5 and Apache requirements.

From your instance:

PROMPT> yum -y install php php-mcrypt.i386 php-soap.i386 \
    php-xml.i386 php-cli.i386 httpd.i386

The server should be ready to go. To confirm that PHP is properly configured, and Apache is running, do the following:

From your instance:

PROMPT> echo "<?php phpinfo(); ?>" > /var/www/html/index.php
PROMPT> service httpd start

Now load the hostname of your instance in your browser. You should see the standard phpinfo() output page. If you don't, please review the steps above again -- it's possible that you missed a step, or that something's gone wrong. However, if all's right with the world, you'll see phpinfo() output and be ready to move on to the next step.


PHP Home | All PHP Tutorials | Latest PHP Tutorials

Sponsored Links

If this tutorial doesn't answer your question, or you have a specific question, just ask an expert here. Post your question to get a direct answer.



Bookmark and Share

Comments(0)


Be the first one to add a comment

Your name (required):


Your email(required, will not be shown to the public):


Your sites URL (optional):


Your comments:



More Tutorials by Clay Loveless, Chief Architect, Mashery
Building a Video Sharing Site using PHP in AWS
A Basic Example using PHP in AWS (Amazon Web Services)
Introduction to Amazon Web Services

More Tutorials in PHP
PHP code to import from CSV file to MySQL
PHP code to write to a CSV file from MySQL query
PHP code to write to a CSV file for Microsoft Applications
Convert XML to CSV in PHP
Password must include both numeric and alphabetic characters - Magento
PHP file upload (Large Files)
PHP file upload prompts authentication for anonymous users
PHP file upload with IIS on windows XP/2000 etc
Error: Length parameter must be greater than 0
Multiple File Upload in PHP using IFRAME
Resume or Pause File Uploads in PHP
Exception in module wampmanager.exe at 000F15A0 in Windows 8
Handling file locks in PHP
HTML table output using Nested for loops in PHP
Count occurrences of a character in a String in PHP

More Latest News
Most Viewed Articles (in PHP )
A Basic Example using PHP in AWS (Amazon Web Services)
isset() function in PHP
Parent: child process exited with status 3221225477 -- Restarting
Different versions of PHP - History and evolution of PHP
Upload and Download files with FTP in PHP
GDBM, NDBM, DB2, DB3, DBM, and CDB Databases in PHP
Sorting an Array in PHP
Using Text file as database in PHP
Generate random timestamp between two dates
Function to return number of digits of an integer in PHP
Count occurrences of a character in a String in PHP
The Object (compound) Type in PHP
Variables in PHP
Using list() in PHP
Constants in PHP
Most Emailed Articles (in PHP)
Integers and Floating-Point Numbers in PHP
Appending One Array to Another in PHP
Reading .CSV file in PHP
Perl's Encoding::FixLatin equivalent in PHP
Handling BLOB in PHP and MySQL
File Handling in PHP
Reading word by word from a file in PHP
Upload and Download files with FTP in PHP
History and origin of PHP
Variables in PHP
Strings in PHP
Using list() in PHP
switch Statements in PHP
do...while Loops in PHP
Destructors in PHP