5

I want to use paramiko to ssh into a bunch a remote nodes and run some command line with root priviledge

I have ssh key in my home directory and so i don't need to input password when I ssh into those remote nodes

but when running the following script:

    def connect(hostname):
                    ssh = paramiko.SSHClient()
                    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())               
                    ssh.connect(hostname, username='niky', pkey=paramiko.RSAKey.from_private_key(open('id_rsa'), 'passwd'), timeout = 240.0)                return ssh          



    def run(hostname):
            ssh = connect(hostname)
            (stdin, stdout, stderr) = ssh.exec_command("sudo ls")
            res = stderr.readlines()
            print hostname+': '+''.join(str(elem) for elem in res)+'\n'

    run(remote.nity.com)

I got the following error:

remote.nity.com: sudo: no tty present and no askpass program specified

if I don't add sudo before ls everything works fine what are potential reasons ? thanks!

1
  • the user who runs the sudo must not have been allowed to run the command(s) you are running, with NOPASSWORD directive in sudoers file
    – MelBurslan
    Apr 10, 2013 at 4:34

3 Answers 3

2

In the stock sudoers configuration, the following line is usually present:

Defaults requiretty

This is both secure and what you need in the majority of the use cases.

In your case, you need to override this default for a specific user, so you would write below:

Defaults:niky !requiretty

Also, you need to define a line allowing niky to call sudo without password:

niky remote.nity.com = (root)NOPASSWD: /bin/ls

This line means that the user niky is allowed to execute /bin/ls as root in remote.nity.com without requiring a password.

Further reference can be found in here.

2

Two things that you'll find useful:

  1. exec_command takes an optional argument of get_pty. You can use it like this:

    (stdin, stdout, stderr) = ssh.exec_command("sudo ls", get_pty = True)
    
  2. Throw the password into stdin, with a line return and flush to make sure it gets delivered. This ensures it receives the password if it asks (you could do something more sophisticated to check if it actually asked or not... simply throwing it in always hasn't caused problems for me, yet.)

    stdin.write('passwd' + '\n')
    stdin.flush()
    

Taken together, those should fix your sudo over paramiko issues.

1

FYI - may help you in your search - note you get the SAME error in plain SSH if you encapsulate one SSH command inside another, ex:

localhost$ ssh [email protected] -C 'sudo su - anotheruser ssh [email protected] /run/this/executable'

(Why not SSH directly to the target box? Well, maybe SSH keys are only setup between host1 and host2, or the network is routed to prohibit host2 access w/o travelling through host1. Maybe you're not allowed to touch sudoers or any other file on host2... common in Production envs.).

In any case, you are able to run non-sudo commands using the above, but prefixing with sudo causes "no tty present".

How do you fix this with bare ssh command? Pass in the -t, ex: localhost$ ssh [email protected] -C 'sudo su - anotheruser ssh -t [email protected] /run/this/executable'

Now the remote sudo runs fine inside SSH, no complaints about tty. The -t allocated it.

So the question is, how does one emulate the "-t" option inside the Paramiko object? There's your answer.

This blog attempts to explain, but perhaps could have spent more time on the 'sudo' example: http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

(Apologies for my point in the right direction instead of a perfect answer... I'm still searching for that info myself actually).

1
  • The blog you linked to shows the guy using sudo without any issue in paramiko. Apr 25, 2016 at 1:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .