Setting up Shell Script for Vagrant Setup - shell

Trying to write a shell script to setup my server environment on Ubuntu through Vagrant and am running into a problem where the script ends unexpectedly. I added the path to the shell script in Vagrant's provision config option.
Vagrant:
# Specify our provision script
config.vm.provision "shell", path: "scripts/bootstrap.sh"
My script:
#!/bin/bash
# Install dependencies for Ruby
sudo apt-get update
sudo apt-get install -y git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common
# Setting up rbenv
echo 'Setting up rbenv'
git clone git://github.com/sstephenson/rbenv.git .rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL
After running, I expect the repository to be cloned into the .rbenv folder and to have rbenv added to $PATH in ~/.bashrc along with the rbenv init function evaluated and put into ~/.bashrc. However, when the script is executed on Vagrant's provision step I end up with the script just cloning the git repository and then terminating without executing anything else in my script.
Output:
==> default: Processing triggers for libc-bin (2.19-0ubuntu6) ...
==> default: Setting up rbenv
==> default: Cloning into '.rbenv'...
And then the script terminates and ~/.bashrc is left unchanged. I was wondering how I can change my shell script so that it will perform the action I want (which is adding rbenv to ~/.bashrc). Any ideas?

As mklement0 said, the script does not run as the vagrant user: it runs as root.
If you want to run the script as the vagrant user you need privileged: false.
config.vm.provision :shell, privileged: false, path: "scripts/bootstrap.sh"
As mklement0 said: use set -xv to debug your provisioning scripts.
If you want to run as another user, don't forget that su user won't work: How do I use su to execute the rest of the bash script as that user?

If you want execute some script like vagrant user, try this.
su vagrant -l -c "echo Hello world"

Related

Trying to set GOPATH and GOROOT in AWS EC2 user data, but it is not working

I am trying to set up GOPATH GOROOT in my AWS EC2 Ubuntu 20.04 user data, but it never worked, every time I connect to the AWS EC2 and view the log in /var/log/cloud-init-output.log it always says
go: not found, but if I key in the echo part it will work.
I am trying to set up multiple EC2 with this basis, so I can't key in every instance myself.
The CloudFormation yaml user data part is below:
UserData:
Fn::Base64: |
#!/bin/bash
wget https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz
tar -C /usr/local -zxvf go1.14.4.linux-amd64.tar.gz
mkdir -p ~/go/{bin,pkg,src}
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export GOROOT=/usr/local/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin:$GOROOT/bin' >> ~/.bashrc
echo 'export GO111MODULE=auto' >> ~/.bashrc
source ~/.bashrc
apt -y update
apt -y install mongodb wget git
systemctl start mongodb
apt -y install git gcc cmake autoconf libtool pkg-config libmnl-dev libyaml-dev
go get -u github.com/sirupsen/logrus
cd ~
git clone --recursive https://github.com/williamlin0504/free5gcWithOCF.git
cd free5gcWithOCF
make
And here is the error inside /var/log/cloud-init-output.log
Error while user data runs
Is there anyone is familiar with this, please I need some help~
In your error message, in the Makefile at line 30 there is a program bin/amf being used
This program appears to be a shell script with a problem in line 1
The nature of the problem is "go: not found"
If you have the bare word "go" in line 1 of the shell script and the path cannot find it then this is what will happen
Probably you need to alter the last line of your userdata shell script to say
PATH=/usr/local/go/bin:$PATH make
I know you have a source command earlier in the script that is supposed to set this up but it doesn't do what you think it does

Installing golang 1.10 on vagrant vbox

I am running the following script from a Vagrantfile and everything is working fine. In the end, I see the output go1.10 linux/amd64 as expected.
But, when I run vagrant ssh I get The program 'go' is currently not installed.
What is the difference between vagrant provision that was able to see go and vagrant ssh that was not able to see go?
config.vm.box = "ubuntu/xenial64"
config.vm.provision "shell" do |s|
s.inline = "
sudo apt-get update
export GOPATH=$HOME/work
sudo curl -O https://storage.googleapis.com/golang/go1.10.linux-amd64.tar.gz
sudo tar -xvf go1.10.linux-amd64.tar.gz
sudo mv go /usr/local
sudo echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
export PATH=$PATH:/usr/local/go/bin
go version" # this row is working fine on the script but not after ssh
end
In order to make your changes to $PATH available to all users, you have to change it in the global profile, not the user's. Change the line
sudo echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
to
sudo echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile

Vagrant - Provisioning script not changing directory

New to vagrant, please help!
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "laravel/homestead"
config.vm.provision "shell", path: "vm-setup/provision.sh"
end
vm-setup/provision.sh
# Update apt-get
apt-get -y update
# Install tree
apt-get install tree
# Create .bash_aliases
sudo echo 'alias cls="clear"' >> ~/.bash_aliases
sudo chsh -s $(which zsh) vagrant
cd /vagrant
provision.sh file runs fine. When I run "vagrant provision" it updates apt-get, installs tree and even changes the shell to ZSH.
But sudo echo 'alias cls="clear"' >> ~/.bash_aliases and cd /vagrant lines do not work, not sure why. When I vagrant ssh into the machine, I am being taken to root directory (/home/vagrant). I would like to start in /vagrant folder.
Vagrant's shell provisioner by default runs with privileged = true:
privileged (boolean) - Specifies whether to execute the shell script
as a privileged user or not (sudo). By default this is "true".
When you perform vagrant ssh you login to a VM as vagrant user.
That's why:
1.
# Create .bash_aliases
sudo echo 'alias cls="clear"' >> ~/.bash_aliases
It writes to root's ~/.bash_aliases and it is really there:
root#vagrant:~# id
uid=0(root) gid=0(root) groups=0(root)
root#vagrant:~# cat .bash_aliases
alias cls="clear"
Solution: write to vagrant's home folder:
# Create .bash_aliases
echo 'alias cls="clear"' >> /home/vagrant/.bash_aliases
chown vagrant:vagrant /home/vagrant/.bash_aliases
2.
cd /vagrant
This means that folder was changed in provision script, nothing else.
Solution: add this statement to vagrant's .bash_aliases as well:
echo 'cd vagrant' >> /home/vagrant/.bash_aliases
Your final vm-setup/provision.sh is:
# Update apt-get
apt-get -y update
# Install tree
apt-get install tree
# Create .bash_aliases
echo 'alias cls="clear"' >> /home/vagrant/.bash_aliases
echo 'cd /vagrant' >> /home/vagrant/.bash_aliases
chown vagrant:vagrant /home/vagrant/.bash_aliases
chsh -s $(which zsh) vagrant
Even not being the case, just for the sake of completion:
I had struggled many times while trying to use Vagrant as testing tool for setup scripts and just now I realized the underlying reason:
Using this Vagrantfile statement:
config.vm.provision "shell", path: "myScript.sh"
myScript.sh is inlined to the virtual machine standard input. This is good in the sense you don't need access to the actual script from inside the virtual machine (typically through /vagrant path).
...but it comes with the drawback that any relative path won't work properly.
Of course: We can adjust it to absolute path based on /vagrant. But this requires to modify the script we are trying to test.
So in this case (and in my opinion in any case we are not going to disable /vagrant share), it is a better solution to use "inline:" option with the "machine-internal" path:
config.vm.provision "shell", inline: "/vagrant/myScript.sh"
...This will inline this statement instead of the contents of the file and relative paths (or even "script path based" ones such as $(dirname "${0}")/relative/path) are going to work properly.
Additionally, if the setup script you are going to test is intended to be executed by non privileged users (for example if it is going to set up some user configuration we will expect to work just after a vagrant ssh -with vagrant user-) it is also a good idea to add the privileged: false option, pointed out by #Nickolay:
config.vm.provision "shell", inline: "/vagrant/myScript.sh", privileged: false

debugging a vagrant setup bash script

I have a Vagrantfile with a setup script as below. I've run it several times with vagrant up and I know the first few commands work, but later ones I know did not succeed.
Vagrantfile:
# -*- mode: ruby -*-
VAGRANTFILE_API_VERSION = "2"
$setup = <<END
# some bash code
# ...
# something that somehow never runs
sudo chown -R vagrant:vagrant /some/path
END
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "puppetlabs/centos-7.0-64-nocm"
config.vm.define "client", primary: true do |client|
client.vm.hostname = "client.example.com"
client.vm.network :private_network, ip: "192.168.250.10"
client.vm.provision "shell", inline: $setup
end
end
Is there any way to see what errors happen when scripts are run on vagrant up?
I tried vagrant up --debug &> vagrant.log but the output was literally thousands of lines and I couldn't find anything useful (or didn't know what to look for, which is more likely).
echo should do the trick and display messages from your shell file.
echo "running update ..."
sudo apt-get update
echo "running install lib ..."
sudo apt-get install --yes git-all libreadline-dev build-essential curl git m4 python-setuptools ruby texinfo libbz2-dev libcurl4-openssl-dev libexpat-dev libncurses-dev zlib1g-dev
echo "install rvm ..."
curl -L https://get.rvm.io | bash -s stable --ruby=2.0.0
all echo messages will be displayed in the output when running the shell provisioning
If you need to redirect stderr to stdout you can do something like grep * 2>&1 -
ref: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html
While Frédéric Henri's answer is definitely recommended and helpful, vagrant also comes with some built in debugging help which you can read more about here, but basically you can vagrant up with a debug flag for more information:
vagrant up --debug

Install Oh My Zsh on a Vagrant Box as part of the bootstrap process

I'd like to add Oh My Zsh to my Vagrant bootstrap process, but a straight install isn't working.
via curl:
curl -L http://install.ohmyz.sh | sh
via wget:
wget --no-check-certificate http://install.ohmyz.sh -O - | sh
Found the solution:
# Added zsh shell.
sudo apt-get install zsh
wget --no-check-certificate https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
sudo chsh -s /bin/zsh vagrant
zsh
As an nice addition, so that your terminals don't look too similar on the different boxes
# Change the oh my zsh default theme.
sed -i 's/ZSH_THEME="robbyrussell"/ZSH_THEME="3den"/g' ~/.zshrc
Here's a complete Vagrantfile that installs Oh My Zsh on an Ubuntu 14.04.2 LTS box and sets it as the default shell for standard vagrant user.
This works with Vagrant 1.7.2. (Your milage may vary with different versions.) It uses the directions from the Manual Installation section of the Readme instead of trying to use the automatic scripts.
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Pick a box to use:
config.vm.box = "ubuntu/trusty64"
############################################################
# Oh My ZSH Install section
# Install git and zsh prerequisites
config.vm.provision :shell, inline: "apt-get -y install git"
config.vm.provision :shell, inline: "apt-get -y install zsh"
# Clone Oh My Zsh from the git repo
config.vm.provision :shell, privileged: false,
inline: "git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh"
# Copy in the default .zshrc config file
config.vm.provision :shell, privileged: false,
inline: "cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc"
# Change the vagrant user's shell to use zsh
config.vm.provision :shell, inline: "chsh -s /bin/zsh vagrant"
############################################################
end
As a bonus, you can do a one time copy of your host machine's .zshrc file to the vagrant box with:
config.vm.provision "file", source: "~/.zshrc", destination: ".zshrc"
(Keep in mind, You may have to figure things that don't work initially because of differences between the host machine and the vagrant box's setups.)
I came here because had a same issue. After seeing some answer and trying it, mostly the zsh & oh-my-zsh got installed as root. The root will set his $SHELL with zsh. What I want is they are installed as user vagrant. The bootstrap was done by root when provisioning. So the logic is try to run install zsh & oh-my-zsh as user. Here is what I did after trying many times until I got what I wanted :
## In Vagrantfile try to call bootstrap.sh
config.vm.provision "shell", path: "bootstrap.sh"
## This is the bootstrap.sh
aptInstl() {
DEBIAN_FRONTEND=noninteractive apt-get install -qq -y $1 > /dev/null
}
install_zsh() {
aptInstl "zsh"
su -l vagrant -s "/bin/sh" \
-c "curl -fsSO https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh; chmod 755 install.sh; ./install.sh --unattended"
chsh -s /bin/zsh vagrant
}
install_miscellaneous() {
apt-get update > /dev/null
apt-get upgrade > /dev/null
for i in curl git; do
aptInstl "$i"
done
}
main() {
install_miscellaneous
install_zsh
}
main
And It works perfectly :)
When you are done try to vagrant ssh it will automatically logged you in with zsh shell and oh-my-zsh. Here is the complete file.

Resources