Execute a bash script with arguments in Ansible - bash

I am new to Ansible. I have a bash script which has three arguments to be passed. I have to run this bash script on the remote server from Ansible.
Basically, I want to declare the hostname, duration and the comment fields as arguments while executing the Ansible command. I don't want to edit the file, as I am doing it from a Slack channel.
- hosts: nagiosserver
tasks:
- name: Executing a script
command: sh /home/aravind/downtime.sh {hostname} {duration} {comments}

If you're executing ansible via ansible-playbook myplay.yml, you can pass additional variables via -e varname=varvalue. A lazy fix would be to run with
ansible-playbook myplay.yml -e my_hostname=foo -e my_duration=bar -e my_comments=foobar
But you should consider that the hostname is already defined in your inventory or gathered facts.
So you could update your playbook to use these additional variables using
- hosts: nagiosserver
tasks:
- name: Executing a script
- command: "sh /home/aravind/downtime.sh {{my_hostname}} {{my_duration}} {{my_comments}}"

Related

Ansible playbook for startup script with arguments

Is it possible in Ansible to write the startup script with input of arguments?
For example, in Unix, when we run it we can do:
/etc/init.d/SCRIPT start|stop|restart
Is it possible to do it in Ansible so it will read the input of start|stop|restart?
You can pass variables into your playbook at runtime using the -e argument. For example:
ansible-playbook playbook.yml -e mode=start
Given the above command line, inside the playbook, you can examine the mode variable:
- hosts: localhost
tasks:
- name: start something
command: echo do you want to be starting something
when: "mode|default('') == 'start'"
You can use as many -e arguments as you want, and you can include variables from a file rather than including them on the command line. E.g., if you have a file vars.yml, you could run:
ansible-playbook playbook.yml -e #vars.yml
So from one perspective, you would need to have three different tasks, each with a different when statement to handle the three start/stop/restart conditions.
But depending on what you're trying to do, there may be a simpler solution. If you're just trying to call the init script from a task, you could instead do this:
- hosts: localhost
tasks:
- name: start something
command: /etc/init.d/SCRIPT {{ mode }}

How to run vendor provided script from playbook to enable csh environment variables

I need to execute a vendor provided csh script to create a veritable plethora of environment variables in order to run application from playbook.
I have built an ad-hoc script that uses screen to inject the commands I need to run inside of a csh session. This succesfully allows me to run the application; but again, from an ad-hoc script and not a playbook.
### start the fsc
# launch a screen session with csh
ansible 10.1.1.103 -m shell -a "su - testdev -c 'screen -dmS testdev_fsc csh'" -b
# run vendor provided env variables script
ansible 10.1.1.103 -m shell -a "su - testdev -c 'screen -S testdev_fsc -X stuff '/export/home/testdev/tcdata/tc_cshvars^M''" -b
# execute the application
ansible 10.1.1.103 -m shell -a "su - testdev -c 'screen -S testdev_fsc -X stuff '/export/home/testdev/ccbin/fsc.sh^M''" -b
In the end, I'd like to be able to create a playbook snippet that allows the above to run/execute.
So basically you want to become user testdev and run two commands in a row in the same csh session. The following fictive playbook should do the job.
---
# Playbook example
- name: Play to run my script
hosts: my_inventory_group
remote_user: my_remote_connection_user
tasks
- name: run my script
become: true
become_user: testdev
shell: |-
./tcdata/tc_cshvars
./ccbin/fsc.sh
args:
chdir: /export/home/testdev/
executable: /bin/csh
|- is the yaml litteral block marker with trailing space control. All the following block is interpreted as a string with new lines preserved. Passed to the shell module, each line will be executed (as if entered in your own shell). Double check the path for your csh executable. You must provide an absolute path.
If you have several tasks in your playbook and need to run all or them as testdev, you can move become and become_user to play level rather that task level.

File created by ansible script module not present after running against remote node

I'm setting up some server in AWS, and want to use Ansible to do some shell in remote nodes. I write playbook as follow
- hosts: remote-nodes
tasks:
- name: Execute script
script: /home/ubuntu/FastBFT_ethereum/experiment/a.sh
remote nodes a.sh as follow
#!/usr/bin/env bash
echo "test">> test.txt
python writejson.py
But when I check the test.text, I find it doesn't work in remote nodes.help me please.
Assuming that you want test.txt to be created in the experiment directory, this should be changed to something like:
- hosts: remote-nodes
tasks:
- name: Execute script
script: /home/ubuntu/FastBFT_ethereum/experiment/a.sh
args:
chdir: /home/ubuntu/FastBFT_ethereum/experiment

Execute fabric commands from Karaf terminal using ansible

In ansible how can we execute fabric commands in Karaf terminal.
Actually in ansible we will execute shell commands, but there are some commands I need to execute with Karaf terminal. Is there any possibility to do.
in generic, how to open other terminal other than shell using ansible playbook
Karaf exposes sshd server, you can use it to call commands from Ansible.
inventory:
test ansible_host=192.168.0.15
test-karaf ansible_host=127.0.0.1 ansible_port=8101 ansible_user=karafuser ansible_password=karafpassword ansible_ssh_common_args="-o ProxyCommand='ssh 192.168.0.15 -W %h:%p'"
playbook:
- hosts: test
gather_facts: no
tasks:
- shell: ps aux | grep [b]in/karaf
- raw: system:version
delegate_to: test-karaf
This will grep for karaf process on test host and execute system:version command inside karaf shell on that host.

How to execute a shell script on a remote server using Ansible?

I am planning to execute a shell script on a remote server using Ansible playbook.
blank test.sh file:
touch test.sh
Playbook:
---
- name: Transfer and execute a script.
hosts: server
user: test_user
sudo: yes
tasks:
- name: Transfer the script
copy: src=test.sh dest=/home/test_user mode=0777
- name: Execute the script
local_action: command sudo sh /home/test_user/test.sh
When I run the playbook, the transfer successfully occurs but the script is not executed.
you can use script module
Example
- name: Transfer and execute a script.
hosts: all
tasks:
- name: Copy and Execute the script
script: /home/user/userScript.sh
local_action runs the command on the local server, not on the servers you specify in hosts parameter.
Change your "Execute the script" task to
- name: Execute the script
command: sh /home/test_user/test.sh
and it should do it.
You don't need to repeat sudo in the command line because you have defined it already in the playbook.
According to Ansible Intro to Playbooks user parameter was renamed to remote_user in Ansible 1.4 so you should change it, too
remote_user: test_user
So, the playbook will become:
---
- name: Transfer and execute a script.
hosts: server
remote_user: test_user
sudo: yes
tasks:
- name: Transfer the script
copy: src=test.sh dest=/home/test_user mode=0777
- name: Execute the script
command: sh /home/test_user/test.sh
It's better to use script module for that:
http://docs.ansible.com/script_module.html
For someone wants an ad-hoc command
ansible group_or_hostname -m script -a "/home/user/userScript.sh"
or use relative path
ansible group_or_hostname -m script -a "userScript.sh"
Contrary to all the other answers and comments, there are some downsides to using the script module. Especially when you are running it on a remote(not localhost) host. Here is a snippet from the official ansible documentation:
It is usually preferable to write Ansible modules rather than pushing
scripts. Convert your script to an Ansible module for bonus points!
The ssh connection plugin will force pseudo-tty allocation via -tt
when scripts are executed. Pseudo-ttys do not have a stderr channel
and all stderr is sent to stdout. If you depend on separated stdout
and stderr result keys, please switch to a copy+command set of tasks
instead of using script.
If the path to the local script contains spaces, it needs to be
quoted.
This module is also supported for Windows targets.
For example, run this script using script module for any host other than localhost and notice the stdout and stderr of the script.
#!/bin/bash
echo "Hello from the script"
nonoexistingcommand
echo "hello again"
You will get something like the below; notice the stdout has all the stderr merged.(ideally line 6: nonoexistingcommand: command not found should be in stderr) So, if you are searching for some substring in stdout in the script output. you may get incorrect results.:
ok: [192.168.122.83] => {
"script_out": {
"changed": true,
"failed": false,
"rc": 0,
"stderr": "Shared connection to 192.168.122.83 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.122.83 closed."
],
"stdout": "Hello from the script\r\n/home/ps/.ansible/tmp/ansible-tmp-1660578527.4335434-35162-230921807808160/my_script.sh: line 6: nonoexistingcommand: command not found\r\nhello again\r\n",
"stdout_lines": [
"Hello from the script",
"/home/ps/.ansible/tmp/ansible-tmp-1660578527.4335434-35162-230921807808160/my_script.sh: line 6: nonoexistingcommand: command not found",
"hello again"
]
}
}
The documentation is not encouraging users to use the script module; consider converting your script into an ansible module; here is a simple post by me that explains how to convert your script into an ansible module.
You can use template module to copy if script exists on local machine to remote machine and execute it.
- name: Copy script from local to remote machine
hosts: remote_machine
tasks:
- name: Copy script to remote_machine
template: src=script.sh.2 dest=<remote_machine path>/script.sh mode=755
- name: Execute script on remote_machine
script: sh <remote_machine path>/script.sh
Since nothing is defined about "the script", means complexity, content, runtime, runtime environment, size, tasks to perform, etc. are unknown, it might be possible to use an unrecommended approach like in "How to copy content provided in command prompt with special chars in a file using Ansible?"
---
- hosts: test
become: false
gather_facts: false
tasks:
- name: Exec sh script on Remote Node
shell:
cmd: |
date
ps -ef | grep ssh
echo "That's all folks"
register: result
- name: Show result
debug:
msg: "{{ result.stdout }}"
which is a multi-line shell command only (annot.: ... just inline code) and resulting into an output of
TASK [Show result] ****************************************************
ok: [test.example.com] =>
msg: |-
Sat Sep 3 21:00:00 CEST 2022
root 709 1 0 Aug11 ? 00:00:00 /usr/sbin/sshd -D
root 123456 709 14 21:00 ? 00:00:00 sshd: user [priv]
user 123456 123456 1 21:00 ? 00:00:00 sshd: user#pts/0
root 123456 123456 0 21:00 pts/0 00:00:00 grep ssh
That's all folks
One could just add more lines, complexity, necessary output, etc.
Because of script module – Runs a local script on a remote node after transferring it - Notes
It is usually preferable to write Ansible modules rather than pushing scripts.
I also recommend to get familar with writing an own module and as already mentioned in the answer of P....
You can execute local scripts at ansible without having to transfer the file to the remote server, this way:
ansible my_remote_server -m shell -a "`cat /localpath/to/script.sh`"

Resources