How to use fabric to create a folder/directory on arbitrary host, multiple platforms, Linux and Windows?

StackOverflow https://stackoverflow.com/questions/21154542

  •  28-09-2022
  •  | 
  •  

Pergunta

I am coding a multiple servers maintenance module using python fabric, and I met a problem that I need to create a folder on random server, this can be either a Linux server or Windows, so the commands are different on these machines.

However this is can be easily done using python on local machine, like

if not os.path.exists(MyDir):
        os.makedirs(MyDir)

But how to do the some thing using fabric on arbitrary platform?

I got the idea like this one,

class FabricSupport:
    def __init__(self):
        pass

    def run(self, host = 'localhost', port = '22', command = None):  
        if host != 'localhost':
            env.host_string = "%s:%s" % (host, port)
            with hide('output','running','warnings'):
                return run(command, shell=False)
        else:
            with hide('running'):
                return local(command)

So I wish this class can have a function that to create a folder. Then I found that I'll be having a problem to make it work on different platforms.

    def createdir(self, targetdir, host = 'localhost', port = '22'):
        if host != 'localhost':
            env.host_string = "%s:%s" % (host, port)
            with hide('output','running','warnings'):
                if not exists(targetdir):
                    return run('mkdir %s' % targetdir, shell=False)
        else:
            with hide('running'):
                return local('mkdir %s' % targetdir)

I found fabric.contrib.files.exists can check if a folder exists, but how about creating one ? What if the 'mkdir' doesn't work?

Update Solution:

Thanks to user865368, I got a complete solution here. This may look stupid long, but I don't see any better one.

class FabricRunReturnSimulator:
    def __init__(self):
        self.info = None
    def __str__(self):
        return "%s" % (self.info)
    pass

def createdir(self, targetdir, host = 'localhost', port = '22'):
    """
    Create a input target dir on local or remote.
    targetdir can be a single string or a list (the sequence of the elements must follow the intended path)

    return code 2: makedir runs into trouble, maybe permission problem
    return code 3: target directory exists
    return code 0: runs normal
    """

    if host != 'localhost':
        env.host_string = "%s:%s" % (host, port)
        with hide('output','running','warnings'), settings(warn_only=True, shell=False):
            if not isinstance(targetdir, list):
                return run('''python -c "import os\nif not os.path.exists('%s'):\ntry:\n  os.makedirs('%s')\nexcept:  exit(2)" ''' % (targetdir, targetdir), capture=True)
            else:
                targetdirpass = repr(targetdir)
                return run('''python -c "import os\ntd = os.path.join(*%s)\nif not os.path.exists(td):\ntry:\n  os.makedirs(td)\nexcept:  exit(2)" ''' % (targetdirpass), capture=True)
    else:
        simulatereturn = FabricRunReturnSimulator()
        if not isinstance(targetdir, list):
            if not os.path.exists(targetdir):
                try:
                    os.makedirs('%s' % targetdir)
                    simulatereturn.return_code = 0
                    simulatereturn.failed = False
                    simulatereturn.succeeded = True
                    simulatereturn.info = ''.join((targetdir , " Folder Created."))
                except:
                    simulatereturn.return_code = 2
                    simulatereturn.failed = True
                    simulatereturn.succeeded = False
                    simulatereturn.info = ''.join(("Unable to create folder ",targetdir))
            else:
                simulatereturn.return_code = 3
                simulatereturn.failed = True
                simulatereturn.succeeded = False
                simulatereturn.info = ''.join((targetdir , " already exists."))
        else:
            td = os.path.join(*targetdir)
            if not os.path.exists(td):
                try:
                    os.makedirs('%s' % td)
                    simulatereturn.return_code = 0
                    simulatereturn.failed = False
                    simulatereturn.succeeded = True
                    simulatereturn.info = ''.join((td , " Folder Created."))
                except:
                    simulatereturn.return_code = 2
                    simulatereturn.failed = True
                    simulatereturn.succeeded = False
                    simulatereturn.info = ''.join(("Unable to create folder " , td))
            else:
                simulatereturn.return_code = 3
                simulatereturn.failed = True
                simulatereturn.succeeded = False
                simulatereturn.info = ''.join((td , " already exists."))
        return simulatereturn
Foi útil?

Solução

If you would like to stay within Python you could go with executing

run('''python -c "import os;os.mkdir('some dir')" ''')

This needs you to know the path to the python executeable on every system, which can change.

Else you could do something like:

  1. Connect to host
  2. Find OS with detect_os
  3. Branch depending on OS
  4. Use 'mkdir' or 'md'

In any way you would have to branch / detect the os there is no fully multiplattform approach.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top