Search code examples
ddev

How can I use bash constructs like 'cd' or '&&' or '>' redirection with ddev exec?


I'm trying to do some complex things with bash in the container using ddev exec and can't seem to get it to work. For example, ddev exec cd /var/tmp results in a big error message

Failed to execute command [cd /var/tmp]: Failed to run docker-compose [-f /Users/rfay/workspace/d8git/.ddev/docker-compose.yaml exec -T web cd /var/tmp], err='exit status 126', stdout='OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"cd\": executable file not found in $PATH": unknown

And trying to use "||" and "&&" or shell redirection with ">" doesn't work either.


Solution

  • Edit 2019-05-14: As of today's ddev release, v1.8.0, the answer below is obsolete, as ddev exec and exec hooks are executed in bash context. So ddev exec "ls | grep php" now works, ddev exec "mysql db <somefile.sql" works, as does an exec hook like exec: mysql <somefile.sql

    ddev exec (and the "exec" hook in config.yaml) both execute actual comamnds, and not in the context of the shell. "cd" is not a Linux command, but rather a shell built-in. And '&&', '||', and '>' or '>>' are also shell constructs. So we have to do a bit of workaround to make them work.

    But we can use bash explicitly to get these things to work:

    ddev exec bash -c "cd /var/tmp && ls > /tmp/junk.txt"
    

    To do the same thing in a post-start hook in config.yaml:

       hooks:
         post-start:
           - exec: bash -c "cd /var/tmp && ls > /tmp/junk.txt"
    

    Note that environment variables will not persist between exec statements, because they're in different shells, so it's best if you need to keep context to do it in one-liners.

    Note also that if you want to redirect stdout/stderr you can redirect either within the container (as above) or to the host (redirecting the ddev exec output) like this:

    ddev exec bash -c "cd /var/tmp && ls" >/tmp/junk.txt
    

    It's possible that ddev exec might in the future execute commands in the context of bash to make this more transparent.