Why doesn't Fabric see my .bash_profile?

后端 未结 3 965
离开以前
离开以前 2021-01-04 06:12

In Fabric, when I try to use any alias\' or functions from my .bash_profile file, they are not recognized. For instance my .bash_profile contains <

相关标签:
3条回答
  • 2021-01-04 06:37

    It looks like you're trying to use virtualenvwrapper locally. You'll need to make your local command string look like this:

        local("/bin/bash -l -c 'workon django-canada && python manage.py runserver'")
    

    Here's an example by yours truly that does that for you in a context manager.

    0 讨论(0)
  • 2021-01-04 06:46

    EDIT - As it turns out, this was fixed in Fabric 1.4.4. From the changelog:

    [Feature] #725: Updated local to allow override of which local shell is used. Thanks to Mustafa Khattab.

    So the original question would be fixed like this:

    def test():
        local('c', shell='/bin/bash')
    

    I've left my original answer below, which only relates to Fabric version < 1.4.4.


    Because local doesn't use bash. You can see it clearly in your output

    /bin/sh: c: command not found
    

    See? It's using /bin/sh instead of /bin/bash. This is because Fabric's local command behaves a little differently internally than run. The local command is essentially a wrapper around the subprocess.Popen python class.

    http://docs.python.org/library/subprocess.html#popen-constuctor

    And here's your problem. Popen defaults to /bin/sh. It's possible to specify a different shell if you are calling the Popen constructor yourself, but you're using it through Fabric. And unfortunately for you, Fabric gives you no means to pass in a shell, like /bin/bash.

    Sorry that doesn't offer you a solution, but it should answer your question.

    EDIT

    Here is the code in question, pulled directly from fabric's local function defined in the operations.py file:

    p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream,
        stderr=err_stream)
    (stdout, stderr) = p.communicate()
    

    As you can see, it does NOT pass in anything for the executable keyword. This causes it to use the default, which is /bin/sh. If it used bash, it'd look like this:

    p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream,
        stderr=err_stream, executable="/bin/bash")
    (stdout, stderr) = p.communicate()
    

    But it doesn't. Which is why they say the following in the documentation for local:

    local is simply a convenience wrapper around the use of the builtin Python subprocess module with shell=True activated. If you need to do anything special, consider using the subprocess module directly.

    0 讨论(0)
  • 2021-01-04 07:04

    One workaround is simply to wrap whatever command you have around a bash command:

    @task
    def do_something_local():
        local("/bin/bash -l -c 'run my command'")
    

    If you need to do a lot of these, consider creating a custom context manager.

    0 讨论(0)
提交回复
热议问题