Ansible: escape quotes and listing users password expiry information - ansible

How to escape in shell module quotation?
I've tried as follows:
- name: UList
shell: "cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c \" echo {} ; chage -l {}\""
and
- name: UList
shell: "cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c \' echo {} ; chage -l {}\'"
Where is a mistake?

This playbook worked for me, hope this will be helpful for you too. You can use single quotes' for a command if you have an issue escaping " quote
Either do it this way
'cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c " echo {} ; chage -l {}"'
Or
"cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c ' echo {} ; chage -l {}'"
Both are working i have tested it.
---
- name: Set my hosts variable
hosts: localhost
tasks:
- name: UList
shell: 'cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c " echo {} ; chage -l {}"'
register: result
- name: debug
debug:
msg: "{{result}}"
Or
For the output you are expecting for that you can use
awk -F':' '{ system("echo " $1 " && chage -l " $1) }' /etc/passwd
Command explanation
---
- name: Set my hosts variable
hosts: localhost
tasks:
- name: UList
shell: "awk -F':' '{ system(\"echo \" $1 \" && chage -l \" $1) }' /etc/passwd"
register: result
- name: debug
debug:
msg: "{{result}}"

Related

Execute bash script via ansible playbook

I'm looking to run the following shell script via ansible playbook.
#!/bin/bash
oci compute instance list --lifecycle-state RUNNING --region ca-toronto-1 --compartment-id < compartment OCID> --all | grep display-name -A 0 > hostnames.txt
for line in `cat hostnames.txt`
do
#echo $line
if [[ $line == *","* ]]; then
# hostname=$(echo ${line//"display-name"/} | tr -d '",: ')
hostname=$(echo "$line" | tr -d '",')
echo "$hostname"
ssh -tt "$hostname" "sudo puppet agent -tv && sleep 10"
# break
fi
done
This works just like how i want when i run the shell script but I get a blank output when i run via ansible.
Playbook:
---
- name: puppet agent trigger
gather_facts: false
become_user: true
hosts: all
tasks:
- name: trigger puppet agent
shell: |
oci compute instance list --lifecycle-state RUNNING --region ca-toronto-1 --compartment-id <compartment OCID> --all | grep display-name -A 0 > hostnames.txt
for line in `cat hostnames.txt`
do
if [[ $line == *","* ]]; then
hostname=$(echo "$line" | tr -d '",')
echo "$hostname"
ssh -tt "$hostname" "sudo puppet agent -tv && sleep 10"
fi
done
register: shell_output
- debug:
msg: "{{ shell_output.stdout }}"
Please point me as to what im missing.
According the description of your use case it seems to be recommended to transfer the whole logic of the script into Ansible itself. To do so and in respect to the comment regarding add_host_module, you could use an approach like
- name: Create an instance list
shell:
cmd: oc get nodes --no-headers | cut -d " " -f 1 | tr '\n' "," | rev | cut -c 2- | rev
register: instance_list
changed_when: false
To generate the instance_list I've used an OpenShift cluster as example, because I don't have something like oci compute instance list ... accessible.
- name: Add all hosts from instance_list to the script group
add_host:
name: '{{ item }}'
groups: script
loop: "{{ instance_list }}"
From there you could proceed further to execute your command puppet agent -tv && sleep 10.

How to pass value to ansible command module

I am new to ansible and trying to write some basic playbook. I need to run a command via command module, but that command needs use a value derived from other command this is what I have:
+++++++++++++++++++++++++++++++++++++++++++
---
- name: Post SentinelOne Agent
hosts: all
tasks:
- name: user sentinel exist
command: /usr/bin/grep sentinelone /etc/passwd
register: user_exist
ignore_errors: yes
- name: Create sentinelone user using existing id, only if the user does not exist
command: "useradd -d /opt/sentinelone/home/ -u `ls -ld /opt/sentinelone/ | awk '{print $3}'`** -f 1 -l -g sentinelone -s /sbin/nologin sentinelone"
when: user_exist.rc == 1
- name: Check again to confirm user exist for copy purpose
command: /usr/bin/grep sentinelone /etc/passwd
register: does_user_exist
ignore_errors: yes
- name: Whitelist sentinelone user ... Copy line from /etc/passwd
command: echo "`cat /etc/passwd | grep -i sentinelone`" >> /etc/crypt/passwd_local
when: does_user_exist.rc == 0
- name: Whitelist sentinelone user ... Copy line from /etc/shadow
command: echo "`cat /etc/shadow | grep -i sentinelone`" >> /etc/crypt/shadow_local
when: does_user_exist.rc == 0
+++++++++++++++++++++++++++++
get error:
for
command: "useradd -d /opt/sentinelone/home/ -u `ls -ld /opt/sentinelone/ | awk '{print $3}'`** -f 1 -l -g sentinelone -s /sbin/nologin sentinelone"
STDERR:
useradd: invalid user ID '`ls'
MSG:
non-zero return code

Bash is redirecting output from command only after script has finished

Context
Got a daft script that checks a process is running on a group of hosts, like a watchdog, as I say it's a daft script so bear in mind it isn't 'perfect' by scripting standards
Problem
I've ran bash -x and can see that the script finishes its first check without actually redirecting the output of the command to the file which is very frustrating, it means each host is actually being evaluated to the last hosts output
Code
#!/bin/bash
FILE='OUTPUT'
for host in $(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {' print $2 ' })
do ssh -n -f $host -i <sshkey> 'ps ax | grep myprocess | wc -l' > $FILE 2> /dev/null
cat $FILE
if grep '1' $FILE ; then
echo "Process is NOT running on $host"
cat $FILE
else
cat $FILE
echo "ALL OK on $host"
fi
cat $FILE
done
Script traceback
++ cat /etc/hosts
++ awk '{ print $2 }'
++ grep 'webserver.[2][1-2][0-2][0-9]'
+ for host in '$(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {'\'' print $2 '\''})'
+ ssh -n -f webserver.2100 -i <omitted> 'ps ax | grep myprocess | wc -l'
+ cat OUTPUT
+ grep 1 OUTPUT
+ cat OUTPUT
+ echo 'ALL OK on webserver.2100'
ALL OK on webserver.2100
+ cat OUTPUT
+ printf 'webserver.2100 checked \n'
webserver.2100 checked
+ for host in '$(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {'\'' print $2 '\''})'
+ ssh -n -f webserver.2101 -i <omitted> 'ps ax | grep myprocess | wc -l'
+ cat OUTPUT
2
+ grep 1 OUTPUT
+ cat OUTPUT
2
+ echo 'ALL OK on webserver.2101'
ALL OK on webserver.2101
+ cat OUTPUT
2
+ printf 'webserver.2101 checked \n'
webserver.2101 checked
Issue
As you can see, it's registering nothing for the first host, then after it is done, it's piping the data into the file, then the second host is being evaluated for the previous hosts data...
I suspect its to do with redirection, but in my eyes this should work, it doesn't so it's frustrating.
I think you're assuming that ps ax | grep myprocess will always return at least one line (the grep process). I'm not sure that's true. I'd rewrite that like this:
awk '/webserver.[2][1-2][0-2][0-9]/ {print $2}' /etc/hosts | while IFS= read -r host; do
output=$( ssh -n -f "$host" -i "$sshkey" 'ps ax | grep "[m]yprocess"' )
if [[ -z "$output" ]]; then
echo "Process is NOT running on $host"
else
echo "ALL OK on $host"
fi
done
This trick ps ax | grep "[m]yprocess" effectively removes the grep process from the ps output:
the string "myprocess" matches the regular expression "[m]yprocess" (that's the running "myprocess" process), but
the string "[m]yprocess" does not match the regular expression "[m]yprocess" (that's the running "grep" process)

ansible shell escape single and double quotes

I'm trying to execute this command:
ps -eo pid,args --cols=10000 | awk '/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO["pid"] { print $1 }'
whith ansible -m shell module (not working example):
ansible -m shell -a '"'ps -eo pid,args --cols=10000 | awk '/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO[\'pid\'] { print $1 }' '"' all
One of the ways would be to put that into a file, but still it would be nice to run as a command - any ideas?
Bash escaping rules will do:
ansible localhost -m shell -a "ps -eo pid,args --cols=10000 | awk '/\\/opt\\/logstash\\/logstash-1.5.3\\// && \$1 != PROCINFO[\"pid\"] { print \$1 }'"
Mine alternative version that worked:
ansible -m command -a "ps a |grep -E '/opt/logstash/logstash-1.5.3/vendor/jruby' " all --sudo
Check if the process are running:
ansible -m shell -a "ps aux |grep -E '/opt/logstash/logstash-1.5.3/vendor/jruby'|grep -v -e grep |wc" all
A simple way (i.e. without having to rewrite the command much or introduce a bunch of escapes) is to use a temporary variable.
Your original command:
ps -eo pid,args --cols=10000 \
| awk '/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO["pid"] { print $1 }'
Corresponding ansible call:
x='/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO["pid"] { print $1 }'; \
ansible all -m shell -a "ps -eo pid,args --cols=10000 | awk '$x'"

Executing a string command - Bash

I have the following command line:
egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 | awk 'NR==1{ips=$1} NR>1{ips=ips ", " $1} $2=="namenode"{nn=$1} END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}'
And that's producing a command line which I will use in my chef cookbook to start a MapR cluster:
/opt/mapr/server/configure.sh -C 10.32.237.251 -Z 10.32.237.251 -N mycluster --create-user -D /dev/xvdb
My first command only prints out that command. How can I modify that command, or add anything else, to automatically execute the command produced by the awk?
Pipe it to the shell:
egrep '^[0-9]' /etc/hosts | grep -v 127.0.0.1 \
| awk 'NR==1{ips=$1}
NR>1{ips=ips ", " $1}
$2=="namenode"{nn=$1}
END{ printf "/opt/mapr/server/configure.sh -C %s -Z %s -N mycluster --create-user -D /dev/xvdb\n", ips, nn}' \
| bash

Resources