0

I need to run a script using Ansible on multiple nodes. I need to provide the script from command line and it will be changing. The script will also have special characters.

I tried to copy the content in a file using --extra-vars. But as there is a single quote ' in the script, the script is failing.

The content of the script:

---
- hosts: all
  become: true

  tasks:

    - name: copy extra variables to a file
      copy:
        content: |
          {{ command }}
        dest: /tmp/commands.sh
      delegate_to: localhost

    - name: copy commands.sh to nodes
      copy:
        src: /tmp/commands.sh
        dest: /tmp/
        mode: 0755

    - name: run the commands in the nodes
      shell: /bin/bash /tmp/commands.sh
      register: command_output

    - name: print output
      debug:
        msg: "{{ command_output.stdout_lines }}" 

Lets say I am giving the command as below

ansible-playbook -i hosts.ini store-in-file-and-run-in-nodes.yaml -e "command='
date
ps -ef | grep httpd
echo "That's all folks"
'
"

Here due to single quote in echo "That's all folks", the command is failing. It works fine if I escape the singe quote. It looks easy to escape a single ' as per this script. But my original script has multiple ' also special chars.

The commands I provide in command line should be stored as it is ...

Please help me to find a solution.

Thanks

U880D
  • 8,601
  • 6
  • 24
  • 40
  • According your description it should be possible to provide the content of `command.sh` upfront and in a file instead of in extra variable and create the file from it. That seems to be an unnecessary tasks and adding complexity instead of reducing it. The `command.sh` can than just copied over and become executed. An other approach might be using the [`script` module – Runs a local script on a remote node after transferring it](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/script_module.html). – U880D Aug 12 '22 at 07:45
  • Thanks for the response. The problem is I need to allow the user to enter the commands in runtime/command prompt. Those sequence of commands need to be stored in a file and then run in the nodes – Krish R Aug 12 '22 at 10:47
  • 1
    So then the user can just creates the file. Another thing you should consider is that you currently (try to) allow users to execute unvalidated code on remote machines. Additionally, your example could be densed down to simply `ansible` ad-hoc commands. Can you therefore provide much more and detailed description about your use case? – U880D Aug 12 '22 at 10:53

1 Answers1

0

According your description it should be possible to provide the content of command.sh upfront and in a file instead of in an extra variable and create the file from it. That seems to be an unnecessary tasks and adding complexity instead of reducing it.

cat > command.sh <<EOF 
date
ps -ef | grep ssh
echo "That's all folks"
EOF

The command.sh can than just copied over and become executed. For this the script module – Runs a local script on a remote node after transferring it.

---
- hosts: test
  become: true
  gather_facts: false

  tasks:

  - name: Exec 'command.sh' on Remote Node
    script: command.sh
    register: result

  - name: Show result
    debug:
      msg: "{{ result.stdout }}"

resulting into an output of

TASK [Exec 'command.sh' on Remote Node] *******************************
changed: [test.example.com]

TASK [Show result] ****************************************************
ok: [test.example.com] =>
  msg: |-
    Fri Aug 12 15:56:37 CEST 2022
    root        709      1  0 Aug11 ?        00:00:00 /usr/sbin/sshd -D
    root     168296    709 24 15:56 ?        00:00:00 sshd: user [priv]
    user     168298 168296  1 15:56 ?        00:00:00 sshd: user@pts/0
    root     168485 168482  0 15:56 pts/0    00:00:00 grep ssh
    That's all folks

Another thing you should consider is that you currently (try to) allow users to execute unvalidated code on remote machines. Additionally and depending on what you try to achieve, your use case can probably become dense down to simple Ansible ad-hoc commands.

ansible test -m shell -a 'date; ps -ef | grep ssh; echo "End of task"; echo " "'

The description

I need to provide the script from command line and it will be changing.

sounds more like an anti-pattern for Ansible. It should be possible to identify common administrative and usual operational tasks before, describe them in a simple playbook and allow users to execute only that. Otherwise you could have a look for parallel or cluster shells.

U880D
  • 8,601
  • 6
  • 24
  • 40
  • Thanks for the detailed update. Storing it as script and running the script from ansible might work for me. I will try and update. – Krish R Aug 16 '22 at 08:54