How to execute Ad-Hoc commands on remote node using ansible
Here in this article we will see how we can install ansible and manage a remote node by gathering information related to the remote node from the controller node. We will look at some the Ad-hoc modules which we can execute using the ansible tool.
Test Environment
Ansible Controller
Ansible Node
If you are interested in watching the video. Here is the YouTube video on the same step by step procedure outlined below.
Procedure
Step1: Install Ansible from RPM repository
Let’s install ansible on the Ansible controller node.
sudo dnf install ansible
Step2: Validate Ansible Installation
Verify the ansible installation by checking the version information.
ansible --version
Output:
ansible 2.9.18
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/admin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.8/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.8.2 (default, Feb 28 2020, 00:00:00) [GCC 10.0.1 20200216 (Red Hat 10.0.1-0.8)]
Step3: Create an Inventory file with the nodes to manage
Let’s define the inventory file with the hostname or ip address of the remote which we would like to manage.
File: /etc/ansible/hosts
Output:
[stack]
192.168.47.130
Step4: Generate SSH key pairs and copy to remote node
Generate ssh private and public for user admin.
ssh-keygen -t rsa -C admin
ls -ltr ~/.ssh/
Output:
-rw-r--r--. 1 admin admin 176 Mar 29 15:53 known_hosts
-rw-r--r--. 1 admin admin 559 Mar 29 15:56 id_rsa.pub
-rw-------. 1 admin admin 2590 Mar 29 15:56 id_rsa
Once the key pair are generated we can copy the public key to the remote node as shown below.
ssh-copy-id -i ~/.ssh/id_rsa.pub admin@192.168.47.130
Output:
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/admin/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
admin@192.168.47.130's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'admin@192.168.47.130'"
and check to make sure that only the key(s) you wanted were added.
Step5: Validate SSH connection
We can validate the remote ssh login using the user admin once the ssh public key has been copied to the remote host. You should be able to login without asking for the password.
ssh admin@192.168.47.130
Output:
Web console: https://ansinode.stack.com:9090/ or https://192.168.47.130:9090/
Last login: Mon Mar 29 15:54:35 2021 from 192.168.47.129
Now that we are able to remote ssh to our node using user admin. Lets try to run some Ad-hoc command using ansible. Ad-hoc commands can be used to manage the files, packages, users, groups, services and facts about the remote node. The default module for the ansible command-line utility is the ansible.builtin.command module.
Step6: Ping the remote node
As a first step, lets try to use the ping module to ping the remote and check what is the response we get from the remote node.
ansible stack -m ping
Output:
192.168.47.130 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
Step7: Check the kernel version and hostname of the remote host
In this step we will run the ad-hoc command ‘uname -a’ to get the hostname and kernal version details as shown below.
ansible stack -a "uname -a"
Output:
192.168.47.130 | CHANGED | rc=0 >>
Linux ansinode.stack.com 5.6.6-300.fc32.x86_64 #1 SMP Tue Apr 21 13:44:19 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
Step8: Check the free memory
Verify the free memory that is available on the remote node as shown below.
ansible stack -a "free -m"
Output:
192.168.47.130 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 1951 257 1220 1 472 1542
Swap: 2047 0 2047
Step9: Check the IP address
Verify the IP address of the remote node as shown below.
ansible stack -a "ip addr"
Output:
192.168.47.130 | CHANGED | rc=0 >>
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:63:e4:47 brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 192.168.47.130/24 brd 192.168.47.255 scope global dynamic noprefixroute ens33
valid_lft 1093sec preferred_lft 1093sec
inet6 fe80::c8da:2d7b:8a00:668a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
Until now we have looked at how we can use the default command module. If we want to use a different module we need to pass the -m module name. For using the shell module we need to pass the module name ‘ansible.builtin.shell’. Lets see some of the examples below.
Step10: Run the shell module to retrieve the hostname of the node
Please note we need to make sure on the shell quoting rules so the local shell retains the variables and passes it to Ansible. For example, using double rather than single quotes in the above example would evaluate the variable on the box you were on.
ansible stack -m shell -a 'echo $HOSTNAME'
Output:
192.168.47.130 | CHANGED | rc=0
ansinode.stack.com
Step11: Copy files using the copy module
Here, lets create and txt file and use the copy module to copy the file from controller node to the remote node destination location.
ansible stack -m copy -a 'src=/tmp/helloansible.txt dest=/tmp/helloansible.txt'
Output:
192.168.47.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"checksum": "97b63eb592e525b043cf4a8d50fa88ad5fd1f031",
"dest": "/tmp/helloansible.txt",
"gid": 1000,
"group": "admin",
"md5sum": "a26463d9ebdd339c8ece493267ae5ee5",
"mode": "0664",
"owner": "admin",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 14,
"src": "/home/admin/.ansible/tmp/ansible-tmp-1617016144.584841-1823-233756633783429/source",
"state": "file",
"uid": 1000
Validate on ansinode server.
ls -ltr /tmp/helloansible.txt
Output:
-rw-rw-r--. 1 admin admin 14 Mar 29 16:39 /tmp/helloansible.txt
Step12: Changing file ownership and permissions using the file module and Managing files
We can also change the ownership and permissions of the files using the file module as shown below. First lets try to change the permissions on the file.
ansible stack -m file -a "dest=/tmp/helloansible.txt mode=600"
Output:
192.168.47.130 | CHANGED
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 1000,
"group": "admin",
"mode": "0600",
"owner": "admin",
"path": "/tmp/helloansible.txt",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 14,
"state": "file",
"uid": 1000
Validate on ansinode server.
Output:
-rw-------. 1 admin admin 14 Mar 29 16:39 /tmp/helloansible.txt
Now lets try to change ownership of the file to root:root and see what happens.
ansible stack -m file -a "dest=/tmp/helloansible.txt owner=root group=root"
Output:
192.168.47.130 | FAILED! {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"gid": 1000,
"group": "admin",
"mode": "0600",
"msg": "chown failed: [Errno 1] Operation not permitted: b'/tmp/helloansible.txt'",
"owner": "admin",
"path": "/tmp/helloansible.txt",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 14,
"state": "file",
"uid": 1000
}
As you can see the user admin does not have the privilege to change the ownership of the file. Lets try to elevate the privilege to root user to change the ownership.
ansible stack -m file -a "dest=/tmp/helloansible.txt owner=root group=root" --become --ask-become-pass
Output:
192.168.47.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0600",
"owner": "root",
"path": "/tmp/helloansible.txt",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 14,
"state": "file",
"uid": 0
}
Validate on ansinode server.
Output:
-rw-------. 1 root root 14 Mar 29 16:39 /tmp/helloansible.txt
We can also manage the directories on the remote node as shown below.
ansible stack -m file -a "dest=/tmp/stack state=directory"
Validate on ansinode server its presence.
ls -ltr /tmp/stack/
ansible stack -m file -a "dest=/tmp/stack state=absent"
Validate on ansinode server its absense.
ls -ltr /tmp/stack/
Output:
ls: cannot access '/tmp/stack/': No such file or directory
Step13: Managing the packages on the remote node using yum module
Here we can install, update, remove the packages on the remote machine using the yum module as shown.
We can also manage users and groups using the ‘user’ module and services using the service module. Also one of the most important thing is about capturing the information about the remote node using the setup module as shown below.
ansible stack -m yum -a 'name=sscg state=present' --become --ask-become-pass
Output:
192.168.47.130 | CHANGED {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Installed: sscg-2.6.2-1.fc32.x86_64"
]
}
ansible stack -m yum -a 'name=sscg state=latest' --become --ask-become-pass
Output:
192.168.47.130 | SUCCESS {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": []
}
ansible stack -m yum -a 'name=sscg state=absent' --become --ask-become-pass
Output:
192.168.47.130 | CHANGED {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Removed: sscg-2.6.2-1.fc32.x86_64"
]
}
We can also manage users and groups using the ‘user’ module and services using the service module. Also one of the most important thing is about capturing the information about the remote node using the setup module as shown below.
ansible stack -m setup
Output:
192.168.47.130 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.47.130"
],
"ansible_all_ipv6_addresses": [
"fe80::c8da:2d7b:8a00:668a"
],
"ansible_apparmor": {
"status": "disabled"
},
...
Hope you enjoyed reading this article. Thank you..
Leave a Reply
You must be logged in to post a comment.