Ansible shell one line syntax not working - ansible

is it possible to write the shell command in one line ?
- shell: my command
register: var
run_once: true
this work
- shell: "my command" register=var run_once=true
this does not work

Shell is a one-to-one comparison to running the command yourself. From Ansible documentation:
The shell module takes the command name followed by a list of
space-delimited arguments.
So my_command register=var run_once=true would be correct if my_command runs that way when you run it in your local shell.
While you didn't ask about it, it's worth noting that it looks like you're trying to add parameters to the shell module that don't exist, so the first example you provided would have to use the args parameter:
- name: Execute my command in a remote shell
shell: my_command
args:
register: var
run_once: true
Documented examples of shell are here

Related

ansible script module: what is `cmd` for?

I'm just reading the script module documentation, and I don't understand what the cmd property is good for. The documentation states that script:
The script module takes the script name followed by a list of space-delimited arguments.
Where cmd also takes a script followed by a list of arguments.
Can someone explain the difference?
It is just a formatting option. The following two tasks are functionally identical:
- name: Run a script with arguments (using 'cmd' parameter)
script:
cmd: /some/local/script.sh --some-argument 1234
- name: Run a script with arguments (freeform)
script: /some/local/create_file.sh --some-argument 1234

How can I write a bash command that takes 15 mins to run before another command is executed in Ansible?

I am trying to update the version of some software through Ansible for a server.
- name: upgrade firmware version
shell: bash -x bmc_firmware_update.sh -k -F BMC_0204.00.bin_enc -s 1
this could take about 15 mins to run. I have another command to run after that, i.e
-name: something else
shell: bash -x bmc_firmware_update.sh -k -F BMC_0204.00.bin_enc -s 2.
I came across wait_for: timeout=300 but I want to know if there is a better way to go about making sure that the first one is successfully completed before the second shell command is run. Please advice!
Apparently this has nothing to do with Ansible.
Programs runs in foreground by default.
#sorin this is Ansible related!
#op; You can append to the firmware_update.sh script that when finished, it writes a certain value to specific path. Then let Ansible check that file and if that value is there. If it is, continue, if not, retry.
Another possibility is to write the logic in the bash scripts themselves.

Executing Expect command with ansible is not outputing anything

I can access the remote server without problem and I would like to send bwcli command which is a CLI of Broadworks server. I am using a shell code to send the command.
Normally if i want to enter the cli I type bwcli but it is not recognized when doing it remotely so I am sendig this sudo -u bworks /usr/local/broadworks/bw_base/bin/bwcli
instead like this:
#! /usr/bin/expect
expect ":"
send "sudo -u bworks /usr/local/broadworks/bw_base/bin/bwcli\r"
expect ">"
send "?\r"
expect "AS_CLI>"
My playbook is done like this:
-script: /home/ansible/playbooks/David/get_command.sh >> bwcli_login.log
When the playbook is ran it shows OK=1 changed=1 unreachable=0 failed=0.
So I am assuming that it works,but when I go to open "bwcli_login.log" I find it empty.
This is only my first step in the code I would like when I enter the CLI the I send some other commands to retrieve some information for the server. And it is annoying that I am stuck at the first step :(
I appreciate if somebody can tell me why the file output file is empty? What I am doing wrong?
Is it works when you manually run the script on the remote server without ansible ?
You can execute a script with different user without using sudo su <username> in your script, also check/share the output from ansible with stdout_lines, it will be easier to debug.
script:
#! /usr/bin/expect
expect ":"
send "/usr/local/broadworks/bw_base/bin/bwcli\r"
expect ">"
send "?\r"
expect "AS_CLI>"
ansible:
- name: run script
script: /home/ansible/playbooks/David/get_command.sh
become: yes
become_user: bworks
register: out
- debug: var=out.stdout_lines
Have you tried to use ansible expect_module ?
I am not famialer with BroadWorks at all, but maybe you can try to do something like the below example.
You will need:
The command module takes command to run,
responses - Mapping of expected string/regex and string to respond with. If the response is a list, successive matches return successive responses.
http://docs.ansible.com/ansible/latest/expect_module.html
I am not sure if the below example it is what you need or if it will work, just something to work with.
- name: expect test
expect:
command: /usr/local/broadworks/bw_base/bin/bwcli
response:
'>': "?\r"
You must consider that when in the BroadWorks CLI, the 'cd' command acts similarly to the equivalent shell command to navigate from one CLI context to the other. However, I'm not sure there is a root as in 'send "cd /Monitoring/Report"\r'.
To get back in the root of the CLI, you could use: 'send "qa; cd Monitoring/Report;"\r' instead.
Furthermore to verify that you moved to the right CLI context, you might want to ' expect "Monitoring/Report>"' intead of '>'.
Note that expect could be used to define functions.
I had the same issue. I found that you need to run the bwcli command with the -nobash option.
Playbook:
- name: Play 1
hosts: mediaservers
tasks:
- name: Play - 1 change to bwcli using script
script: /etc/ansible/bwcli.sh
args:
executable: /usr/bin/expect
register: bwcli_output
- debug: var=bwcli_output
Expect Script
#!/usr/bin/expect
# This will set a timeout for each send command sent to remote server
set timeout 20
spawn bash
send "bwcli -nobash\r";
expect "*_CLI*"
send "int;snmp;v3u\r"
expect "*V3Users*"
send "delete bwems\r"
expect "*Warning: The SNMP Agent needs to be restarted*"
send "get\r"
expect "*_CLI*"
send "exit\r"
expect "*Yes*\r"
send "Yes\r"
expect eof

how to invoke a shell script in remote node through ansible and input a series of run time values to that shell script from local node

I have a script called configAdmin.sh in remote node. I need to
invoke that script from local node, later it will open below session
and prompts for input.
some input like connect to domain
ConfigAdmin> -->
How can I achieve this through ansible?
To run a remote script that expects commands from standard input, you can use shell and provide the commands before your script with a pipe:
- shell: echo "some command" | myscript

Redirect command output to file (existing command)

To write the stdout of a command (in this case, echo hi) to a file, you can do:
echo hi > outfile
I would like a command instead of a redirection or pipe so that I do not need to invoke a shell. This is eventually for use with Ansible, which calls python's subprocess.POpen.
I am looking for:
stdout-to-file outfile echo hi
tee makes copying stdout to a file easy enough, but it accepts stdin, not a separate command.
Is there a common, portable command that does this? It's easy enough to write one, of course, but that's not the question. Ultimately, in Ansible, I want to do:
command: to-file /opt/binary_data base64 -d {{ base64_secret }}
Instead of:
shell: base64 -d {{ base64_secret }} > /opt/binary_data
Edit: Looking for a command available on RHEL 7, Fedora 21
What you are actually looking for, is a Ansible Module, which takes two parameters,
The actual command
A file to redirect the output of above command
In this case, you could use shell module instead of command module, which allows such redirections.
e.g.
- shell: /usr/bin/your_command >> output.log
You could check the source and example documentation here.
This is the simplest. And I believe you are aware of this. I am just putting this across for anyone new to shell/command modules reading this thread.
If you don't like to do it that way, you could still write a wrapper module, which accepts the "file name" as an argument and will run as,
- custommodule: output.log /usr/bin/your_command
All you may need to do is fork the repo, look into existing modules, and customize yours accordingly.
Not sure if that is what you want, but in Ansible - Save registered variable to file I have found what I have needed:
- name: "Gather lsof"
command: lsof
register: lsof_command
- name: "Save lsof log"
local_command:
copy content="{{ lsof_command.stdout }}" dest="/root/lsof.log"
Or, in my specific case (might be useful for you as well) playbook was running on system A, but I needed the log from B and having it saved to localhost (because A system is hitting B and I want to log B's state):
- name: "Gather lsof on B"
delegate_to: B
command: lsof
register: lsof_command
run_once: true
- name: "Save lsof log"
local_action:
copy content="{{ lsof_command.stdout }}" dest="/root/lsof.log"
run_once: true
IMO run_once: true is required in my case, as I want the log gathered only once per playbook run (not say 10 times if playbook is running on 10 systems).
Space for improvement would be to save stderr as well or possibly failing "Save lsof log" task when it is not empty.

Resources