lima
lima copied to clipboard
arguments of shell command doesn't support "raw"
limactl shell command actually take two responsibility:
- : lima act like ssh,
# expected to get home dir in lima guest vm
$ limactl shell default -- echo '$HOME'
/home/robert.linux
Case 1 is right.
- : lima act like command tunnel, in following example, as tunnel to pass arguments to nerdctl.
# expected to get home path in container
$ alias docker='limactl shell default -- nerdctl'
docker run -it --rm alpine:latest sh -x -c 'echo $HOME'
+ echo
Case 2, the behavior of limactl is not expected. Comparing with docker for desktop:
$ /usr/local/bin/docker run -it --rm alpine:latest sh -x -c 'echo $HOME'
+ echo /root
/root
I propose to add --raw flag to make limactl support act like command tunnel, which means what you pass to limactl, what inner command get.
I propose to add
--rawflag to make limactl support act like command tunnel,
Yes, I've struggled with this use case before too!
However, I think I would prefer to use a different command, e.g. limactl run instead of limactl shell --raw to provide the different semantics. Let's wait to hear what @AkihiroSuda says!
I propose to add
--rawflag to make limactl support act like command tunnel,Yes, I've struggled with this use case before too!
However, I think I would prefer to use a different command, e.g.
limactl runinstead oflimactl shell --rawto provide the different semantics. Let's wait to hear what @AkihiroSuda says!
I don't think I can remember the differences between run and shell 😅 , and I'd rather prefer to reserve run for something similar to start.
So limactl shell --raw (or maybe limactl shell --escape, or limactl shell --verbatim) SGTM, but if it has to be a new subcommand (why?) it should be like limactl shell-raw / limactl shell-escape / limactl shell-verbatim.
I think I'm mostly thrown by the name raw, which to me means kind of the opposite of what it does here, namely wrapping each argument in an extra set of quotes before joining all the arguments by a space. "Raw" to me means un-processed, not wrapped/formatted.
A descriptive name (instead of --raw) would be --auto-quoted, but I admit that it is a bit unwieldy, so --quoted seems like a reasonable alternative.
But effectively we want to be able to say: "Run this command on the guest, but do not do any shell processing of the arguments." From this I gather that shell is the wrong verb because our intend is run, without any processing by the shell. So if you insist that the command has to start with shell- then shell-but-no-shell sounds descriptive (not a serious suggestion). 😄
I find run much more intuitive than shell-verbatim or shell --quoted.
Using shell with a qualifier to say we are disabling the shell processing is a description of the implementation. Using run or exec matches the intention of what we expect the command to do. The user doesn't care that it is implemented via ssh internally.
It is the same reasoning why we have limactl copy, with an alias of cp, but not scp because scp is an implementation detail and has nothing to do with what the user wants to do.
As an alternative to run I could also go with exec. It also implies (to me) that the arguments will not be evaluated by a shell before being passed to the process.
So my order of preference would be:
limactl run (best)
limactl exec (also ok)
limactl shell --quoted (grudgingly ok; looks busy)
limactl shell --verbatim (already feels somewhat wrong to me)
Side note about run being a variant of start: I think eventually we should have a complex create verb to create new instances, and use start just as the opposite of stop. But that is a discussion for a different issue (and a different time).
Update I think exec has a stronger association of not evaluating arguments (to me), so I think it is my top choice, followed by run.
If you are confused about the difference between exec and sh, think of the following, and all will be clear: 😄
$ cd /var
# limactl exec
$ (exec 'ls' '*')
ls: *: No such file or directory
# limactl shell
$ (sh '-c' 'ls' '*')
agentx db jabberd mail root select yp
at empty lib msgs rpc spool
audit folders log netboot run tmp
backups install ma networkd rwho vm
exec SGTM, as long as we can have good --help texts to explain the difference
@RobberPhex WDYT?
as long as we can have good
--helptexts to explain the difference
limactl shell runs the command inside a shell on the INSTANCE, so all arguments are first evaluated by the local shell, and then again by the remote shell:
$ limactl shell INSTANCE echo $HOME
/User/username
$ limactl shell INSTANCE echo '$HOME'
/home/username.linux
Use the limactl exec command if you don't want the arguments to be evaluated again inside the INSTANCE:
$ limactl exec INSTANCE echo '$HOME'
$HOME
And correspondingly for limactl exec, which will have its own help, being a separate command.
A note for other people who need to print the value of the $HOME variable inside the VM: wrapping the echo in sh -c gives me the result I want:
limactl shell default echo $HOME # prints '/Users/username'
limactl shell default echo '$HOME' # prints '$HOME'
limactl shell default sh -c 'echo $HOME' # prints /home/username.linux
While wrapping a command in a shell inside the VM is the generic solutions to this problem, in the special case of just querying an environment variable you can use of the printenv command:
limactl shell default printenv HOME
And Lima includes the lima wrapper to run a shell in your default instance, so it can be just
lima printenv HOME
@jandubois thanks, that's very useful! I didn't remember the existence of printenv. :)