Menu
Amazon Elastic Compute Cloud
User Guide for Linux Instances

Running Commands on Your Linux Instance at Launch

When you launch an instance in Amazon EC2, you have the option of passing user data to the instance that can be used to perform common automated configuration tasks and even run scripts after the instance starts. You can pass two types of user data to Amazon EC2: shell scripts and cloud-init directives. You can also pass this data into the launch wizard as plain text, as a file (this is useful for launching instances using the command line tools), or as base64-encoded text (for API calls).

If you are interested in more complex automation scenarios, consider using AWS CloudFormation and AWS OpsWorks. For more information, see the AWS CloudFormation User Guide and the AWS OpsWorks User Guide.

For information about running commands on your Windows instance at launch, see Running Commands on Your Windows Instance at Launch and Managing Windows Instance Configuration in the Amazon EC2 User Guide for Windows Instances.

In the following examples, the commands from the Installing a LAMP Web Server tutorial are converted to a shell script and a set of cloud-init directives that executes when the instance launches. In each example, the following tasks are executed by the user data:

  • The distribution software packages are updated.

  • The necessary web server, php, and mysql packages are installed.

  • The httpd service is started and turned on via chkconfig.

  • The www group is added, and ec2-user is added to that group.

  • The appropriate ownership and file permissions are set for the web directory and the files contained within it.

  • A simple web page is created to test the web server and PHP engine.

By default, user data and cloud-init directives only run during the first boot cycle when you launch an instance. However, AWS Marketplace vendors and owners of third-party AMIs may have made their own customizations for how and when scripts run.

Prerequisites

The following examples assume that your instance has a public DNS name that is reachable from the Internet. For more information, see Step 1: Launch an Instance. You must also configure your security group to allow SSH (port 22), HTTP (port 80), and HTTPS (port 443) connections. For more information about these prerequisites, see Setting Up with Amazon EC2.

Also, these instructions are intended for use with Amazon Linux, and the commands and directives may not work for other Linux distributions. For more information about other distributions, such as their support for cloud-init, see their specific documentation.

User Data and Shell Scripts

If you are familiar with shell scripting, this is the easiest and most complete way to send instructions to an instance at launch, and the cloud-init output log file (/var/log/cloud-init-output.log) captures console output so it is easy to debug your scripts following a launch if the instance does not behave the way you intended.

Important

User data scripts and cloud-init directives only run during the first boot cycle when an instance is launched.

User data shell scripts must start with the #! characters and the path to the interpreter you want to read the script (commonly /bin/bash). For a great introduction on shell scripting, see the BASH Programming HOW-TO at the Linux Documentation Project (tldp.org).

Scripts entered as user data are executed as the root user, so do not use the sudo command in the script. Remember that any files you create will be owned by root; if you need non-root users to have file access, you should modify the permissions accordingly in the script. Also, because the script is not run interactively, you cannot include commands that require user feedback (such as yum update without the -y flag).

Adding these tasks at boot time adds to the amount of time it takes to boot the instance. You should allow a few minutes of extra time for the tasks to complete before you test that the user script has finished successfully.

To pass a shell script to an instance with user data

  1. Follow the procedure for launching an instance at Launching Your Instance from an AMI, but when you get to Step 6 in that procedure, enter your shell script in the User data field, and then complete the launch procedure.

    In the example script below, the script creates and configures our web server.

    Copy
    #!/bin/bash yum update -y yum install -y httpd24 php56 mysql55-server php56-mysqlnd service httpd start chkconfig httpd on groupadd www usermod -a -G www ec2-user chown -R root:www /var/www chmod 2775 /var/www find /var/www -type d -exec chmod 2775 {} + find /var/www -type f -exec chmod 0664 {} + echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
  2. Allow enough time for the instance to launch and execute the commands in your script, and then check to see that your script has completed the tasks that you intended.

    For our example, in a web browser, enter the URL of the PHP test file the script created. This URL is the public DNS address of your instance followed by a forward slash and the file name.

    http://my.public.dns.amazonaws.com/phpinfo.php

    You should see the PHP information page. If you are unable to see the PHP information page, check that the security group you are using contains a rule to allow HTTP (port 80) traffic. For more information, see Adding Rules to a Security Group.

  3. (Optional) If your script did not accomplish the tasks you were expecting it to, or if you just want to verify that your script completed without errors, examine the cloud-init output log file at /var/log/cloud-init-output.log and look for error messages in the output.

    For additional debugging information, you can create a Mime multipart archive that includes a cloud-init data section with the following directive:

    Copy
    output : { all : '| tee -a /var/log/cloud-init-output.log' }

    This directive sends command output from your script to /var/log/cloud-init-output.log. For more information about cloud-init data formats and creating Mime multi part archive, see cloud-init Formats.

User Data and cloud-init Directives

The cloud-init package configures specific aspects of a new Amazon Linux instance when it is launched; most notably, it configures the .ssh/authorized_keys file for the ec2-user so you can log in with your own private key. For more information, see cloud-init.

The cloud-init user directives can be passed to an instance at launch the same way that a script is passed, although the syntax is different. For more information about cloud-init, go to http://cloudinit.readthedocs.org/en/latest/index.html.

Important

User data scripts and cloud-init directives only run during the first boot cycle when an instance is launched.

The Amazon Linux version of cloud-init does not support all of the directives that are available in the base package, and some of the directives have been renamed (such as repo_update instead of apt-upgrade).

Adding these tasks at boot time adds to the amount of time it takes to boot an instance. You should allow a few minutes of extra time for the tasks to complete before you test that your user data directives have completed.

To pass cloud-init directives to an instance with user data

  1. Follow the procedure for launching an instance at Launching Your Instance from an AMI, but when you get to Step 6 in that procedure, enter your cloud-init directive text in the User data field, and then complete the launch procedure.

    In the example below, the directives create and configure a web server. The #cloud-config line at the top is required in order to identify the commands as cloud-init directives.

    Copy
    #cloud-config repo_update: true repo_upgrade: all packages: - httpd24 - php56 - mysql55-server - php56-mysqlnd runcmd: - service httpd start - chkconfig httpd on - groupadd www - [ sh, -c, "usermod -a -G www ec2-user" ] - [ sh, -c, "chown -R root:www /var/www" ] - chmod 2775 /var/www - [ find, /var/www, -type, d, -exec, chmod, 2775, {}, + ] - [ find, /var/www, -type, f, -exec, chmod, 0664, {}, + ] - [ sh, -c, 'echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php' ]
  2. Allow enough time for the instance to launch and execute the directives in your user data, and then check to see that your directives have completed the tasks you intended.

    For our example, in a web browser, enter the URL of the PHP test file the directives created. This URL is the public DNS address of your instance followed by a forward slash and the file name.

    http://my.public.dns.amazonaws.com/phpinfo.php

    You should see the PHP information page. If you are unable to see the PHP information page, check that the security group you are using contains a rule to allow HTTP (port 80) traffic. For more information, see Adding Rules to a Security Group.

  3. (Optional) If your directives did not accomplish the tasks you were expecting them to, or if you just want to verify that your directives completed without errors, examine the output log file at /var/log/cloud-init-output.log and look for error messages in the output. For additional debugging information, you can add the following line to your directives:

    Copy
    output : { all : '| tee -a /var/log/cloud-init-output.log' }

    This directive sends runcmd output to /var/log/cloud-init-output.log.

User Data and the AWS CLI

You can use the AWS CLI to specify, modify, and view the user data for your instance. For information about viewing user data from your instance using instance metadata, see Retrieving User Data.

On Windows, you can use the AWS Tools for Windows PowerShell instead of using the AWS CLI. For more information, see User Data and the Tools for Windows PowerShell in the Amazon EC2 User Guide for Windows Instances.

Example: Specify User Data at Launch

To specify user data when you launch your instance, use the run-instances command with the --user-data parameter. With run-instances, the AWS CLI performs base64 encoding of the user data for you.

The following example shows how to specify a script as a string on the command line:

Copy
aws ec2 run-instances --image-id ami-abcd1234 --count 1 --instance-type m3.medium \ --key-name my-key-pair --subnet-id subnet-abcd1234 --security-group-ids sg-abcd1234 \ --user-data echo user data

The following example shows how to specify a script using a text file. Be sure to use the file:// prefix to specify the file.

Copy
aws ec2 run-instances --image-id ami-abcd1234 --count 1 --instance-type m3.medium \ --key-name my-key-pair --subnet-id subnet-abcd1234 --security-group-ids sg-abcd1234 \ --user-data file://my_script.txt

The following is an example text file with a shell script.

Copy
#!/bin/bash yum update -y service httpd start chkconfig httpd on

Example: Modify the User Data of a Stopped Instance

You can modify the user data of a stopped instance using the modify-instance-attribute command. With modify-instance-attribute, the AWS CLI does not perform base64 encoding of the user data for you.

On Linux, use the base64 command to encode the user data.

Copy
base64 my_script.txt >my_script_base64.txt

On Windows, use the certutil command to encode the user data. Before you can use this file with the AWS CLI, you must remove the first (BEGIN CERTIFICATE) and last (END CERTIFICATE) lines.

Copy
certutil -encode my_script.txt my_script_base64.txt notepad my_script_base64.txt

Use the --user-data and --value parameters to use the encoded text file to specify the user data. Be sure to use the file:// prefix to specify the file.

Copy
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --value file://my_script_base64.txt

Example: View User Data

To retrieve the user data for an instance, use the describe-instance-attribute command. With describe-instance-attribute, the AWS CLI does not perform base64 decoding of the user data for you.

Copy
aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData

The following is example output with the user data base64 encoded.

{
    "UserData": {
        "Value": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQpzZXJ2aWNlIGh0dHBkIHN0YXJ0CmNoa2NvbmZpZyBodHRwZCBvbg=="
    },
    "InstanceId": "i-1234567890abcdef0"
}

On Linux, use the --query option to get the encoded user data and the base64 command to decode it.

Copy
aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --output text --query "UserData.Value" | base64 --decode

On Windows, use the --query option to get the coded user data and the certutil command to decode it. Note that the encoded output is stored in a file and the decoded output is stored in another file.

Copy
aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --output text --query "UserData.Value" >my_output.txt certutil -decode my_output.txt my_output_decoded.txt type my_output_decoded.txt

The following is example output.

#!/bin/bash
yum update -y
service httpd start
chkconfig httpd on