`multipass exec` and shells

See also: exec


How exec parses commands

When one calls multipass exec from a shell, the whole command is first parsed by the shell one is in. The result of that parsing is what the multipass client gets in its argv.

For example, when multipass exec primary -- ls ~ is entered on a Linux shell, the tilde is translated to the calling user’s local home before the command is passed to multipass. But that is not the case on a Windows PowerShell, because “~” does not have the same meaning there.

Multipass then executes the command in the given instance as if there was no further shell in the middle (I say “as if” because the reality is a little more complicated). This is slightly different from what one would get with SSH:

$ multipass exec mp-builder -- python3 -c 'import sys; print(sys.argv)' foo bar
['-c', 'foo', 'bar']

How SSH parses commands

With SSH, the whole command would need to be quoted.

$ ssh -i /var/root/Library/Application\ Support/multipassd/ssh-keys/id_rsa ubuntu@ python -c 'import sys; print(sys.argv)' foo bar
bash: -c: line 1: syntax error near unexpected token `sys.argv'
bash: -c: line 1: `python -c import sys; print(sys.argv) foo bar'

Using a shell to parse commands

To overcome the above problem with multipass exec, one can still have another shell parse the command in the instance with multipass exec, it just needs to be called explicitly:

$ multipass exec calm-woodcock -- sh -c 'ls -a ~'
.  ..  .bash_logout  .bashrc  .cache  .profile  .ssh

This behaves the same regardless of the host platform. Without sh -c, it also fails on all platforms (although possibly in different ways, depending on whether or not the nested command is quoted). It makes for a more consistent cross-platform experience.

Last updated 1 year, 3 months ago.