I am working on Ansible playbook to execute some of my tasks. In one of my tasks, I need to switch to particular directory and then execute a command using sudo but I need to do all these things by switching to root user first otherwise it won't work. So in general this is what I do without ansible:
david#machineA:/tmp/parallel-20140422$ sudo su
root#machineA:/tmp/parallel-20140422# sudo ./configure && make && make install
After above steps, I see GNU parallel library is installed in my system correctly. But with the below steps using Ansible, I don't see my GNU library getting installed at all.
- name: install gnu parallel
command: chdir=/tmp/parallel-20140422 sudo ./configure && make && make install
Now my question is how can I switch to root user and execute a particular command. I am running Ansible 1.5.4 and looks like I cannot upgrade. I even tried with below but still it doesn't work:
- name: install gnu parallel
command: chdir=/tmp/parallel-20140422 sudo ./configure && make && make install
sudo: true
sudo_user: root
I am running my playbook using below command:
ansible-playbook -e 'host_key_checking=False' setup.yml -u david --ask-pass --sudo -U root --ask-sudo-pass
You need the become directive.
For example, to start a service as root:
- name: Ensure the httpd service is running
service:
name: httpd
state: started
become: true
you can also become another user, such as the apache user:
- name: Run a command as the apache user
command: somecommand
become: true
become_user: apache
For your case, it will be:
- name: install gnu parallel
command: chdir=/tmp/parallel-20140422 sudo ./configure && make && make install
become: true
From your comment:
I know command module is working fine bcoz I verified for other tasks and they work fine.
command module might be working for other commands, but in this example you use a shell syntax (&&) to execute multiple commands. This syntax will not work in the command module (because this module runs commands directly from Python and does not support combined commands).
You need to use the shell module in this case.
- name: install gnu parallel
shell: ./configure && make && make install
args:
chdir=/tmp/parallel-20140422
sudo: true
sudo_user: root
Related
The below 3 lines are part of my shell script, but it is executing first line and copying file properly.
In-order execute this rpm file, i need to prompt to root user. Hence, 2nd step i wrote. But it is not executing, hence i'm not able to install the rpm file.
aws s3 cp s3://mybucket/oracle-instantclient12.2-basiclite.rpm /home/user1/
sudo su
yum -y install /home/user1/oracle-instantclient12.2-basiclite.rpm
So, any alternate solution to this (sudo su) or tell me how to prompt to root user in-order to install the mentioned rpm file.
Thanks
You could try using sudo -s or
sudo yum -y install /home/user1/oracle-instantclient12.2-basiclite-12.2.0.1.0-1.x86_64.rpm
The first option switches you to the root user, while the second allows you to run the command as root.
aws s3 cp s3://mybucket/oracle-instantclient12.2-basiclite.rpm /home/user1/ && sudo -i yum -y install /home/user1/oracle-instantclient12.2-basiclite.rpm
you'd have to add && (see this answer) in between the two commands and install with sudo yum:
aws s3 cp s3://mybucket/oracle-instantclient12.2-basiclite.rpm /home/user1/ && sudo yum -y install /home/user1/oracle-instantclient12.2-basiclite.rpm
sudo rpm -i /home/user1/oracle-instantclient12.2-basiclite.rpm should also work.
there is no other way to run two commands from a single command-line ...
are you sure the seconds half of the command-line even runs on the remote host? because I'd rather would expect it to be prefixed with send-command (in case running this from a local shell and not on the remote host). it is also not being indicated which Linux distribution you attempt to run the command against; adding the relevant RPM repository and then installing from there, might be the most reliable method of doing so.
I am working on Ansible playbook to execute some of my tasks. In one of my tasks, I need to switch to particular directory and then execute a command using sudo but I need to do all these things by switching to root user first otherwise it won't work. So in general this is what I do without ansible:
david#machineA:/tmp/parallel-20140422$ sudo su
root#machineA:/tmp/parallel-20140422# sudo ./configure && make && make install
After above steps, I see GNU parallel library is installed in my system correctly. But with the below steps using Ansible, I am getting an error:
- name: install gnu parallel
shell: ./configure && make && make install
args:
chdir=/tmp/parallel-20140422
sudo: true
sudo_user: root
Below is the error I am getting:
fatal: [machineA] => args must be a dictionary, received chdir=/tmp/parallel-20140422
I am working with 1.5.4 ansible. I am not sure what's wrong here with my ansible tasks?
Your task should probably look like this:
- name: install gnu parallel
shell: ./configure && make && make install
args:
chdir: /tmp/parallel-20140422
sudo: true
sudo_user: root
I'm a bit confused that you have to give root as sudo_user, because that's the default as far as I know. But then again, if it works for you, it works.
I am in process of automating installation of sage through ansible-playbook. In that I need to run two shell scripts.
Here is how the first shell script look:
#!/bin/bash
# Creating Sage notebook
dir="/root/.sage/sage_notebook.sagenb"
screen -S "Sage_Server" sage -c 'notebook(interface="", directory=$dir, port=80, accounts=true)'
This is the second shell script's code:
#!/bin/bash
# Creating Sage inotebook
address=$(hostname --ip-address)
sage -c "inotebook(interface=" "'$address'" ",port=80,accounts=true)"
And this is how the playbook looks:
---
- hosts: localhost
remote_user: root
tasks:
- name : update system
apt : update_cache=yes
- name : install m4
apt : name=m4 state=present
- name : install build-essential
apt : name=build-essential state=present
- name : install gcc
apt : name=gcc state=present
- name : install gfortran
apt : name=gfortran state=present
- name : install libssl-dev
apt : name=libssl-dev state=present
- name : install python-software-properties
apt : name=python-software-properties state=present
- name : add sage ppa repo
apt_repository: repo='ppa:aims/sagemath'
- name : update system
apt : update_cache=yes
- name : install dvipng
apt : name=dvipng state=present
- name : install sage binary
apt : name=sagemath-upstream-binary state=present
- name : invoke create_sagenb script
command: /usr/bin/screen -d -m sudo /root/databases-and-datamining-iiith/python-scripts/create_sagenb -i -y
- name : invoke start_sage script
command: /usr/bin/screen -d -m sudo /root/databases-and-datamining-iiith/python-scripts/start_sage -i -y
Now when I run the first script, it asks for a new sage password which could be anything. But I am not able to pass that password from the playbook.
Still, if I do
ps -ef | grep sh
I could see that the scripts are running but the sage service is not running.
It needs the password in order to start the service.
Could anyone please tell me how can I provide password as an argument to the shell scripts through command.
I don't know sage and don't know how to provide a password in an alternative way, but if the program ask for a password than you can probably use expect as suggested here.
As a rule of thumb you shouldn't run scripts that needs user input in ansible playbooks.
You could try to use something like
echo "password" | script.sh
or
Create a sage-password file in /etc containing the password and:
script.sh < /etc/sage-password
But this will only work if it is reading from stdin - most applications read password directly from terminal device driver (i.e. /dev/ttyS# ), in that case this trick won't work.
If that's the case, take a look to the sage docs, they should have a more robust way for non-interactive startup.
I'm trying to switch user to the tomcat7 user in order to setup SSH certificates.
When I do su tomcat7, nothing happens.
whoami still ruturns root after doing su tomcat7
Doing a more /etc/passwd, I get the following result which clearly shows that a tomcat7 user exists:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
messagebus:x:101:104::/var/run/dbus:/bin/false
colord:x:102:105:colord colour management daemon,,,:/var/lib/colord:/bin/false
saned:x:103:106::/home/saned:/bin/false
tomcat7:x:104:107::/usr/share/tomcat7:/bin/false
What I'm trying to work around is this error in Hudson:
Command "git fetch -t git#________.co.za:_______/_____________.git +refs/heads/*:refs/remotes/origin/*" returned status code 128: Host key verification failed.
This is my Dockerfile, it takes an existing hudson war file and config that is tarred and builds an image, hudson runs fine, it just can't access git due to certificates not existing for user tomcat7.
FROM debian:wheezy
# install java on image
RUN apt-get update
RUN apt-get install -y openjdk-7-jdk tomcat7
# install hudson on image
RUN rm -rf /var/lib/tomcat7/webapps/*
ADD ./ROOT.tar.gz /var/lib/tomcat7/webapps/
# copy hudson config over to image
RUN mkdir /usr/share/tomcat7/.hudson
ADD ./dothudson.tar.gz /usr/share/tomcat7/
RUN chown -R tomcat7:tomcat7 /usr/share/tomcat7/
# add ssh certificates
RUN mkdir /root/.ssh
ADD ssh.tar.gz /root/
# install some dependencies
RUN apt-get update
RUN apt-get install --y maven
RUN apt-get install --y git
RUN apt-get install --y subversion
# background script
ADD run.sh /root/run.sh
RUN chmod +x /root/run.sh
# expose port 8080
EXPOSE 8080
CMD ["/root/run.sh"]
I'm using the latest version of Docker (Docker version 1.0.0, build 63fe64c/1.0.0), is this a bug in Docker or am I missing something in my Dockerfile?
You should not use su in a dockerfile, however you should use the USER instruction in the Dockerfile.
At each stage of the Dockerfile build, a new container is created so any change you make to the user will not persist on the next build stage.
For example:
RUN whoami
RUN su test
RUN whoami
This would never say the user would be test as a new container is spawned on the 2nd whoami. The output would be root on both (unless of course you run USER beforehand).
If however you do:
RUN whoami
USER test
RUN whoami
You should see root then test.
Alternatively you can run a command as a different user with sudo with something like
sudo -u test whoami
But it seems better to use the official supported instruction.
As a different approach to the other answer, instead of indicating the user upon image creation on the Dockerfile, you can do so via command-line on a particular container as a per-command basis.
With docker exec, use --user to specify which user account the interactive terminal will use (the container should be running and the user has to exist in the containerized system):
docker exec -it --user [username] [container] bash
See https://docs.docker.com/engine/reference/commandline/exec/
In case you need to perform privileged tasks like changing permissions of folders you can perform those tasks as a root user and then create a non-privileged user and switch to it.
FROM <some-base-image:tag>
# Switch to root user
USER root # <--- Usually you won't be needed it - Depends on base image
# Run privileged command
RUN apt install <packages>
RUN apt <privileged command>
# Set user and group
ARG user=appuser
ARG group=appuser
ARG uid=1000
ARG gid=1000
RUN groupadd -g ${gid} ${group}
RUN useradd -u ${uid} -g ${group} -s /bin/sh -m ${user} # <--- the '-m' create a user home directory
# Switch to user
USER ${uid}:${gid}
# Run non-privileged command
RUN apt <non-privileged command>
Add this line to docker file
USER <your_user_name>
Use docker instruction USER
You should also be able to do:
apt install sudo
sudo -i -u tomcat
Then you should be the tomcat user. It's not clear which Linux distribution you're using, but this works with Ubuntu 18.04 LTS, for example.
There's no real way to do this. As a result, things like mysqld_safe fail, and you can't install mysql-server in a Debian docker container without jumping through 40 hoops because.. well... it aborts if it's not root.
You can use USER, but you won't be able to apt-get install if you're not root.
Setting up a Dockerfile to install node prereqs and then set up supervisor in order to run the final npm install command. Running Docker in CoreOS under VirtualBox.
I have a Dockerfile that sets everything up correctly:
FROM ubuntu
MAINTAINER <<Me>>
# Install docker basics
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade -y
# Install dependencies and nodejs
RUN apt-get update
RUN apt-get install -y python-software-properties python g++ make
RUN add-apt-repository ppa:chris-lea/node.js
RUN apt-get update
RUN apt-get install -y nodejs
# Install git
RUN apt-get install -y git
# Install supervisor
RUN apt-get install -y supervisor
RUN mkdir -p /var/log/supervisor
# Add supervisor config file
ADD ./etc/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Bundle app source
ADD . /src
# create supervisord user
RUN /usr/sbin/useradd --create-home --home-dir /usr/local/nonroot --shell /bin/bash nonroot
RUN chown -R nonroot: /src
# set install script to executable
RUN /bin/chmod +x /src/etc/install.sh
#set up .env file
RUN echo "NODE_ENV=development\nPORT=5000\nRIAK_SERVERS={SERVER}" > /src/.env
#expose the correct port
EXPOSE 5000
# start supervisord when container launches
CMD ["/usr/bin/supervisord"]
And then I want to set up supervisord to launch one of a few possible processes, including an installation shell script that I've confirmed to work correctly, install.sh, which is located in the application's /etc directory:
#!/bin/bash
cd /src; npm install
export PATH=$PATH:node_modules/.bin
However, I'm very new to supervisor syntax, and I can't get it to launch the shell script correctly. This is what I have in my supervisord.conf file:
[supervisord]
nodaemon=true
[program:install]
command=install.sh
directory=/src/etc/
user=nonroot
When I run the Dockerfile, everything runs correctly, but when I launch the image, I get the following:
2014-03-15 07:39:56,854 CRIT Supervisor running as root (no user in config file)
2014-03-15 07:39:56,856 WARN Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
2014-03-15 07:39:56,913 INFO RPC interface 'supervisor' initialized
2014-03-15 07:39:56,913 WARN cElementTree not installed, using slower XML parser for XML-RPC
2014-03-15 07:39:56,914 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2014-03-15 07:39:56,915 INFO supervisord started with pid 1
2014-03-15 07:39:57,918 INFO spawnerr: can't find command 'install.sh'
2014-03-15 07:39:58,920 INFO spawnerr: can't find command 'install.sh'
Clearly, I have not set up supervisor correctly to run this shell script -- is there part of the syntax that I'm screwing up?
The best way that I found was setting this:
[program:my-program-name]
command = /path/to/my/command.sh
startsecs = 0
autorestart = false
startretries = 1
think I got this sorted: needed the full path in command, and instead of having user=nonroot in the .conf file, I put su nonroot into the install.sh script.
I had a quick look in the source code for supervisor and noticed that if the command does not contain a forward slash /, it will look in the PATH environmental variable for that file. This imitates the behaviour of execution via shell.
The following methods should fix your initial problem:
Specify the full path of the script (like you have done in your own answer)
Prefix the command with ./, i.e. ./install.sh (in theory, but untested)
Prefix the command with the shell executable, i.e. /bin/bash install.sh
I do not understand why user= does not work for you (have you tried it after fixing execution?), but the problem you encountered in your own answer was probably due to the incorrect usage of su which does not work like sudo. su will create its own interactive shell and will therefore hang while waiting for standard input. To run commands with su, use the -c flag, i.e. su -c "some-program" nonroot. An explicit shell can also be specified with the -s flag if necessary.
I had this issue too. For me, the root cause was failing to set the shebang line. Even if the script can run in bash fine, for supervisord to be able to exec() it, it has to begin with e.g. #!/bin/bash.