How to execute Ad-Hoc commands on remote node using ansible
Test Environment
Ansible Controller
Ansible Node
In this article we will 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.
If you are interested in watching the video, here is the youtube video on the same with the step by step procedure.
Procedure –
Step1: Install Ansible from RPM repository
Lets install ansible on the Ansible controller node
Install Ansible |
---|
[admin@ansicontrol ~]$ sudo dnf install ansible ... Installed: ansible-2.9.18-1.fc32.noarch libsodium-1.0.18-3.fc32.x86_64 python3-babel-2.8.0-3.fc32.noarch python3-bcrypt-3.1.7-4.fc32.x86_64 python3-cffi-1.14.0-1.fc32.x86_64 python3-chardet-3.0.4-15.fc32.noarch python3-cryptography-2.8-3.fc32.x86_64 python3-fluidity-sm-0.2.0-18.fc32.noarch python3-idna-2.8-6.fc32.noarch python3-invoke-1.4.1-1.fc32.noarch python3-jinja2-2.11.3-1.fc32.noarch python3-jmespath-0.9.4-4.fc32.noarch python3-lexicon-1.0.0-10.fc32.noarch python3-markupsafe-1.1.1-5.fc32.x86_64 python3-ntlm-auth-1.1.0-9.fc32.noarch python3-paramiko-2.7.1-2.fc32.noarch python3-ply-3.11-7.fc32.noarch python3-pyasn1-0.4.8-1.fc32.noarch python3-pycparser-2.19-2.fc32.noarch python3-pynacl-1.3.0-6.fc32.x86_64 python3-pysocks-1.7.1-4.fc32.noarch python3-pytz-2020.5-1.fc32.noarch python3-pyyaml-5.4.1-1.fc32.x86_64 python3-requests-2.22.0-8.fc32.noarch python3-requests_ntlm-1.1.0-10.fc32.noarch python3-urllib3-1.25.7-3.fc32.noarch python3-winrm-0.3.0-9.fc32.noarch python3-xmltodict-0.12.0-7.fc32.noarch sshpass-1.06-9.fc32.x86_64 Complete! |
Step2: Validate Ansible Installation
Verify the ansible installation by checking the version information
Validate Ansible version |
---|
[admin@ansicontrol ~]$ ansible --version 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
Lets define the inventory file with the hostame or ip address of the remote which we would like to manage.
Create inventory file |
---|
[admin@ansicontrol ansible]$ cat /etc/ansible/hosts ... |
[stack]
192.168.47.130
Step4: Generate SSH key pairs and copy to remote node
Generate ssh private and publice for user admin.
Generate SSH key-pair |
---|
[admin@ansicontrol ansible]$ ssh-keygen -t rsa -C admin [admin@ansicontrol ansible]$ ls -ltr ~/.ssh/ total 12 -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.
Copy the public key to the remote node |
---|
[admin@ansicontrol ansible]$ ssh-copy-id -i ~/.ssh/id_rsa.pub admin@192.168.47.130 /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.
Verify the remote ssh login |
---|
[admin@ansicontrol ansible]$ ssh admin@192.168.47.130 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 [admin@ansinode ~]$ logout Connection to 192.168.47.130 closed. |
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 thefiles, 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.
Ping remote node |
---|
[admin@ansicontrol ansible]$ ansible stack -m ping 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.
Check remote node hostname and kernel version |
---|
[admin@ansicontrol ansible]$ ansible stack -a "uname -a" 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.
Check remote node free memory |
---|
[admin@ansicontrol ansible]$ ansible stack -a "free -m" 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.
Check remote node IP address |
---|
[admin@ansicontrol ansible]$ ansible stack -a "ip addr" 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.
Check hostname using single quote and double quote to see the difference |
---|
[admin@ansicontrol ansible]$ ansible stack -m shell -a 'echo $HOSTNAME' 192.168.47.130 | CHANGED | rc=0 >> ansinode.stack.com [admin@ansicontrol ansible]$ ansible stack -m shell -a "echo $HOSTNAME" 192.168.47.130 | CHANGED | rc=0 >> ansicontrol.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.
Copy file using the copy module and verify in the remote node |
---|
[admin@ansicontrol ansible]$ cat /tmp/helloansible.txt Hello Ansible [admin@ansicontrol ansible]$ ls -ltr /tmp/helloansible.txt -rw-rw-r--. 1 admin admin 14 Mar 29 16:37 /tmp/helloansible.txt [admin@ansicontrol ansible]$ ansible stack -m copy -a 'src=/tmp/helloansible.txt dest=/tmp/helloansible.txt' 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 [admin@ansinode ~]$ ls -ltr /tmp/helloansible.txt -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.
Change permission of the file on remote node |
---|
[admin@ansicontrol ansible]$ ansible stack -m file -a "dest=/tmp/helloansible.txt mode=600" 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 [admin@ansinode ~]$ ls -ltr /tmp/helloansible.txt -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
Change ownership of the remote node file to root without privilage |
---|
[admin@ansicontrol ansible]$ ansible stack -m file -a "dest=/tmp/helloansible.txt owner=root group=root" 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 privilage to change the ownership of the file. Lets try to elevate the privilage to root user to change the ownership.
Change ownership of the remote node file to root with privilage escalation and validate the remote node file |
---|
[admin@ansicontrol ansible]$ ansible stack -m file -a "dest=/tmp/helloansible.txt owner=root group=root" --become --ask-become-pass BECOME password: 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 } [admin@ansinode ~]$ ls -ltr /tmp/helloansible.txt -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.
Create and remove directory from remote node using the file module and validate on the remote node |
---|
[admin@ansicontrol ansible]$ ansible stack -m file -a "dest=/tmp/stack state=directory" [admin@ansinode ~]$ ls -ltr /tmp/stack/ total 0 [admin@ansicontrol ansible]$ ansible stack -m file -a "dest=/tmp/stack state=absent" [admin@ansinode ~]$ ls -ltr /tmp/stack/ 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.
Managing Packages on the remote node using the yum module |
---|
[admin@ansicontrol ansible]$ ansible stack -m yum -a 'name=sscg state=present' --become --ask-become-pass BECOME password: 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" ] } [admin@ansicontrol ansible]$ ansible stack -m yum -a 'name=sscg state=latest' --become --ask-become-pass BECOME password: 192.168.47.130 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "msg": "Nothing to do", "rc": 0, "results": [] } [admin@ansicontrol ansible]$ ansible stack -m yum -a 'name=sscg state=absent' --become --ask-become-pass BECOME password: 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.
Check remote node facts collected using the setup module |
---|
[admin@ansicontrol ansible]$ ansible stack -m setup 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.