ibash
ibash

Reputation: 741

sudo cd into a directory with Fabric

I am new to Fabric and I am trying to cd into a directory I don't have permission to, so I'm using sudo. (The permissions on the directory are drwx------, i.e., 700)

I am using Fabric 0.9.7.

I tried this:

from fabric.api import run, env
from fabric.context_managers import cd

env.hosts = [ '1.2.3.4' ]
env.user = 'username'

def test():
       run('sudo cd /my/dir')
              run('ls')

But this gives me "sorry, you must have a tty to run sudo" which is understandable. I've also tried this:

snip:

def test():
        with cd('/my/dir'):
                run('ls')

But this returns "permission denied", again understandable.

In a nutshell, how do I "sudo cd" within Fabric?

Upvotes: 3

Views: 4320

Answers (3)

mrts
mrts

Reputation: 18973

As others have explained, cd is a shell builtin in Linux, but sudo only works with executables, so sudo cd cannot work.

Therefore even using with c.cd() and sudo() with latest Fabric does not work, this task:

@task
def pwd(c):
    with c.cd('/tmp'):
        c.sudo('pwd')

results in the following error:

sudo: cd: command not found

The arguably unattractive workaround is to launch a new shell with sudo() for the command and manually prefix it with cd:

@task
def pwd(c):
    c.sudo('sh -c "cd /tmp && pwd"')

See this Invoke issue.

Upvotes: 4

Brendan Long
Brendan Long

Reputation: 54272

Is there any reason you're not just using sudo()? It may work around the issue you're having.

If you're using a version of Fabric before 1.0, you'll need to explicitly tell it to create a TTY:

sudo("ls", pty=True)

Otherwise, you may need to edit your sudoers file and remove or comment out this line:

Defaults    requiretty 

Should be:

#Defaults    requiretty

Also, it may be more annoying, but if with cd(...) causes problems, you can always pass the path as an argument to ls:

sudo("ls /my/dir")

Upvotes: 3

Iguananaut
Iguananaut

Reputation: 23346

This is because cd is a shell builtin command and not an actual program that can be run with sudo. You were on the right track with with cd(...):. Try something like:

with cd('/my/dir'):
    sudo('ls')

I think that will work, though admittedly I have not yet tried it myself. That's because the way the cd context manager works is to prepend cd <dirname> && to any command run with run() or sudo().

Upvotes: 1

Related Questions