Python in relocatable guix pack leads to wrong sys.path

  • Open
  • quality assurance status badge
Details
5 participants
  • Konrad Hinsen
  • Ludovic Courtès
  • Maxim Cournoyer
  • Rutherther
  • Rutherther
Owner
unassigned
Submitted by
Rutherther
Severity
normal

Debbugs page

Rutherther wrote 6 months ago
(address . bug-guix@gnu.org)
87ed5j1jzd.fsf@protonmail.com
When I add both python and a python package (seems like any) to a
relocatable guix pack, the resulting python in the merged profile seems
to be broken. Specifically its `sys.path` contains missing paths.

To replicate:
```
mkdir -p /tmp/b && cd /tmp/b
tar xzvf $(guix pack -RR python python-pyflakes -S /profile=)`
```

Then try executing the python from merged profile, and see sys.path output
Toggle snippet (6 lines)
./profile/bin/python3
>>> import sys
>>> print(sys.path)
['', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python310.zip', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/lib-dynload', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/site-packages']

Now if you instead use the realpath of this python
Toggle snippet (6 lines)
$(realpath ./profile/bin/python3)
>>> import sys
>>> print(sys.path)
['', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python310.zip', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/lib-dynload', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/site-packages']

As can be observed, the first instance misses "gnu/store" in the path,
and instead points to a path that does not exist. I have not
investigated, at least not yet, where this discrepancy comes from.
I was not able to replicate this with anything else than relocatable
pack. So my guess would be something strange happens when making
bwrap/fakechroot etc.

Regards,
Rutherther
Rutherther wrote 6 months ago
(address . 73304@debbugs.gnu.org)
87bk0n1jps.fsf@protonmail.com
As a workaround, the profile in gnu/store can be used instead
of the one exposed by -S symlink. Specifically, getting
`realpath ./profile` and using that as the profile instead
of `./profile` directly resolves the issue.
Ludovic Courtès wrote 5 months ago
Re: bug#73304: Python in relocatable guix pack leads to wrong sys.path
(name . Rutherther)(address . rutherther@protonmail.com)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(address . 73304@debbugs.gnu.org)(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
87zfno3l4i.fsf@gnu.org
Hello,

Rutherther <rutherther@protonmail.com> skribis:

Toggle quote (28 lines)
> When I add both python and a python package (seems like any) to a
> relocatable guix pack, the resulting python in the merged profile seems
> to be broken. Specifically its `sys.path` contains missing paths.
>
> To replicate:
> ```
> mkdir -p /tmp/b && cd /tmp/b
> tar xzvf $(guix pack -RR python python-pyflakes -S /profile=)`
> ```
>
> Then try executing the python from merged profile, and see sys.path output
>
> ./profile/bin/python3
>>>> import sys
>>>> print(sys.path)
> ['', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python310.zip', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/lib-dynload', '/tmp/b/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/site-packages']
>
>
> Now if you instead use the realpath of this python
>
> $(realpath ./profile/bin/python3)
>>>> import sys
>>>> print(sys.path)
> ['', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python310.zip', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/lib-dynload', '/tmp/b/gnu/store/pwajwfiygrkmag8fm1wzn3cf362j7sri-python-3.10.7R/lib/python3.10/site-packages']
>
> As can be observed, the first instance misses "gnu/store" in the path,
> and instead points to a path that does not exist.

Commit d5e0180805f52ef38a03ff9d6c11dd6174e3526b fixed a similar issue I

Not sure whether it’s a new problem here. Konrad, Maxim, Josselin,
WDYT? :-)

Thanks,
Ludo’.
Rutherther wrote 5 months ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(address . 73304@debbugs.gnu.org)(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
87ttdv8vf8.fsf@ditigal.xyz
Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (6 lines)
> Commit d5e0180805f52ef38a03ff9d6c11dd6174e3526b fixed a similar issue I
> think, discussed at <https://issues.guix.gnu.org/53258>.
>
> Not sure whether it’s a new problem here. Konrad, Maxim, Josselin,
> WDYT? :-)

Hello Ludovic,

if I understand correctly this commit was merged to master with
the quite-recent core-updates merge? The experiment I did was
after this.

Moreover, I tried with newest master now to make sure,
and still the same behavior.

I will try to investigate this myself after I get some time (which may
be quite a while) if no one else will get to it until that time.

Regards,
Rutherther.

PS: sorry for the e-mail change, I recently set up self-hosted one, so
let's see how well it works with debbugs / your gnu.org address. :)
Konrad Hinsen wrote 5 months ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Rutherther)(address . rutherther@protonmail.com)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
m15xqbqb3w.fsf@fastmail.net
Ludovic Courtès <ludo@gnu.org> writes:

Toggle quote (12 lines)
> Rutherther <rutherther@protonmail.com> skribis:
>
>> When I add both python and a python package (seems like any) to a
>> relocatable guix pack, the resulting python in the merged profile seems
>> to be broken. Specifically its `sys.path` contains missing paths.

> Commit d5e0180805f52ef38a03ff9d6c11dd6174e3526b fixed a similar issue I
> think, discussed at <https://issues.guix.gnu.org/53258>.
>
> Not sure whether it’s a new problem here. Konrad, Maxim, Josselin,
> WDYT? :-)

This problem clearly looks like it's caused by our sitecustomize.py.
One indicator is "When I add both python and a python package": if there
is no additional package, only python by itself, our sitecustomize
doesn't do anything.

However, I don't see how the recent patch (see
https://issues.guix.gnu.org/68241)could be responsible for this new
problem. It should have happened before as well.

Here is what sitecustomize.py does:

1. Collect the "site-packages" subdirectories of everything on
$GUIX_PYTHONPATH.
2. Normalize them via sys.normpath()
3. Add them to sys.path
4. Re-arrange the elements in sys.path such that the add-on
packages come before Python's standard library.

The recent patch fixes a bug in the last step, which wasn't executed at
all (and generated an error message). So the difference between the
current and the previous behavior is only the order of entries in
sys.path.

The current problem is that even the standard library's paths are wrong.
I suspect that this is due to sys.normpath not implementing the correct
POSIX semantics for dot-dot.

Cheers,
Konrad.
Konrad Hinsen wrote 5 months ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Rutherther)(address . rutherther@protonmail.com)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
m1jzeq4sw3.fsf@fastmail.net
Konrad Hinsen <konrad.hinsen@fastmail.net> writes:

Toggle quote (5 lines)
> This problem clearly looks like it's caused by our sitecustomize.py.
> One indicator is "When I add both python and a python package": if there
> is no additional package, only python by itself, our sitecustomize
> doesn't do anything.

I have changed my mind. In the sys.path outputs shown, there are no
paths from add-on packages. It's just the Python standard library.
Maybe our sitecustomize.py is not run at all, but if it is, it didn't do
anything to sys.path. There must be a bug somewhere else.

Cheers,
Konrad.
Konrad Hinsen wrote 5 months ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Rutherther)(address . rutherther@protonmail.com)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
m1bjzxeisd.fsf@fastmail.net
Konrad Hinsen <konrad.hinsen@fastmail.net> writes:

Toggle quote (5 lines)
> I have changed my mind. In the sys.path outputs shown, there are no
> paths from add-on packages. It's just the Python standard library.
> Maybe our sitecustomize.py is not run at all, but if it is, it didn't do
> anything to sys.path. There must be a bug somewhere else.

Our sitecustomize.py is indeed not run at all, so this definitely is a
different problem.

Evidence: Run Rutherther's example, adding the -v option. The long
output is attached, both for "./profile/bin/python3 -v" and "$(realpath
./profile/bin/python3) -v". Search for "site-packages" to find the
interesting parts. If you don't use realpath, large parts of the
initialization are not done.

There are lots of ../../ in the path shown in these log files. If Python
resolves them lexically, as the normpath function does, that would
probably explain most of these issues.

Cheers,
Konrad.
Attachment: with-realpath.log
Ludovic Courtès wrote 5 months ago
(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(name . Rutherther)(address . rutherther@protonmail.com)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
87a5f73pnb.fsf@gnu.org
Hello,

Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:

Toggle quote (20 lines)
> Konrad Hinsen <konrad.hinsen@fastmail.net> writes:
>
>> I have changed my mind. In the sys.path outputs shown, there are no
>> paths from add-on packages. It's just the Python standard library.
>> Maybe our sitecustomize.py is not run at all, but if it is, it didn't do
>> anything to sys.path. There must be a bug somewhere else.
>
> Our sitecustomize.py is indeed not run at all, so this definitely is a
> different problem.
>
> Evidence: Run Rutherther's example, adding the -v option. The long
> output is attached, both for "./profile/bin/python3 -v" and "$(realpath
> ./profile/bin/python3) -v". Search for "site-packages" to find the
> interesting parts. If you don't use realpath, large parts of the
> initialization are not done.
>
> There are lots of ../../ in the path shown in these log files. If Python
> resolves them lexically, as the normpath function does, that would
> probably explain most of these issues.

Ouch. Any idea where to look for solutions here?

Ludo’.
Rutherther wrote 1 months ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
87v7tvfg4e.fsf@ditigal.xyz
Toggle quote (24 lines)
> Hello,
>
> Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:
>
>> Konrad Hinsen <konrad.hinsen@fastmail.net> writes:
>>
>>> I have changed my mind. In the sys.path outputs shown, there are no
>>> paths from add-on packages. It's just the Python standard library.
>>> Maybe our sitecustomize.py is not run at all, but if it is, it didn't do
>>> anything to sys.path. There must be a bug somewhere else.
>>
>> Our sitecustomize.py is indeed not run at all, so this definitely is a
>> different problem.
>>
>> Evidence: Run Rutherther's example, adding the -v option. The long
>> output is attached, both for "./profile/bin/python3 -v" and "$(realpath
>> ./profile/bin/python3) -v". Search for "site-packages" to find the
>> interesting parts. If you don't use realpath, large parts of the
>> initialization are not done.
>>
>> There are lots of ../../ in the path shown in these log files. If Python
>> resolves them lexically, as the normpath function does, that would
>> probably explain most of these issues.

I am not sure I understand this right. I am looking at the output, and
it has `/tmp/b/profile/bin/../../hash-python-3.10.7R/{rest}`, omitting
the gnu/store even here. Why is it significant how these paths are
evaluated, if there is the gnu/store part missing already?

Regards,
Rutherther
Rutherther wrote 1 months ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)
87seozfb2t.fsf@ditigal.xyz
"Rutherther" <rutherther@protonmail.com> writes:

Toggle quote (32 lines)
>> Hello,
>>
>> Konrad Hinsen <konrad.hinsen@fastmail.net> skribis:
>>
>>> Konrad Hinsen <konrad.hinsen@fastmail.net> writes:
>>>
>>>> I have changed my mind. In the sys.path outputs shown, there are no
>>>> paths from add-on packages. It's just the Python standard library.
>>>> Maybe our sitecustomize.py is not run at all, but if it is, it didn't do
>>>> anything to sys.path. There must be a bug somewhere else.
>>>
>>> Our sitecustomize.py is indeed not run at all, so this definitely is a
>>> different problem.
>>>
>>> Evidence: Run Rutherther's example, adding the -v option. The long
>>> output is attached, both for "./profile/bin/python3 -v" and "$(realpath
>>> ./profile/bin/python3) -v". Search for "site-packages" to find the
>>> interesting parts. If you don't use realpath, large parts of the
>>> initialization are not done.
>>>
>>> There are lots of ../../ in the path shown in these log files. If Python
>>> resolves them lexically, as the normpath function does, that would
>>> probably explain most of these issues.
>
> I am not sure I understand this right. I am looking at the output, and
> it has `/tmp/b/profile/bin/../../hash-python-3.10.7R/{rest}`, omitting
> the gnu/store even here. Why is it significant how these paths are
> evaluated, if there is the gnu/store part missing already?
>
> Regards,
> Rutherther

Okay, I spent a bit of time on this, and I think I get it now.
This seems to boil down to something in Python wrongly handling
the argv0, where it looks at the path, being /tmp/a/profile/bin/python3,
substitutes the symlink /tmp/a/profile/bin/python3/../../hash-python-3.10.7/bin/python3, and then
probably calls something like normpath on it, and it becomes
/tmp/a/hash-python-3.10.7. Whereas the correct approach is to first get
the actual path /tmp/a/profile/bin/python3 is at, being
/tmp/a/gnu/store/hash-python-3.10.7R/bin/python3, and unwrap the symlink
from there. This happens even if python3 is called from PATH, I suppose
Python then looks through PATH and again finds the python3 file outside
of the store.

As a workaround,
Toggle diff (50 lines)
diff --git a/gnu/packages/aux-files/run-in-namespace.c b/gnu/packages/aux-files/run-in-namespace.c
index 074befde46..5ce8032ed8 100644
--- a/gnu/packages/aux-files/run-in-namespace.c
+++ b/gnu/packages/aux-files/run-in-namespace.c
@@ -654,6 +654,11 @@ main (int argc, char *argv[])
assert (size > 0);
self[size] = '\0';
+ for (int i = 0; i < argc; i++) {
+ printf("%s\n", argv[i]);
+ }
+ argv[0] = "@WRAPPED_PROGRAM@";
+
/* SELF is something like "/home/ludo/.local/gnu/store/…-foo/bin/ls" and we
want to extract "/home/ludo/.local/gnu/store". */
size_t index = strlen (self)
diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm
index 7f5a5f2aa7..f73d92b678 100644
--- a/guix/scripts/pack.scm
+++ b/guix/scripts/pack.scm
@@ -1343,7 +1343,20 @@ (define* (wrapped-package package
(+ (string-length (%store-directory))
1)))))
(mkdir-p (dirname result))
- (apply invoke #$compiler "-std=gnu99" "-static" "-Os" "-g0" "-Wall"
+ (call-with-output-file (string-append result ".comp")
+ (lambda (port)
+ (format port
+ (apply string-append #$compiler "-std=gnu99" "-O0" "-g" "-Wall"
+ "run.c" "-o" result
+ (string-append "-DWRAPPER_PROGRAM=\""
+ (canonicalize-path (dirname result)) "/"
+ (basename result) "\"")
+ (append (if proot
+ (list (string-append "-DPROOT_PROGRAM=\""
+ proot "\""))
+ '())
+ (elf-loader-compile-flags program))) )))
+ (apply invoke #$compiler "-std=gnu99" "-O0" "-g" "-Wall"
"run.c" "-o" result
(string-append "-DWRAPPER_PROGRAM=\""
(canonicalize-path (dirname result)) "/"
@@ -1353,6 +1366,7 @@ (define* (wrapped-package package
proot "\""))
'())
(elf-loader-compile-flags program)))
+ (copy-file "run.c" (string-append result ".run.c"))
(delete-file "run.c")))
(setvbuf (current-output-port) 'line)
Maxim Cournoyer wrote 1 months ago
(name . Rutherther)(address . rutherther@protonmail.com)(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 73304@debbugs.gnu.org)(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(name . Josselin Poiret)(address . dev@jpoiret.xyz)
877c6bnla5.fsf@gmail.com
Hi,

Rutherther <rutherther@protonmail.com> writes:

[...]

Toggle quote (14 lines)
> Okay, I spent a bit of time on this, and I think I get it now.
> This seems to boil down to something in Python wrongly handling
> the argv0, where it looks at the path, being /tmp/a/profile/bin/python3,
> substitutes the symlink /tmp/a/profile/bin/python3/../../hash-python-3.10.7/bin/python3, and then
> probably calls something like normpath on it, and it becomes
> /tmp/a/hash-python-3.10.7. Whereas the correct approach is to first get
> the actual path /tmp/a/profile/bin/python3 is at, being
> /tmp/a/gnu/store/hash-python-3.10.7R/bin/python3, and unwrap the symlink
> from there. This happens even if python3 is called from PATH, I suppose
> Python then looks through PATH and again finds the python3 file outside
> of the store.
>
> As a workaround,

The workaround looks smart (too smart for my tired brain tonight), but
to be honest I'd rather have Python handle the relative paths correctly,
or work around it in our sitecustomize.py script that runs early when
Python runs. I doubt submitting a patch fixing this in Python will be
accepted, for backward compatibility reasons (I think Josselin had done
so already). Looking back for it, I've seen reports of the issue going
back to 2008 [0], and a more recent one in 2021 [1]:


It seems using realpath wouldperhaps do the right thing instead of using
normpath? It resolves symlinks, appears to conform to POSIX. See some
sample output from [2].


--
Thanks,
Maxim
Konrad Hinsen wrote 1 months ago
(name . Maxim Cournoyer)(address . maxim.cournoyer@gmail.com)(name . Rutherther)(address . rutherther@protonmail.com)(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)
m17c6bhy1z.fsf@fastmail.net
Hi,

Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:

Toggle quote (4 lines)
> The workaround looks smart (too smart for my tired brain tonight), but
> to be honest I'd rather have Python handle the relative paths correctly,
> or work around it in our sitecustomize.py script that runs early when

That's indeed preferable, but according to my analysis not possible, as
there are situations of faulty startup behavior in which out
sitecustomize.py is not run at all.

What we can envisage is a combination of
1. patching Python
2. using realpath rather than normpath in our sitecustomize.py

Cheers,
Konrad.
Maxim Cournoyer wrote 1 months ago
(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(name . Rutherther)(address . rutherther@protonmail.com)(name . Ludovic Courtè s)(address . ludo@gnu.org)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)
87y0yrm0li.fsf@gmail.com
Hi Konrad,

Konrad Hinsen <konrad.hinsen@fastmail.net> writes:

Toggle quote (12 lines)
> Hi,
>
> Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:
>
>> The workaround looks smart (too smart for my tired brain tonight), but
>> to be honest I'd rather have Python handle the relative paths correctly,
>> or work around it in our sitecustomize.py script that runs early when
>
> That's indeed preferable, but according to my analysis not possible, as
> there are situations of faulty startup behavior in which out
> sitecustomize.py is not run at all.

I think I had read this from you before but I hadn't grasped how that's
possible/when it occurs. Do yo have a link, or refresher?

Toggle quote (4 lines)
> What we can envisage is a combination of
> 1. patching Python
> 2. using realpath rather than normpath in our sitecustomize.py

I hope we could get by with just 2.

--
Thanks,
Maxim
Maxim Cournoyer wrote 1 months ago
(name . Konrad Hinsen)(address . konrad.hinsen@fastmail.net)(name . Rutherther)(address . rutherther@protonmail.com)(name . Ludovic Courtè s)(address . ludo@gnu.org)(address . 73304@debbugs.gnu.org)(name . Josselin Poiret)(address . dev@jpoiret.xyz)
87tt9fm0c7.fsf@gmail.com
Hi,

[...]

Toggle quote (13 lines)
>> That's indeed preferable, but according to my analysis not possible, as
>> there are situations of faulty startup behavior in which out
>> sitecustomize.py is not run at all.
>
> I think I had read this from you before but I hadn't grasped how that's
> possible/when it occurs. Do yo have a link, or refresher?
>
>> What we can envisage is a combination of
>> 1. patching Python
>> 2. using realpath rather than normpath in our sitecustomize.py
>
> I hope we could get by with just 2.

I've just reread the original message in this thread/issue, and it has a
reproducer demonstrating the problem. If Python itself breaks the
symlinks paths before it even gets to run our sitecustomize.py, then
yes, we'd need a fix on the Python side.

I guess we should revisit this issue upstream (perhaps some are still
opened), show our broken use case, and discuss a solution with them?

--
Thanks,
Maxim
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send an email to 73304@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 73304
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch
You may also tag this issue. See list of standard tags. For example, to set the confirmed and easy tags
mumi command -t +confirmed -t +easy
Or, remove the moreinfo tag and set the help tag
mumi command -t -moreinfo -t +help