User-data scripts is not running on my custom AMI, but working in standard Amazon linux
Asked Answered
K

15

83

I searched a lot of topic about "user-data script is not working" in these few days, but until now, I haven't gotten any idea about my case yet, please help me to figure out what happened, thanks a lot!

According to AWS User-data explanation:

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.

So I tried to pass my own user-data when instance launch, this is my user-data:

\#!/bin/bash

echo 'test' > /home/ec2-user/user-script-output.txt

But there is no file in this path: /home/ec2-user/user-script-output.txt

I checked /var/lib/cloud/instance/user-data.txt, the file is exist and same as my user-data script.

Also I checked the log in /var/log/cloud-init.log, there is no error message.

But the user-data script is working if I launch an new instance with Amazon linux(2014.09.01), but I'm not sure what difference between my AMI (based on Amazon linux) and Amazon linux.

The only different part I saw is if I run this script:

sudo yum list installed | grep cloud-init

My AMI:

cloud-init.noarch 0.7.2-8.33.amzn1 @amzn-main

Amazon linux:

cloud-init.noarch 0.7.2-8.33.amzn1 installed

I'm not sure this is the reason?

If you need more information, I'm glad to provide, please let me know what happened in my own AMI and how to fix it?

many thanks

Update

Just found an answer from this post,

If I add #cloud-boothook in the top of user-data file, it works!

#cloud-boothook
#!/bin/bash
echo 'test' > /home/ec2-user/user-script-output.txt

But still not sure why.

Khalkha answered 23/11, 2014 at 7:32 Comment(4)
Possible duplicate of How to make EC2 user-data work on freshly built AMI, made with PackerZinkenite
The #cloud-boothook solution is not working for me. UserData is still not running.Freestone
There is an official documentation page now.. After all the attempts this finally worked for me.. aws.amazon.com/premiumsupport/knowledge-center/…Emcee
To debug, you can use this after the instance starts - login and check this log: /var/log/cloud-init-output.logDryer
K
51

User_data is run only at the first start up. As your image is a custom one, I suppose it has already been started once and so user_data is deactivated.

For windows, it can be done by checking a box in Ec2 Services Properties. I'm looking at the moment how to do that in an automated way at the end of the custom image creation.

For linux, I suppose the mechanism is the same, and user_data needs to be re-activated on your custom image.

The #cloud-boothook make it works because it changes the script from a user_data mechanism to a cloud-boothook one that runs on each start.


EDIT :

Here is the code to reactivate start on windows using powershell:

$configFile = "C:\\Program Files\\Amazon\\Ec2ConfigService\\Settings\\Config.xml"
[xml] $xdoc = get-content $configFile
$xdoc.SelectNodes("//Plugin") |?{ $_.Name -eq "Ec2HandleUserData"} |%{ $_.State = "Enabled" }
$xdoc.SelectNodes("//Plugin") |?{ $_.Name -eq "Ec2SetComputerName"} |%{ $_.State = "Enabled" }
$xdoc.OuterXml | Out-File -Encoding UTF8 $configFile

$configFile = "C:\\Program Files\\Amazon\\Ec2ConfigService\\Settings\\BundleConfig.xml"
[xml] $xdoc = get-content $configFile
$xdoc.SelectNodes("//Property") |?{ $_.Name -eq "AutoSysprep"} |%{ $_.Value = "Yes" }
$xdoc.OuterXml | Out-File -Encoding UTF8 $configFile

(I know the question focuses on linux, but it could help others ...)

Kent answered 1/6, 2016 at 7:46 Comment(2)
As your image is a custom one, I suppose it has already been started once and so user_data is deactivated. - nothing is deactivated. User data only runs once per EC2 instance. So if you restart your instance it will not get executed, but if you create new instance, it will get executed.Dryer
@Thibault Deheurles This solution no longer works. For example, I don't have 'C:\\Program Files\\Amazon\\Ec2ConfigService\\' on my system nowRegenerate
V
17

As I tested, there were some bootstrap data in /var/lib/cloud directory. After I cleared that directory, User Data script worked normally.

rm -rf /var/lib/cloud/*
Volva answered 11/4, 2015 at 22:1 Comment(0)
A
14

I have also faced the same issue on Ubuntu 16.04 hvm AMI. I have raised the issue to AWS support but still I couldn't find exact reason/bug which affects it.

But still I have something which might help you.

Before taking AMI remove /var/lib/cloud directory (each time). Then while creating Image, set it to no-reboot.

If these things still ain't working, you can test it further by forcing user-data to run manually. Also tailf /var/log/cloud-init-output.log for cloud-init status. It should end with something like modules:final to make your user-data run. It should not stuck on modules:config.

sudo rm -rf /var/lib/cloud/* sudo cloud-init init sudo cloud-init modules -m final

I don't have much idea whether above commands will work on CentOS or not. I have tested it on Ubuntu.

In my case, I have also tried removing /var/lib/cloud directory, but still it failed to execute user-data in our scenario. But I have came up with different solution for it. What we have did is we have created script with above commands and made that script to run while system boots.

I have added below line in /etc/rc.local to make it happen.

sudo bash /home/ubuntu/force-user-data.sh || exit 1

But here is the catch, it will execute the script on each boot so which will make your user-data to run on every single boot, just like #cloud-boothook. No worries, you can just tweak it by just removing the force-user-data.sh itself at the end. So your force-user-data.sh will look something like

#!/bin/bash sudo rm -rf /var/lib/cloud/* sudo cloud-init init sudo cloud-init modules -m final sudo rm -f /home/ubuntu/force-user-data.sh exit 0

I will appreciate if someone can put some lights on why it is unable to execute the user-data.

Alanealanine answered 4/5, 2017 at 12:40 Comment(1)
amazing. you saved me lots of time!Thrave
C
13

this is the answer as an example: ensure that you have in the headline only #!/bin/bash

#!/bin/bash
yum update -y
yum install httpd mod_ssl
service httpd start
chkconfig httpd on
Caster answered 10/7, 2019 at 13:7 Comment(0)
K
7

I was having a lot of trouble with this. I'll provide detailed walk-though.

My added wrinkle is that I'm using terraform to instantiate the hosts via a launch configuration and autoscaling group.

I could NOT get it to work by adding the script inline in lc.tf

user_data                   = DATA <<
"
#cloud-boothook
#!/bin/bash
echo 'some crap'\'
"
DATA

I could fetch it from user data,

wget http://169.254.169.254/latest/user-data

but noticed I was getting it with the quotes still in it.

This is how I got it to work: I moved to pulling it from a template instead since what you see is what you get.

user_data                   = "${data.template_file.bootscript.rendered}"

This means I also need to declare my template file like so:

data "template_file" "bootscript" {
  template = "${file("bootscript.tpl")}"

}

But I was still getting an error in the cloud init logs /var/log/cloud-init.log [WARNING]: Unhandled non-multipart (text/x-not-multipart) userdata: 'Content-Type: text/cloud...'

Then I found this article about user data formatting user That makes sense, if user-data can come in multiple parts, maybe cloud-init needs cloud-init commands in one place and the script in the other.

So my bootscript.tpl looks like this:

Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
echo "some crap"
--//
Krystakrystal answered 2/2, 2018 at 22:40 Comment(0)
C
4
#!/bin/bash

Do not leave any white space at the start of the line . Use exact command. Otherwise it may run in AMAZON Linux AMI , but it’ll not run in RHEL.

Chamomile answered 12/6, 2020 at 12:48 Comment(0)
A
3

The only way I get it to work was to add the #cloud-boothook before the #!/bin/bash

This is a typical user data script that installs Apache web server on a newly created instance

#cloud-boothook
#!/bin/bash

yum update -y 
yum install -y httpd.x86_64 
systemctl start httpd.service 
systemctl enable httpd.service 

without the #cloud-boothook it does not work, but with it, it works. It seems that different users have different experiences. Some are able to get it to work without it, not sure why.

Axle answered 9/8, 2020 at 19:48 Comment(0)
C
2

On ubuntu 16, removing /var/lib/cloud/* does not work. I removed only instance(s) from the folder /var/lib/cloud/ and then it ran fine for me

I ran:

sudo rm /var/lib/cloud/instance
sudo rm /var/lib/cloud/instances

Then I retried my user data script and it worked fine

Coulisse answered 2/12, 2020 at 9:45 Comment(1)
This worked for me on an Ubuntu, however I needed to run sudo rm -r /var/lib/cloud/instances because instances is a directory.Judi
P
1

I'm using CentOS and the logic for userdata there is simple:

  • In the file /etc/rc.local there is a call for a initial.sh script, but it looks for a flag first:

    if [ -f /var/tmp/initial ]; then
        /var/tmp/initial.sh &
    fi
    

initial.sh is the file that does the execution of user-data, but in the end it deletes the flag. So, if you want your new AMI to execute user-data again, just create the flag again before create the image:

touch /var/tmp/initial
Permission answered 13/4, 2017 at 2:15 Comment(0)
P
1

just add --// at the end of your user data script , example :

#!/bin/bash
#Upgrade ec2 instance
sudo yum update -y 

#Start docker service 
sudo service docker start 

 --//
Plaided answered 13/5, 2021 at 19:15 Comment(1)
Can you explain what this is supposed to do?Romeu
M
1

The proper way to do this in 2023 is to add this block under <powershell> block:

<persist>true</persist>
Milena answered 25/12, 2023 at 12:32 Comment(0)
S
0

User Data should execute fine without using #cloud-boothook (which is used to activate the User Data at the earliest possible time during the boot process).

I started a new Amazon Linux AMI and used your User Data, plus a bit extra:

#!/bin/bash

echo 'bar' > /tmp/bar
echo 'test' > /home/ec2-user/user-script-output.txt
echo 'foo' > /tmp/foo

This successfully created three files.

User Data scripts are executed as root, so it should have permission to create files in any location.

I notice that in your supplied code, one example refers to /home/ec2-user/user-script/output.txt (with a subdirectory) and one example refers to /home/ec2-user/user-script-output.txt (no subdirectory). The command would understandably fail if you attempt to create a file in a non-existent directory, but your "Update" example seems to show that it did actually work.

Sublimation answered 23/11, 2014 at 12:5 Comment(1)
Thanks for answer, sorry about that, the /home/ec2-user/user-script/output.txt is typo, already fixed it, for now I still don't know why it doesn't work if I remove #cloud-boothook, still trying to figure outKhalkha
C
0

Also, If we are using user interactive commands like

sudo yum install java-1.8.0-devel

Then, we need to use with flags like -y

sudo yum install java-1.8.0-devel -y

You can find this in the EC2 documentation under Run commands at launch.

Ref: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-shell-scripts

Caplan answered 9/10, 2020 at 5:32 Comment(0)
B
0

#!/bin/bash

This should be your first line and it should not contains any WHITE SPACES OR OTHER SYMBOLS

User Data should looks like this:

#!/bin/bash
sudo yum update -y 
sudo yum install -y httpd 
sudo systemctl start httpd
sudo systemctl enable httpd
Banded answered 1/5 at 10:59 Comment(0)
P
-1

This worked for me you can try this

#!/bin/bash

#Start docker service 
sudo service docker start 
sudo docker start 6f
sudo docker update --restart=always 6f

 --//
Paraphernalia answered 21/3, 2023 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.