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, andmysqlpackages are installed. -
The
httpdservice is started and turned on via chkconfig. -
The www group is added, and
ec2-useris 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.
Contents
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
-
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.
#!/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 -
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.phpYou 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.
-
(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.logand 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:
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
-
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-configline at the top is required in order to identify the commands as cloud-init directives.#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' ] -
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.phpYou 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.
-
(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.logand look for error messages in the output. For additional debugging information, you can add the following line to your directives: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:
aws ec2 run-instances --image-id ami-abcd1234--count1--instance-typem3.medium\ --key-namemy-key-pair--subnet-id subnet-abcd1234--security-group-ids sg-abcd1234\ --user-dataecho 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.
aws ec2 run-instances --image-id ami-abcd1234--count1--instance-typem3.medium\ --key-namemy-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.
#!/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.
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.
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.
aws ec2 modify-instance-attribute --instance-idi-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.
aws ec2 describe-instance-attribute --instance-idi-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.
aws ec2 describe-instance-attribute --instance-idi-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.
aws ec2 describe-instance-attribute --instance-idi-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


