Using "shell" with a switch

Hey, all.

I need to run a script residing on the remote machine with a switch, as in “/scripts/myscript -f” (it must be executed by root). I’m using the shell module, but can find no way to add the switch without the play failing. Help would be appreciated.

Dimitri

Hey Dimitri,

Why don't you send us your code and the output you are receiving?

Piotr

OK:


  • hosts: all
    gather_facts: false
    become: yes

become_user: root

become_method: su

tasks:

  • shell: “su - root”
    args:
    warn: false
  • shell: ‘/scripts/dnscopy.pl -f’
    register: (result)
  • debug:
    var: (result)
    verbosity: 2

*become_user and become_method are commented out in favor of shell: “su - root” because using the former causes a timeout error, But that’s another issue.

Output of play:

TASK [command] ***************************************************************************************************************************************************************************
fatal: [admin1]: FAILED! => {“changed”: true, “cmd”: “/scripts/dnscopy.pl -f”, “delta”: “0:00:01.425695”, “end”: “2018-12-03 17:13:56.113927”, “failed”: true, “rc”: 2, “start”: “2018-12-03 17:13:54.688232”, “stderr”: “Can’t exec "rndc": No such file or directory at /scripts/dnscopy.pl line 296.\nrndc -s dns1 reload failed: No such file or directory at /scripts/dnscopy.pl line 296.”, “stderr_lines”: [“Can’t exec "rndc": No such file or directory at /scripts/dnscopy.pl line 296.”, “rndc -s dns1 reload failed: No such file or directory at /scripts/dnscopy.pl line 296.”], “stdout”: “”, “stdout_lines”: }

without the -f switch, the play completes successfully.

Dimitri,

    - shell: "su - root"
      args:
        warn: false
    - shell: '/scripts/dnscopy.pl -f'
      register: (result)

You are running 2 separate shells. First shell runs su - root then exits -
this is not doining anything. Then secon task runs in a new shell, you are
not leveraging the previous "su - root". You are using become: yes, and
that should be sufficient to elevate task's rights, so the second task
should work anyway. Try this:
Remove
- shell: "su - root" task
replace it with:
- shell: "whoami"
   register: who
- debug: var=who
to check under which user is your script executing. If it's not 'root'
then you messed up, if it is 'root' but your script still fails, you have a
problem with your script.

Piotr

Thank you, Piotr. All good, now. You’re right, and this is a mistake I shouldn’t have made, given my long history with Ansible. But, hey, never too late to learn. Thanks, again.

Piotr,

Before I consider this solved, let me push the envelope a bit, and ask about the switch. If I run the play like this:

Shell: /scripts/myscript

it works.

If I run it like this:

Shell: /scripts/myscript -f

it fails with:

fatal: [admin1]: FAILED! => {“changed”: true, “cmd”: “/scripts/dnscopy.pl -f”, “delta”: “0:00:02.025735”, “end”: “2018-12-04 09:34:11.123312”, “failed”: true, “rc”: 2, “start”: “2018-12-04 09:34:09.097577”, “stderr”: “Can’t exec "rndc": No such file or directory at /scripts/dnscopy.pl line 296.\nrndc -s dns1 reload failed: No such file or directory at /scripts/dnscopy.pl line 296.”, “stderr_lines”: [“Can’t exec "rndc": No such file or directory at /scripts/dnscopy.pl line 296.”, “rndc -s dns1 reload failed: No such file or directory at /scripts/dnscopy.pl line 296.”], “stdout”: “”, “stdout_lines”: }

Your continued help (or anybody else’s) would be appreciated.

Dimitri

You script does something else with -f than without.
As the error message say it can't find rndc, so I guess it's a missing path issue.

Thanks, Kai.

Now, I’m completely turned around.

In order for /scripts/dnscopy.pl -f to work in the remote host itself, I must su - root first. I thought that become: yes took care of that. Here’s the playbook as it stands (and fails) now:

Become uses sudo by default unless you set become_method: su

Default I think it only will do "su root -c /scripts/dnscopy.pl -f" so if you need the - aka --login option you might need become_flags: '-' as well

Sorry, Kai, I’m not understanding what the playbook should look like. I’m a bit slow on the uptake.

- hosts: all
  gather_facts: false
  become: yes
  become_method: su
  become_flags: '-'

  tasks:
    - shell: /scripts/dnscopy.pl -f
      register: script_output
    - debug:
        var: script_output.stdout_lines

I thought that’s what I should do. I made those changes, but then the playbook is stuck/runs without completion (until it ultimately times out, I’m guessing).

Piotr

Piotr,

After putting in the directives you mentioned, if I leave become_method: su and become_flags: ‘-’ in the playbook, then the playbook is stuck/runs without completion. If I take those out, leaving only become: yes, then I get the following output:

ok: [admin1] => {
“who”: {
“changed”: true,
“cmd”: “whoami”,
“delta”: “0:00:00.006895”,
“end”: “2018-12-04 13:32:06.805245”,
“rc”: 0,
“start”: “2018-12-04 13:32:06.798350”,
“stderr”: “”,
“stderr_lines”: ,
“stdout”: “root”,
“stdout_lines”: [
“root”
]
}
}

If I run the script on the remote host without su - root, I get:

Can’t exec “rndc”: No such file or directory at ./dnscopy.pl line 296.
rndc -s dns1 reload failed: No such file or directory at ./dnscopy.pl line 296.

If I run the script on the remote host with su - root, I get:

server reload successful

Piotr

Piotr,

The thing of it is, the script (which I didn’t write) runs the rndc (BIND Remote Name Daemon Control - we use it to reload zone files) command on our dns servers (which it locates), not on the host in which the script is located. Thus, the failure. Here’s a snippet from the script:

rndc -s dns1 reload

@args = (“rndc”, “-s”, “dns1”, “reload”);
system(@args) == 0
or die “rndc -s dns1 reload failed: $!”;

Changes to the script are not an option.

That said, is what I’m trying to do not doable?

Dimitri

Dimitri
Your script is depending on rndc residing in the host's $PATH. It might
happen, that the root's profile is being set differently when you become
root in Ansible playbook, than the situation when are switching to root in
a regular way in SSH or terminal. This is why I asked you for more
information in my previous post.
A possible workaround would be to forcibly set PATH env variable when
calling dnscopy.pl. but I can't give you a ready recipe because I don't
have enough informaton about your system

Piotr

Piotr,

Fair enough. And, I do appreciate you sticking with this.

Output of “echo $PATH”:

/usr/kerberos/sbin:/usr/kerberos/bin:/usr/bin:/bin

Output of “which rndc”:

/usr/bin/which: no rndc in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/bin:/bin) ← not a surprise; BIND isn’t installed on this machine

Output after adding - shell: “‘echo $PATH’”, etc. to playbook:

ok: [admin1] => {
“path”: {
“changed”: true,
“cmd”: “echo $PATH”,
“delta”: “0:00:00.006128”,
“end”: “2018-12-04 14:36:50.766764”,
“rc”: 0,
“start”: “2018-12-04 14:36:50.760636”,
“stderr”: “”,
“stderr_lines”: ,
“stdout”: “/usr/bin:/bin”,
“stdout_lines”: [
“/usr/bin:/bin”
]
}
}

Remote machine OS os CentOS 5.11 ← yes, I know

/usr/bin/which: no rndc in (/usr/kerberos/sbin:/usr/kerberos/bin:/usr/bin:/bin) ← not a surprise; BIND isn’t installed on this machine

So, do you already know what the problem is? Are you executing rndc on remote host but you dont have BIND installed on it?

Hi,

I am trying to setup communication between ansible and a windows server which is hosted in virtual machine manager. Do any one know about it.

I am getting error like
Bad HTTP response from server . Code 404

Thanks in advance