Running script with arguments through ansible - ansible

[Ansible version == 2.1.0]
In order to run a script which is present locally on the target server, we can use Ansible's "command" module. Following can be done easily:
- name: Executing getpkgs.sh to download packages.
command: sh "/path/to /dir/scriptName.sh" arg1 arg2 arg3 arg4
I have my script names and the arguments stored in ansible variables. For example, the following variable contains all the script names and the arguments to be passed to those scripts:
scripts_to_execute:
- { filename: "/path/to/file/file1.sh", args: "arg11 arg12 arg13"}
- { filename: "/path/to/file/file2.sh", args: "arg21 arg22"}
- { filename: "/path/to/file/file3.sh", args: "arg31 arg32 arg33 arg34"}
And i want all these files which are already present on the target server, to be executed using with_items. Trying to achieve something like the following:
- name: Executing all files.
command: sh "{{item.filename}}" "{{item.args}}"
with_items: scripts_to_execute
I am trying to pass the script name followed by the string containing all arguments that are to be passed into the script. But it is considering that string of arguments as a single argument.

But it is considering that string of arguments as a single argument.
I think that makes sense since you pass the args in quotes. Did you try without quotes?
- name: Executing all files.
command: sh "{{item.filename}}" {{item.args}}
with_items: scripts_to_execute

Related

Expand complex ansible variable

I have distinct ansible variables which are combined in a single command. More precisely, the system defines a variable with default value:
# This exists in an ansible variable definition file
instrumentor = ''
At some the python script that "creates" the ansible commands specifies the extra arguments to override the default values. I'm jumping through some hoops (using \" and \') because the desired value contain spaces:
# This is a line from python script
instrumentation_specs =
'-e \'instrumentor=\"/software/cuda-memcheck --tool racecheck --log-file /tmp/memlog\"\''
On the ansible side then the command is structured as
;; This exists in a jinja template (.j2 extension)
;; command is what the start.yml script will be running
command="{{ instrumentor }}" my_program
Unfortunately I cannot get this to work. The command is reported to expand to something that contains extra ' and ":
start.yml (...) -e 'instrumentor="/software/cuda-memcheck --tool racecheck --log-file /tmp/memlog"' (...)
The weird thing is that
if I create another variable before command that only contains instrumentor, it is reported to have the exact value that I need
instr_tmp = "{{ instrumentor }}"
command = "{{ instr_tmp }}" my_program
i.e. the extra ' and " don't appear in instr_tmp but do appear in command
If I ommit the \" and \' on the python side (when creating the string that is used to provide the extra arguments) everything that's after a space gets omitted.
Anyone knows how to specify such a variable override, i.e. how the string should look like when I specify a variable that contains multiple space separated strings (instrumentor), but that variable is supposed to be plugged into another ansible variable (command).

What is the purpose of ">" in "shell: >" within an Ansible task?

What function does the ">" character serve, in a simple Ansible task that executes a shell command? For the life of me I can't find documentation or mention of this! Here is the template for the task:
- name: <task_name>
shell: >
<command>
Thank you.
The > is a mark for yaml. It means that the following lines will be compressed into a single string with leading indentation compressed to a single space. There are some technical details regarding leading indentation that will modify how the final string is generated, but to the yaml parser the following are equivalent:
- name: task_name
shell: >
this is some
arbitrary string which may
be a shell command
- name: task2_name
shell: this is some arbitrary string which may be a shell command

How to supply both named and free_form arguments to ansible ad-hoc?

I ran across one of Ansible's modules that take free_form arguments along with named arguments - win_command. A specific example is given, where a powershell script is provided on stdin:
- name: Run an executable and send data to the stdin for the executable
win_command: powershell.exe -
args:
stdin: Write-Host test
I want to use this as a one-off task, so I want to use ad-hoc execution in the style of
ansible <host> -m <module> -a <args...>
Unfortunately, I see no info in the documentation on how to deal with a module that requires specifying both free_form and named arguments. Does anyone know?
Putting the named arguments after the free_form argument puts everything in the free_form argument, resulting in powershell complaining about extraneous arguments
... -m win_command -a 'powershell - stdin=C:\some\script.ps1 -arg1 value_1 -arg2 value_2'
PS: I'm aware I could probably stuff both the script path and arguments in the free_form argument, but I am more interested in learning whether this is possible with ad-hoc, as the docs don't say either way.
I can't test the win_command module directly, but with the command module, which is syntactically very similar, you can reproduce this:
- command: some_command
args:
chdir: /tmp
creates: flagfile
Like this:
ansible -m command -a 'chdir=/tmp creates=flagfile some_command'
Update
Upon investigation...the problem you've encountered with stdin isn't a quoting issue;
it's that when using the k1=v1 k2=v2 somecommand format of passing parameters to e.g. the command module, Ansible only handles specific keys. In lib/ansible/parsing/splitter.py we see:
if check_raw and k not in ('creates', 'removes', 'chdir', 'executable', 'warn'):
raw_params.append(orig_x)
else:
options[k.strip()] = unquote(v.strip())
That is, it only recognizes creates, removes, chdir, executable, and warn as module arguments. I would argue that this is a bug in Ansible. Adding support for the stdin argument is trivial, of course:
if check_raw and k not in ('stdin', 'creates', 'removes', 'chdir', 'executable', 'warn'):
With this change, we can include stdin with spaces as expected:
$ ansible localhost -m command -a 'chdir=/tmp stdin="Hello world" sed s/Hello/Goodbye/'
[WARNING]: Unable to parse /home/lars/.ansible_hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
localhost | CHANGED | rc=0 >>
Goodbye world

How to use wildcard with variable [duplicate]

This question already has answers here:
Ansible Command module says that '|' is illegal character
(2 answers)
Closed 5 years ago.
I want to list the files as per the host name.But problem is i not able to use the wildcard with variable properly.Can someone suggest me on this.
---
- hosts: local
become_user: yes
vars:
filename: /root/stuff
tasks:
- name: list files
action: command ls -lrt {{ filename }}/'*{{ansible_hostname}}'
register: listfiles
- debug: var=listfiles
If your question is why * doesn't expand?, then:
command module:
The command module takes the command name followed by a list of space-delimited arguments. The given command will be executed on all selected nodes. It will not be processed through the shell, so variables like $HOME and operations like "<", ">", "|", and "&" will not work
shell module:
The shell module takes the command name followed by a list of space-delimited arguments. It is almost exactly like the command module but runs the command through a shell (/bin/sh) on the remote node.
So if you need any shell tricks, like wildcard expansion or access to environment variables, use shell module.

Ansible variable length command line options

I'm trying to create a directive using shell or command to execute something that could have any number of command line arguments.
So something like
- Name: Runs MediaWiki command line setup.
command: "php /opt/wiki/maintanance/install.php {{ arguments }}"
I'm looking for something like a [item for "%s=%s % (key, value) in arguments"]
Looking at ansible variables, everything I see there wants to loop each command on any of the datastruture.
Does anyone know what is the best way to join an arbitrary list of arguments for a command and the best way to structure that in a variables file?
If arguments is a list you can use the join filter.
- Name: Runs MediaWiki command line setup.
command: "php /opt/wiki/maintanance/install.php {{ arguments | join }}"
If arguments is a dict you might be able to do something like this:
- Name: Runs MediaWiki command line setup.
command: "php /opt/wiki/maintanance/install.php {{ arguments | urlencode | replace('&', ' ') }}"

Resources