calibre-uninstall doesn't run on Ubuntu 20.04

Bug #1876164 reported by Junaid Ahmed on 2020-04-30
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
calibre
Undecided
Unassigned

Bug Description

Calibre is installed using the command as per stated in official website-

"sudo -v && wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sudo sh /dev/stdin"

The "calibre-uninstall" file successfully generates in /bin
But running "sudo calibre-uninstall" returns error- "No such file or directory".
Opening the "calibre-uninstall" file with text-editor reveals that the file lists the address of python in "/usr/bin/python". There is no longer a "python" file in "/usr/bin" on a freshly installed Ubuntu 20.04, it has been replaced by the file "python3".
Editing the "calibre-uninstall" file to rename the package as "python3" works and uninstall process completes without any error.
Requesting appropriate change(s).

description: updated
description: updated
description: updated

The linux-installer.py script has already been switched for Ubuntu's
convenience to be a shellscript that repeatedly tries to find various
interpreters. So that's one option.

Maybe, however, it would be better to make calibre.linux:PostInstall
accept another argument, which linux-installer.py would populate as

pi.extend(['--python-cmd', sys.executable])

This would ensure that whichever python command was used when
linux-installer.sh probed for a suitable $PYTHON to run its integrated
heredoc, was also embedded into the calibre-uninstall program.

setup/install.py could make opts.python_cmd default to sys.executable
for from-source builds, and for the case where someone uses an isolated
install of the binary build, then later runs calibre_postinstall, they
can either manually specify it or let it assume /usr/bin/python.

@Eli: Not sure that is the best approach. What if sys.executable points
to something like /usr/bin/python3.7 then it will break if python is
upgraded. Might be better to point to the installed path of
calibre-debug which can run python scripts.

Kovid Goyal (kovid) wrote :

The problem with that is we dont know where calibre-debug will be
installed, so the best we can do is hope it is in the path.

Maybe best to just wrap the uninstaller is a .sh like we do for the
installer, and send Canonical the bill for my time wasted.

Apparently in commit ddca079000ffd03611d19c5dfe29341b9c1c6e2e it was
changed from using sys.executable in the postinstall script itself due
to bug 1283154

Which I suppose is... understandable as it seemed to be the
bin/calibre_postinstall program? calibre-debug itself should work, I
suppose, as long as it's the right one...

Use of calibre-debug as a script interpreter is indeed a good point.

Eli Schwartz (eschwartz) wrote :

Nah, sure you know where the calibre-debug program is installed. It's
used to create symlinks on frozen builds (this whole codepath is only
run when sys.frozen_path exists, so getattr seems unneeded):

tgt = os.path.join(getattr(sys, 'frozen_path'), exe)
self.info('\tSymlinking %s to %s'%(tgt, dest))

So calibre-debug on frozen builds can be guaranteed to be at

os.path.join(sys.frozen_path, 'calibre-debug')

For non-frozen builds opts.bindir should have this passed along from
setup/install.py

Still, I think I prefer to have the uninstaller independent of the rest
of calibre, in case of corrupted installs, or similar.

Fixed in branch master. The fix will be in the next release. calibre is usually released every alternate Friday.

 status fixreleased

Changed in calibre:
status: New → Fix Released

Note that because shell scripts are *wonderful*, you cannot rely on $0
being the path to the calibre-uninstall script (programs are freely
permitted to define their own argv0), and in some cases it won't be
deleted properly (although everything else will be).

e.g. one way to *accidentally* trigger this is with

bash calibre-uninstall

$0 will be 'calibre-uninstall', bash detects the program on $PATH, but
it's not relative to ./ and you cannot trace it back to the original
source file, so the uninstaller doesn't get detected as existing.

The bash-specific equivalent of `__file__` is ${BASH_SOURCE[0]} which
has nothing to do with argv0 and does, in fact, explicitly refer to the
filename of the file which is currently being parsed, but /bin/sh has
*no* way of detecting this. None. Period. It cannot be done.

(In order to break BASH_SOURCE you need to do something like:
`cat /usr/bin/calibre-uninstall | bash`, which would break python
`__file__` too.)

It's *probably* okay to say "if you find yourself invoking the
calibre-uninstall program in some way that lies about $0, you deserve to
not have it uninstalled with the rest".

Just thought you might be interested in adding to the list of
frustrations to bill Canonical for. :)

Yeah, I know, but since there is no a-priori reason to run
calibre-uninstall as anything but calibre-uninstall, I am ok with
it being a little fragile.

description: updated
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers