Looking for something? Try here..

Tuesday, March 30, 2021

Ansible ping and types of Unix shells, a learning...

 I've just started to learn the basics of Ansible which is a powerful automation tool. The first step of any automation is to setup the environment on which we are working. I'm referring Frits Hoogland's blog which is very easy to understand the basics of Ansible. 

The first step is to set up your hosts file and test the connectivity between the servers. We have an inbuilt Ansible ping module to do this. Here is how my hosts file looks like 

[oracle@linux-8 ansible-project]$ cat hosts
192.168.56.131
192.168.56.151

[l7]
192.168.56.151

[l8]
192.168.56.131
192.168.56.181

[oracle@linux-8 ansible-project]$
I'm using the below command to test the ping and the result is also provided. Just keep in mind I have already setup password less communication and hence not required to pass the password. If I still need to prompt for password, I can provide -k option to the command line. 
[oracle@linux-8 ansible-project]$ ansible l8 -m ping -u oracle
SSH password:
[WARNING]: Unhandled error in Python interpreter discovery for host 192.168.56.131: unexpected output from Python interpreter discovery
192.168.56.131 | FAILED! => {
    "msg": "failed to transfer file to /home/oracle/.ansible/tmp/ansible-local-32681q1m7n_gx/tmpzvfmvwgz /home/oracle/.ansible/tmp/ansible-tmp-1617045011.6527164-32687-33868194395919/AnsiballZ_ping.py:\n\nOracle Home set as /u01/db/122 and SID=orcl\n"
}
192.168.56.181 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
[oracle@linux-8 ansible-project]$
We can see the ping failed for 192.168.56.131 server with the error line including "\n\nOracle Home set as /u01/db/122 and SID=orcl\n"

This "\n\nOracle Home set as /u01/db/122 and SID=orcl\n" is a environment info message I have set in the server when we login as Oracle user using .bashrc file. 

Normal ssh works without any issues.
[oracle@linux-8 ansible-project]$ ssh 192.168.56.131
Web console: https://linux75.selvapc.com:9090/ or https://10.0.2.15:9090/

Last login: Mon Mar 29 14:46:24 2021 from 192.168.56.181
Oracle Home set as /u01/db/122 and SID=orcl
[oracle@linux75 ~]$
We can see the info message line once we login. 

All that Ansible ping command does is try to connect to host, verify a usable python and return pong on success. So, the question here is why my ssh command works without any issues but not my Ansible ping. 

The answer lies in how the connection is being established to the server. There are 4 types of shells in Unix. 
  • Interactive login                     - Login session started using graphical interface or by providing username/password via ssh
  • Interactive non-login             - Sessions started by opening another terminal in a server
  • Non interactive non-login     - Sessions started by scripts execution where the commands are run and exits the shell. We can't interact with these shells
  • Non interactive login     - Providing a command to run using ssh like "echo "some command" |ssh servername". Here instead of login, the session will run the "some command" and exits
So now, the difference in these shells is that the Login shells (shells started by the login system process, or by your X display manager) uses or reads .profile or .login files to set your environment or initialize your environment
Non interactive login/non-login shells, such as scripts started by shell or the Ansible ping that we are using now reads .bashrc or .kshrc files to initialize environment. Hence we should not set up any echo statements which would then become stdout to the shell initialization (which the shell won't expect) and errors out as a result. 

My .bashrc file looked like the below which was causing the issue with the non interactive session from Ansible ping. 
[oracle@linux75 ~]$ cat .bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
export ORACLE_BASE=/u01/db
export ORACLE_HOME=/u01/db/122
export PATH=$PATH:$ORACLE_HOME/bin
export ORACLE_SID=orcl
echo "Oracle Home set as $ORACLE_HOME and SID=$ORACLE_SID"

Once I remove the "echo" line from the file, I didn't have issues from the Ansible ping. We can simply move the echo line to the .bash_profile (I already had the entry in the .bash_profile file as well which is why when I previously did a ssh we got the info message once we login) which is the file used to initialize when we start interactive session. 
[oracle@linux-8 ansible-project]$ ansible l8 -m ping -u oracle -k
SSH password:
192.168.56.181 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
192.168.56.131 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
[oracle@linux-8 ansible-project]$
You can notice now I have used -k option and the password is being prompted. Ping works as expected on all the servers in the group l8 and now we can proceed further with our automations..

Hope you have learnt regarding different types of Unix shells and the different initialization files they use. 

References: 

Happy Shelling!!! :)

1 comment: